#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 50;
const int mod = 1e9 + 7;
unsigned long long k1, k2;
unsigned long long xorShift128Plus() {
  unsigned long long k3 = k1, k4 = k2;
  k1 = k4;
  k3 ^= k3 << 23;
  k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
  return k2 + k4;
}
inline int mul(long long a, int b) {
  a *= b;
  return a % mod;
}
inline int add(int a, int b) {
  a += b;
  if (a >= mod) a -= mod;
  return a;
}
struct mat {
  int a[2][2];
  void init() {
    a[0][0] = a[1][1] = 1;
    a[0][1] = a[1][0] = 0;
  }
  mat operator*(mat &c) {
    mat b;
    memset(b.a, 0, sizeof(b.a));
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++)
        for (int k = 0; k < 2; k++)
          b.a[i][j] = add(b.a[i][j], mul(a[i][k], c.a[k][j]));
    return b;
  }
  void print() {
    cout << "MAT::" << endl;
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2; j++) cout << a[i][j] << ' ';
      cout << endl;
    }
  }
};
int a[N << 2][2], b[N], t1, t2;
mat lazy[N << 2];
mat m;
mat qp(mat a, long long b) {
  mat res;
  res.init();
  if (b < 0) return res;
  while (b) {
    if (b & 1LL) res = res * a;
    a = a * a;
    b >>= 1;
  }
  return res;
}
mat I;
inline bool check(mat &c) {
  for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++) {
      if (I.a[i][j] != c.a[i][j]) {
        return true;
      }
    }
  return false;
}
inline void pushup(int rt) {
  a[rt][0] = add(a[rt << 1][0], a[rt << 1 | 1][0]);
  a[rt][1] = add(a[rt << 1][1], a[rt << 1 | 1][1]);
}
inline void pushdown(int rt) {
  if (check(lazy[rt])) {
    lazy[rt << 1] = lazy[rt << 1] * lazy[rt];
    lazy[rt << 1 | 1] = lazy[rt << 1 | 1] * lazy[rt];
    t1 = add(mul(a[rt << 1][0], lazy[rt].a[0][0]),
             mul(a[rt << 1][1], lazy[rt].a[1][0]));
    t2 = add(mul(a[rt << 1][0], lazy[rt].a[0][1]),
             mul(a[rt << 1][1], lazy[rt].a[1][1]));
    a[rt << 1][0] = t1;
    a[rt << 1][1] = t2;
    t1 = add(mul(a[rt << 1 | 1][0], lazy[rt].a[0][0]),
             mul(a[rt << 1 | 1][1], lazy[rt].a[1][0]));
    t2 = add(mul(a[rt << 1 | 1][0], lazy[rt].a[0][1]),
             mul(a[rt << 1 | 1][1], lazy[rt].a[1][1]));
    a[rt << 1 | 1][0] = t1, a[rt << 1 | 1][1] = t2;
    lazy[rt] = I;
  }
}
inline void build(int rt, int l, int r) {
  lazy[rt] = I;
  if (l == r) {
    m.a[0][0] = m.a[0][1] = m.a[1][0] = 1;
    m.a[1][1] = 0;
    a[rt][0] = 1;
    a[rt][1] = 0;
    b[l]--;
    m = qp(m, b[l]);
    t1 = add(mul(a[rt][0], m.a[0][0]), mul(a[rt][1], m.a[1][0]));
    t2 = add(mul(a[rt][0], m.a[0][1]), mul(a[rt][1], m.a[1][1]));
    a[rt][0] = t1, a[rt][1] = t2;
    return;
  }
  int mid = (l + r) >> 1;
  build(rt << 1, l, mid);
  build(rt << 1 | 1, mid + 1, r);
  pushup(rt);
}
inline void update(int rt, int l, int r, int x, int y) {
  if (x <= l && r <= y) {
    t1 = add(mul(a[rt][0], m.a[0][0]), mul(a[rt][1], m.a[1][0]));
    t2 = add(mul(a[rt][0], m.a[0][1]), mul(a[rt][1], m.a[1][1]));
    a[rt][0] = t1, a[rt][1] = t2;
    lazy[rt] = lazy[rt] * m;
    return;
  }
  pushdown(rt);
  int mid = (l + r) >> 1;
  if (x <= mid) update(rt << 1, l, mid, x, y);
  if (y > mid) update(rt << 1 | 1, mid + 1, r, x, y);
  pushup(rt);
}
inline int query(int rt, int l, int r, int x, int y) {
  if (x <= l && r <= y) {
    return a[rt][0];
  }
  pushdown(rt);
  int mid = (l + r) >> 1, res = 0;
  if (x <= mid) res = add(res, query(rt << 1, l, mid, x, y));
  if (y > mid) res = add(res, query(rt << 1 | 1, mid + 1, r, x, y));
  pushup(rt);
  return res;
}
inline int read() {
  int s = 0, w = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') w = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
  return s * w;
}
int main() {
  int n, q;
  I.init();
  while (~scanf("%d%d", &n, &q)) {
    for (int i = 1; i <= n; i++) {
      b[i] = read();
    }
    build(1, 1, n);
    int t, l, r, x;
    for (int i = 1; i <= q; i++) {
      t = read();
      if (t & 1) {
        l = read(), r = read(), x = read();
        if (l > r) swap(l, r);
        m.a[0][0] = m.a[0][1] = m.a[1][0] = 1;
        m.a[1][1] = 0;
        m = qp(m, x);
        update(1, 1, n, l, r);
      } else {
        l = read(), r = read();
        if (l > r) swap(l, r);
        printf("%d\n", query(1, 1, n, l, r));
      }
    }
  }
}
