#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
const long long mod = 1e9 + 7;
int n, m;
long long a[maxn];
struct Matrix {
  long long a[2][2];
  Matrix() { memset(a, 0, sizeof(a)); }
  Matrix operator+(const Matrix M) {
    Matrix ans;
    for (long long i = 0; i <= 1; i++)
      for (long long j = 0; j <= 1; j++)
        ans.a[i][j] = (a[i][j] + M.a[i][j]) % mod;
    return ans;
  }
  Matrix operator*(const Matrix y) {
    Matrix ans;
    for (int i = 0; i <= 1; i++)
      for (int j = 0; j <= 1; j++)
        for (int k = 0; k <= 1; k++) ans.a[i][j] += a[i][k] * y.a[k][j];
    for (int i = 0; i <= 1; i++)
      for (int j = 0; j <= 1; j++) ans.a[i][j] %= mod;
    return ans;
  }
};
Matrix tmp;
Matrix solve(long long x) {
  Matrix ans, trs;
  ans.a[0][0] = ans.a[1][1] = 1;
  trs.a[0][0] = trs.a[1][0] = trs.a[0][1] = 1;
  while (x) {
    if (x & 1) ans = ans * trs;
    trs = trs * trs;
    x >>= 1;
  }
  return ans;
}
struct Node {
  int rt, l, r, flag;
  Matrix m, add;
} cover[maxn << 3];
void pushdown(int rt) {
  if (cover[rt].flag) {
    cover[rt].flag = 0;
    cover[rt << 1].flag = cover[rt << 1 | 1].flag = 1;
    cover[rt << 1].m = cover[rt].add * cover[rt << 1].m;
    cover[rt << 1 | 1].m = cover[rt].add * cover[rt << 1 | 1].m;
    cover[rt << 1].add = cover[rt].add * cover[rt << 1].add;
    cover[rt << 1 | 1].add = cover[rt].add * cover[rt << 1 | 1].add;
    cover[rt].add.a[0][0] = cover[rt].add.a[1][1] = 1;
    cover[rt].add.a[0][1] = cover[rt].add.a[1][0] = 0;
  }
}
void pushup(int rt) {
  for (int i = 0; i <= 1; i++)
    for (int j = 0; j <= 1; j++)
      cover[rt].m.a[i][j] =
          (cover[rt << 1].m.a[i][j] + cover[rt << 1 | 1].m.a[i][j]) % mod;
}
void build(int rt, int l, int r) {
  cover[rt].l = l;
  cover[rt].r = r;
  cover[rt].flag = 0;
  cover[rt].add.a[0][0] = cover[rt].add.a[1][1] = 1;
  cover[rt].add.a[0][1] = cover[rt].add.a[1][0] = 0;
  if (l == r) {
    cover[rt].m = solve(a[l]) * tmp;
    return;
  }
  int m = (l + r) / 2;
  build(rt << 1, l, m);
  build(rt << 1 | 1, m + 1, r);
  pushup(rt);
}
void update(int rt, int qstart, int qend, Matrix x) {
  pushdown(rt);
  if (cover[rt].l >= qstart && cover[rt].r <= qend) {
    cover[rt].flag = 1;
    cover[rt].m = cover[rt].m * x;
    cover[rt].add = cover[rt].add * x;
    return;
  }
  int m = (cover[rt].l + cover[rt].r) / 2;
  if (qstart <= m) update(rt << 1, qstart, qend, x);
  if (m < qend) update(rt << 1 | 1, qstart, qend, x);
  pushup(rt);
}
Matrix query(int rt, int qstart, int qend) {
  if (cover[rt].l >= qstart && cover[rt].r <= qend) {
    return cover[rt].m;
  }
  pushdown(rt);
  Matrix ans;
  int m = (cover[rt].l + cover[rt].r) / 2;
  if (qstart <= m) ans = query(rt << 1, qstart, qend);
  if (m < qend) ans = ans + query(rt << 1 | 1, qstart, qend);
  return ans;
}
int main() {
  ios::sync_with_stdio(false);
  tmp.a[0][0] = 1;
  tmp.a[0][1] = -1;
  tmp.a[1][0] = -1;
  tmp.a[1][1] = 2;
  cin >> n >> m;
  for (int i = 1; i <= n; i++) cin >> a[i];
  build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    long long x;
    int flag, l, r;
    cin >> flag;
    if (flag == 1) {
      cin >> l >> r >> x;
      Matrix ma = solve(x);
      update(1, l, r, ma);
    } else {
      cin >> l >> r;
      Matrix ans = query(1, l, r);
      cout << ((ans.a[0][0] + ans.a[0][1]) % mod + mod) % mod << endl;
    }
  }
  return 0;
}
