#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;
struct matrix {
 public:
  long long mat[2][2];
  matrix() {
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++) mat[i][j] = 0;
  }
  matrix(int _a, int _b, int _c, int _d) {
    mat[0][0] = _a;
    mat[0][1] = _b;
    mat[1][0] = _c;
    mat[1][1] = _d;
  }
  matrix operator-(const matrix a) {
    matrix temp;
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++)
        for (int k = 0; k < 2; k++) {
          temp.mat[i][j] += (mat[i][k] * a.mat[k][j]);
        }
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++) temp.mat[i][j] %= MOD;
    return temp;
  }
  matrix operator*(const matrix a) {
    matrix temp;
    temp.mat[0][0] = (mat[0][0] * a.mat[0][0] + mat[0][1] * a.mat[1][0]) % MOD;
    temp.mat[1][0] = (mat[1][0] * a.mat[0][0] + mat[1][1] * a.mat[1][0]) % MOD;
    return temp;
  }
  matrix operator+(const matrix a) {
    matrix temp;
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2; j++) {
        temp.mat[i][j] = (mat[i][j] + a.mat[i][j]);
        if (temp.mat[i][j] >= MOD) temp.mat[i][j] -= MOD;
      }
    }
    return temp;
  }
  void Set(int _a, int _b, int _c, int _d) {
    mat[0][0] = _a;
    mat[0][1] = _b;
    mat[1][0] = _c;
    mat[1][1] = _d;
  }
  void print() {
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2; j++) cout << mat[i][j] << ' ';
      cout << endl;
    }
  }
};
matrix b[64];
inline void MatMul(matrix &a, long long p) {
  int in = 0;
  while (p) {
    if (p & 1) a = b[in] * a;
    p = p >> 1;
    in++;
  }
}
int n, m;
int ara[100005];
matrix tree[400005];
long long lazy[400005];
inline void updateRange(int node, int start, int end, int l, int r, int val) {
  if (lazy[node] != 0) {
    MatMul(tree[node], lazy[node]);
    if (start != end) {
      lazy[node * 2] += lazy[node];
      lazy[node * 2 + 1] += lazy[node];
    }
    lazy[node] = 0;
  }
  if (start > end or start > r or end < l) return;
  if (start >= l and end <= r) {
    MatMul(tree[node], val);
    if (start != end) {
      lazy[node * 2] += val;
      lazy[node * 2 + 1] += val;
    }
    return;
  }
  long long mid = (start + end) / 2;
  updateRange(node * 2, start, mid, l, r, val);
  updateRange(node * 2 + 1, mid + 1, end, l, r, val);
  tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
inline matrix queryRange(long long node, long long start, long long end,
                         long long l, long long r) {
  if (start > end or start > r or end < l) return matrix(0, 0, 0, 0);
  if (lazy[node] != 0) {
    MatMul(tree[node], lazy[node]);
    if (start != end) {
      lazy[node * 2] += lazy[node];
      lazy[node * 2 + 1] += lazy[node];
    }
    lazy[node] = 0;
  }
  if (start >= l and end <= r) return tree[node];
  long long mid = (start + end) / 2;
  matrix p1 = queryRange(node * 2, start, mid, l, r);
  matrix p2 = queryRange(node * 2 + 1, mid + 1, end, l, r);
  return (p1 + p2);
}
int main() {
  matrix B(1, 1, 1, 0);
  b[0].Set(1, 1, 1, 0);
  for (int i = 1; i <= 64; i++) {
    b[i] = b[i - 1] - b[i - 1];
  }
  for (int i = 1; i <= 400000; i++) tree[i] = matrix(1, 0, 0, 0);
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= n; i++) scanf("%d", &ara[i]);
  for (int i = 1; i <= n; i++) updateRange(1, 1, n, i, i, ara[i]);
  while (m--) {
    int tp;
    scanf("%d", &tp);
    if (tp == 1) {
      int l, r, x;
      scanf("%d %d %d", &l, &r, &x);
      updateRange(1, 1, n, l, r, x);
    } else {
      int l, r;
      scanf("%d %d", &l, &r);
      matrix ans = queryRange(1, 1, n, l, r);
      printf("%lld\n", ans.mat[1][0]);
    }
  }
}
