#include <bits/stdc++.h>
#pragma GCC optimize("Ofast", 3, "inline")
using namespace std;
const long long Mod = 1e9 + 7;
const long long MAX_N = 100005;
struct mat {
  long long A[2][2];
  mat() { memset(A, 0, sizeof(A)); }
  long long* operator[](long long i) { return A[i]; }
};
bool operator==(mat a, mat b) {
  for (long long i = 0; i < 2; i++) {
    for (long long j = 0; j < 2; j++) {
      if (a[i][j] != b[i][j]) return false;
    }
  }
  return true;
}
long long n, Q;
mat start, matrix, one;
mat operator+(mat a, mat b) {
  mat c = a;
  for (long long i = 0; i < 2; i++) {
    for (long long j = 0; j < 2; j++) {
      c[i][j] += b[i][j];
      c[i][j] %= Mod;
    }
  }
  return c;
}
mat operator*(mat a, mat b) {
  mat c;
  for (long long i = 0; i < 2; i++) {
    for (long long j = 0; j < 2; j++) {
      for (long long k = 0; k < 2; k++) {
        c[i][j] += a[i][k] * b[k][j];
        c[i][j] %= Mod;
      }
    }
  }
  return c;
}
mat bin_pow(mat a, long long b) {
  mat ret = a;
  b--;
  while (b > 0) {
    if (b % 2) ret = ret * a;
    a = a * a;
    b /= 2;
  }
  return ret;
}
void init() {
  start[0][0] = 1;
  start[0][1] = 0;
  matrix[0][0] = 1;
  matrix[0][1] = 1;
  matrix[1][0] = 1;
  one[0][0] = 1;
  one[1][1] = 1;
}
struct node {
  long long l, r;
  mat data;
  mat tag;
} T[MAX_N << 2];
void pushup(long long rt) {
  if (T[rt].l == T[rt].r) return;
  T[rt].data = T[(rt << 1)].data + T[(rt << 1 | 1)].data;
}
void pushdown(long long rt) {
  if (T[rt].l == T[rt].r) return;
  if (T[rt].tag == one) return;
  T[(rt << 1)].data = T[(rt << 1)].data * T[rt].tag;
  T[(rt << 1)].tag = T[(rt << 1)].tag * T[rt].tag;
  T[(rt << 1 | 1)].data = T[(rt << 1 | 1)].data * T[rt].tag;
  T[(rt << 1 | 1)].tag = T[(rt << 1 | 1)].tag * T[rt].tag;
  T[rt].tag = one;
}
long long A[MAX_N];
void build(long long rt, long long l, long long r) {
  T[rt].l = l;
  T[rt].r = r;
  T[rt].tag = one;
  if (l == r) {
    if (A[l] > 1)
      T[rt].data = start * bin_pow(matrix, A[l] - 1);
    else
      T[rt].data = start;
    return;
  }
  long long mid = (l + r) / 2;
  build((rt << 1), l, mid);
  build((rt << 1 | 1), mid + 1, r);
  pushup(rt);
}
mat query(long long rt, long long l, long long r) {
  pushdown(rt);
  if (T[rt].l == l && T[rt].r == r) return T[rt].data;
  if (r <= T[(rt << 1)].r)
    return query((rt << 1), l, r);
  else if (l >= T[(rt << 1 | 1)].l)
    return query((rt << 1 | 1), l, r);
  else
    return query((rt << 1), l, T[(rt << 1)].r) +
           query((rt << 1 | 1), T[(rt << 1 | 1)].l, r);
}
long long query(long long l, long long r) {
  mat ret = query(1, l, r);
  return ret[0][0];
}
mat mt;
void modify(long long rt, long long l, long long r) {
  if (T[rt].l == l && T[rt].r == r) {
    T[rt].data = T[rt].data * mt;
    T[rt].tag = T[rt].tag * mt;
    return;
  }
  pushdown(rt);
  if (r <= T[(rt << 1)].r)
    modify((rt << 1), l, r);
  else if (l >= T[(rt << 1 | 1)].l)
    modify((rt << 1 | 1), l, r);
  else
    modify((rt << 1), l, T[(rt << 1)].r),
        modify((rt << 1 | 1), T[(rt << 1 | 1)].l, r);
  pushup(rt);
}
signed main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  init();
  cin >> n >> Q;
  for (long long i = 1; i <= n; i++) cin >> A[i];
  build(1, 1, n);
  while (Q--) {
    long long op;
    cin >> op;
    if (op == 1) {
      long long l, r, x;
      cin >> l >> r >> x;
      mt = bin_pow(matrix, x);
      modify(1, l, r);
    } else {
      long long l, r;
      cin >> l >> r;
      cout << query(l, r) << endl;
    }
  }
  return 0;
}
