#include <bits/stdc++.h>
using namespace std;
const int Q = 1e9 + 7;
int sum(int a, int b) { return a + b >= Q ? a + b - Q : a + b; }
int mul(int a, int b) { return (int)((1LL * a * b) % Q); }
struct matrix {
  int a[2][2];
  matrix() {
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++) a[i][j] = 0;
  }
};
matrix mul(matrix &A, matrix &B) {
  matrix C;
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        C.a[i][j] = sum(C.a[i][j], mul(A.a[i][k], B.a[k][j]));
      }
    }
  }
  return C;
}
matrix pow(matrix &x, long long y) {
  if (y == 1) return x;
  matrix tmp = pow(x, y / 2);
  tmp = mul(tmp, tmp);
  if (y & 1) tmp = mul(tmp, x);
  return tmp;
}
int f(long long x) {
  x--;
  if (x <= 1) return 1;
  matrix A;
  A.a[0][0] = 1;
  A.a[0][1] = 1;
  A.a[1][0] = 1;
  A.a[1][1] = 0;
  matrix Ax = pow(A, x);
  return Ax.a[0][0];
}
const int M = 1e5 + 10;
matrix tree[4 * M];
matrix d[4 * M];
int a[M];
matrix E;
void build(int i, int L, int R) {
  d[i] = E;
  if (L == R - 1) {
    tree[i].a[0][0] = f(a[L]);
    tree[i].a[0][1] = f(a[L] + 1);
    return;
  }
  build(2 * i + 1, L, (L + R) / 2);
  build(2 * i + 2, (L + R) / 2, R);
  tree[i].a[0][0] = sum(tree[2 * i + 1].a[0][0], tree[2 * i + 2].a[0][0]);
  tree[i].a[0][1] = sum(tree[2 * i + 1].a[0][1], tree[2 * i + 2].a[0][1]);
}
void push(int i) {
  d[2 * i + 1] = mul(d[2 * i + 1], d[i]);
  d[2 * i + 2] = mul(d[2 * i + 2], d[i]);
  tree[2 * i + 1] = mul(tree[2 * i + 1], d[i]);
  tree[2 * i + 2] = mul(tree[2 * i + 2], d[i]);
  d[i] = E;
}
void upd(int i, int L, int R, int l, int r, matrix &x) {
  if (R <= l || r <= L) return;
  if (l <= L && R <= r) {
    d[i] = mul(d[i], x);
    tree[i] = mul(tree[i], x);
    return;
  }
  push(i);
  upd(2 * i + 1, L, (L + R) / 2, l, r, x);
  upd(2 * i + 2, (L + R) / 2, R, l, r, x);
  tree[i].a[0][0] = sum(tree[2 * i + 1].a[0][0], tree[2 * i + 2].a[0][0]);
  tree[i].a[0][1] = sum(tree[2 * i + 1].a[0][1], tree[2 * i + 2].a[0][1]);
}
int get(int i, int L, int R, int l, int r) {
  if (R <= l || r <= L) return 0;
  if (l <= L && R <= r) return tree[i].a[0][0];
  push(i);
  return sum(get(2 * i + 1, L, (L + R) / 2, l, r),
             get(2 * i + 2, (L + R) / 2, R, l, r));
}
int main() {
  srand(time(NULL));
  E.a[0][0] = 1;
  E.a[1][0] = 0;
  E.a[1][1] = 1;
  E.a[0][1] = 0;
  for (int i = 1; i < 10; i++) {
    cerr << f(i) << endl;
    ;
  }
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < n; i++) cin >> a[i];
  build(0, 0, n);
  for (int i = 0; i < m; i++) {
    int tp, l, r;
    cin >> tp >> l >> r;
    l--;
    if (tp == 2) {
      cout << get(0, 0, n, l, r) << "\n";
    } else {
      int x;
      cin >> x;
      matrix k;
      k.a[0][0] = 0;
      k.a[0][1] = 1;
      k.a[1][0] = 1;
      k.a[1][1] = 1;
      matrix st = pow(k, x);
      upd(0, 0, n, l, r, st);
    }
  }
  fprintf(stderr, "TIME: %.3f\n", 1.0 * clock() / CLOCKS_PER_SEC);
  return 0;
}
