#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
struct node {
  long long a[2][2];
  void init() { memset(a, 0, sizeof(a)); }
  void one() {
    init();
    a[0][0] = a[1][1] = 1;
  }
};
node add(node A, node B) {
  node C;
  C.init();
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      C.a[i][j] = (A.a[i][j] + B.a[i][j]) % mod;
    }
  }
  return C;
}
node mul(node A, node B) {
  node C;
  C.init();
  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] = (C.a[i][j] + A.a[i][k] * B.a[k][j]) % mod;
      }
    }
  }
  return C;
}
node pow(int p) {
  node A;
  A.a[0][0] = 0;
  A.a[0][1] = 1;
  A.a[1][0] = 1;
  A.a[1][1] = 1;
  node res;
  res.one();
  while (p) {
    if (p % 2) res = mul(res, A);
    A = mul(A, A);
    p >>= 1;
  }
  return res;
}
int a[maxn];
struct SegmentTree {
  int l, r, flag;
  node sum, lazy;
  void update(node v) {
    sum = mul(sum, v);
    lazy = mul(lazy, v);
    flag = 1;
  }
} Tree[maxn << 2];
void pushup(int rt) {
  Tree[rt].sum = add(Tree[rt * 2].sum, Tree[rt * 2 + 1].sum);
}
void pushdown(int rt) {
  if (Tree[rt].flag) {
    Tree[rt * 2].update(Tree[rt].lazy);
    Tree[rt * 2 + 1].update(Tree[rt].lazy);
    Tree[rt].flag = 0;
    Tree[rt].lazy.one();
  }
}
void Build(int l, int r, int rt) {
  Tree[rt].l = l, Tree[rt].r = r, Tree[rt].sum.init(), Tree[rt].lazy.one(),
  Tree[rt].flag = 0;
  if (l == r) {
    Tree[rt].sum = pow(a[l]);
    return;
  }
  int mid = (l + r) / 2;
  Build(l, mid, rt * 2);
  Build(mid + 1, r, rt * 2 + 1);
  pushup(rt);
}
void update(int L, int R, node v, int rt) {
  if (L <= Tree[rt].l && Tree[rt].r <= R) {
    Tree[rt].update(v);
    return;
  } else {
    pushdown(rt);
    int mid = (Tree[rt].l + Tree[rt].r) / 2;
    if (L <= mid) update(L, R, v, rt * 2);
    if (mid < R) update(L, R, v, rt * 2 + 1);
    pushup(rt);
  }
}
node queryans(int L, int R, int rt) {
  if (L <= Tree[rt].l && Tree[rt].r <= R) {
    return Tree[rt].sum;
  } else {
    pushdown(rt);
    int mid = (Tree[rt].l + Tree[rt].r) / 2;
    node res;
    res.init();
    if (L <= mid) res = add(res, queryans(L, R, rt * 2));
    if (mid < R) res = add(res, queryans(L, R, rt * 2 + 1));
    pushup(rt);
    return res;
  }
}
int n, q;
int main() {
  while (scanf("%d%d", &n, &q) != EOF) {
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    Build(1, n, 1);
    for (int i = 1; i <= q; i++) {
      int op;
      scanf("%d", &op);
      if (op == 2) {
        int l, r;
        scanf("%d%d", &l, &r);
        printf("%lld\n", queryans(l, r, 1).a[1][0]);
      } else {
        int l, r, v;
        scanf("%d%d%d", &l, &r, &v);
        update(l, r, pow(v), 1);
      }
    }
  }
  return 0;
}
