#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
const long long maxn = 1e5 + 12, MOD = (1e9 + 7);
long long n, m;
long long a[maxn];
struct Matrix {
  long long a[2][2];
  Matrix() { a[0][0] = a[0][1] = a[1][0] = a[1][1] = 0; }
  Matrix operator*(const Matrix B) {
    Matrix ret;
    ret.a[0][0] =
        (((B.a[0][0] * a[0][0]) % MOD) + (B.a[0][1] * a[1][0]) % MOD) % MOD;
    ret.a[0][1] =
        (((B.a[0][0] * a[0][1]) % MOD) + (B.a[0][1] * a[1][1]) % MOD) % MOD;
    ret.a[1][0] =
        (((B.a[1][0] * a[0][0]) % MOD) + (B.a[1][1] * a[1][0]) % MOD) % MOD;
    ret.a[1][1] =
        (((B.a[1][0] * a[0][1]) % MOD) + (B.a[1][1] * a[1][1]) % MOD) % MOD;
    return ret;
  }
  Matrix operator+(const Matrix B) {
    Matrix ret;
    for (long long i = 0; i < 2; i++)
      for (long long j = 0; j < 2; j++)
        ret.a[i][j] = (a[i][j] + B.a[i][j]) % MOD;
    return ret;
  }
};
Matrix FIB, emp;
Matrix B[maxn], seg[4 * maxn], lazy[4 * maxn];
Matrix Pow(Matrix A, long long p) {
  if (p == 1) return FIB;
  Matrix B = Pow(A, p / 2);
  B = B * B;
  if (p % 2) B = B * A;
  return B;
}
void init();
void BIULD(long long id, long long l, long long r, long long idx, Matrix val);
void QUERYS();
void add(long long id, long long l, long long r, long long st, long long en,
         Matrix val);
void shift(long long id, long long l, long long r);
Matrix get(long long id, long long l, long long r, long long st, long long en);
int32_t main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  init();
  QUERYS();
}
void init() {
  FIB.a[0][0] = FIB.a[0][1] = FIB.a[1][0] = 1;
  for (long long i = 0; i < 4 * maxn; i++) {
    lazy[i].a[0][0] = lazy[i].a[1][1] = 1;
    seg[i] = lazy[i];
  }
  cin >> n >> m;
  for (long long i = 0; i < n; i++) {
    cin >> a[i];
    B[i] = Pow(FIB, a[i]);
    BIULD(1, 0, n, i, B[i]);
  }
  return;
}
void BIULD(long long id, long long l, long long r, long long idx, Matrix val) {
  if (idx < l || idx >= r) return;
  if (l == r - 1) {
    seg[id] = seg[id] * val;
    return;
  }
  long long mid = (l + r) >> 1;
  BIULD(id * 2 + 0, l, mid, idx, val);
  BIULD(id * 2 + 1, mid, r, idx, val);
  seg[id] = seg[id * 2 + 0] + seg[id * 2 + 1];
  return;
}
void QUERYS() {
  while (m--) {
    long long T, l, r, x;
    cin >> T >> l >> r;
    if (T == 1) {
      cin >> x;
      Matrix X = Pow(FIB, x);
      add(1, 0, n, l - 1, r, X);
      continue;
    }
    Matrix X = get(1, 0, n, l - 1, r);
    cout << X.a[1][0] << '\n';
  }
  return;
}
void add(long long id, long long l, long long r, long long st, long long en,
         Matrix val) {
  shift(id, l, r);
  if (en <= l || st >= r) return;
  if (st <= l && r <= en) {
    seg[id] = seg[id] * val;
    lazy[id] = lazy[id] * val;
    return;
  }
  long long mid = (l + r) >> 1;
  add(id * 2 + 0, l, mid, st, en, val);
  add(id * 2 + 1, mid, r, st, en, val);
  seg[id] = seg[id * 2 + 0] + seg[id * 2 + 1];
  return;
}
void shift(long long id, long long l, long long r) {
  Matrix X = lazy[id];
  lazy[id].a[0][0] = lazy[id].a[1][1] = 1;
  lazy[id].a[1][0] = lazy[id].a[0][1] = 0;
  if (l == r - 1) return;
  seg[id * 2 + 0] = seg[id * 2 + 0] * X;
  seg[id * 2 + 1] = seg[id * 2 + 1] * X;
  lazy[id * 2 + 0] = lazy[id * 2 + 0] * X;
  lazy[id * 2 + 1] = lazy[id * 2 + 1] * X;
  return;
}
Matrix get(long long id, long long l, long long r, long long st, long long en) {
  if (en <= l || r <= st) return emp;
  shift(id, l, r);
  if (st <= l && r <= en) {
    return seg[id];
  }
  long long mid = (l + r) >> 1;
  return get(id * 2 + 0, l, mid, st, en) + get(id * 2 + 1, mid, r, st, en);
}
