#include <bits/stdc++.h>
using namespace std;
inline int read() {
  char ch = getchar();
  int x = 0, f = 1;
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while ('0' <= ch && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}
struct Matrix {
  int a[2][2];
  Matrix() { memset(a, 0, sizeof(a)); }
  inline Matrix operator*(const Matrix& rhs) const {
    Matrix ret;
    memset(ret.a, 0, sizeof(ret.a));
    for (int i = 0; i <= 1; i++) {
      for (int j = 0; j <= 1; j++) {
        long long at = 0;
        for (int k = 0; k <= 1; k++) {
          at += 1ll * a[i][k] * rhs.a[k][j];
        }
        ret.a[i][j] = at % 1000000007;
      }
    }
    return ret;
  }
} sz;
int a[400010];
Matrix q[400010];
Matrix la[400010];
Matrix l1[400010], l2[400010], l3[400010];
inline Matrix pow(int x) {
  return l1[x % 1000] * l2[(x / 1000) % 1000] * l3[x / 1000000];
}
inline void build(int l, int r, int o) {
  la[o].a[1][1] = la[o].a[0][0] = 1;
  if (l == r) {
    q[o].a[0][1] = 1;
    q[o] = q[o] * pow(a[l] - 1);
    return;
  }
  int mid = (l + r) / 2;
  build(l, mid, 2 * o);
  build(mid + 1, r, 2 * o + 1);
  q[o].a[0][1] = (q[2 * o].a[0][1] + q[2 * o + 1].a[0][1]) % 1000000007;
  q[o].a[0][0] = (q[2 * o].a[0][0] + q[2 * o + 1].a[0][0]) % 1000000007;
}
inline void change(int o, Matrix z) {
  q[o] = q[o] * z;
  la[o] = la[o] * z;
}
inline void pushdown(int o) {
  change(2 * o, la[o]);
  change(2 * o + 1, la[o]);
  la[o].a[0][0] = la[o].a[1][1] = 1;
  la[o].a[0][1] = la[o].a[1][0] = 0;
}
inline void add(int l, int r, int o, int x, int y, int z) {
  if (x <= l && r <= y) {
    change(o, pow(z));
    return;
  }
  int mid = (l + r) / 2;
  pushdown(o);
  if (x <= mid) add(l, mid, 2 * o, x, y, z);
  if (y > mid) add(mid + 1, r, 2 * o + 1, x, y, z);
  q[o].a[0][1] = (q[2 * o].a[0][1] + q[2 * o + 1].a[0][1]) % 1000000007;
  q[o].a[0][0] = (q[2 * o].a[0][0] + q[2 * o + 1].a[0][0]) % 1000000007;
}
inline int query(int l, int r, int o, int x, int y) {
  if (x <= l && r <= y) return q[o].a[0][1];
  int mid = (l + r) / 2;
  int ret = 0;
  pushdown(o);
  if (x <= mid) ret += query(l, mid, 2 * o, x, y);
  if (y > mid) ret += query(mid + 1, r, 2 * o + 1, x, y);
  return ret % 1000000007;
}
int main() {
  sz.a[0][0] = 0;
  sz.a[0][1] = 1;
  sz.a[1][0] = 1;
  sz.a[1][1] = 1;
  Matrix st;
  st.a[0][0] = st.a[1][1] = 1;
  int n = read(), m = read();
  for (int i = 1; i <= n; i++) {
    a[i] = read();
  }
  l1[0] = st;
  for (int i = 1; i <= 1000; i++) {
    l1[i] = l1[i - 1] * sz;
  }
  l2[0] = st;
  for (int i = 1; i <= 1000; i++) {
    l2[i] = l2[i - 1] * l1[1000];
  }
  l3[0] = st;
  for (int i = 1; i <= 1000; i++) {
    l3[i] = l3[i - 1] * l2[1000];
  }
  build(1, n, 1);
  while (m--) {
    int op = read();
    if (op == 1) {
      int l = read(), r = read(), x = read();
      add(1, n, 1, l, r, x);
    } else {
      int l = read(), r = read();
      printf("%d\n", query(1, n, 1, l, r));
    }
  }
  return 0;
}
