#include <bits/stdc++.h>
using namespace std;
namespace my_std {
bool ccc(long long a, long long b) { return a > b; }
long long my_pow(long long a, long long b, long long mod) {
  long long res = 1;
  if (!b) return 1;
  while (b) {
    if (b & 1) res = (res * a) % mod;
    a = (a * a) % mod;
    b >>= 1;
  }
  return res;
}
long long qpow(long long a, long long b) {
  long long res = 1;
  if (!b) return 1;
  while (b) {
    if (b & 1) res *= a;
    a *= a;
    b >>= 1;
  }
  return res;
}
inline long long read() {
  long long sum = 0, f = 1;
  char ch = 0;
  while (!isdigit(ch)) {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    sum = sum * 10 + (ch ^ 48);
    ch = getchar();
  }
  return sum * f;
}
inline void write(long long x) {
  if (x < 0) {
    x = -x;
    putchar('-');
  }
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
inline void writeln(long long x) {
  write(x);
  putchar('\n');
}
inline void writesp(long long x) {
  write(x);
  putchar(' ');
}
}  // namespace my_std
using namespace my_std;
long long n, m, a[100010];
struct matrix {
  long long q[3][3];
  matrix() { memset(q, 0, sizeof(q)); }
  void clear() { q[1][1] = q[1][2] = q[2][1] = q[2][2] = 0; }
  void init() {
    q[1][1] = q[2][2] = 1;
    q[1][2] = q[2][1] = 0;
  }
  matrix operator*(const matrix &a) {
    matrix ans;
    ans.clear();
    for (register long long i = (1); i <= (2); i++)
      for (register long long j = (1); j <= (2); j++)
        for (register long long k = (1); k <= (2); k++)
          ans.q[i][j] =
              (ans.q[i][j] + q[i][k] * a.q[k][j] % 1000000007) % 1000000007;
    return ans;
  }
  matrix operator+(const matrix &a) {
    matrix ans;
    ans.clear();
    for (register long long i = (1); i <= (2); i++)
      for (register long long j = (1); j <= (2); j++)
        ans.q[i][j] = (q[i][j] + a.q[i][j]) % 1000000007;
    return ans;
  }
} qwe, st, tree[400040], lz[400040];
matrix ksm(matrix a, long long b) {
  matrix res;
  res.init();
  while (b) {
    if (b & 1) res = res * a;
    a = a * a;
    b >>= 1;
  }
  return res;
}
void pushup(long long x) { tree[x] = tree[x << 1] + tree[x << 1 | 1]; }
void build(long long x, long long l, long long r) {
  tree[x].clear();
  lz[x].init();
  if (l == r) {
    tree[x] = st * ksm(qwe, a[l] - 1);
    return;
  }
  long long mid = (l + r) >> 1;
  build(x << 1, l, mid);
  build(x << 1 | 1, mid + 1, r);
  pushup(x);
}
void pushdown(long long x) {
  tree[x << 1] = tree[x << 1] * lz[x];
  tree[x << 1 | 1] = tree[x << 1 | 1] * lz[x];
  lz[x << 1] = lz[x << 1] * lz[x];
  lz[x << 1 | 1] = lz[x << 1 | 1] * lz[x];
  lz[x].init();
}
void add(long long x, long long l, long long r, long long ql, long long qr,
         matrix p) {
  if (ql <= l && r <= qr) {
    tree[x] = tree[x] * p;
    lz[x] = lz[x] * p;
    return;
  }
  long long mid = (l + r) >> 1;
  pushdown(x);
  if (ql <= mid) add(x << 1, l, mid, ql, qr, p);
  if (mid < qr) add(x << 1 | 1, mid + 1, r, ql, qr, p);
  pushup(x);
}
matrix query(long long x, long long l, long long r, long long ql,
             long long qr) {
  if (ql <= l && r <= qr) return tree[x];
  long long mid = (l + r) >> 1;
  matrix res;
  res.clear();
  pushdown(x);
  if (ql <= mid) res = res + query(x << 1, l, mid, ql, qr);
  if (mid < qr) res = res + query(x << 1 | 1, mid + 1, r, ql, qr);
  return res;
}
int main() {
  n = read();
  m = read();
  for (register long long i = (1); i <= (n); i++) a[i] = read();
  qwe.q[1][1] = qwe.q[1][2] = qwe.q[2][1] = 1;
  st.q[1][1] = st.q[1][2] = 1;
  build(1, 1, n);
  while (m--) {
    long long opt = read(), l = read(), r = read();
    if (opt == 1) {
      long long x = read();
      add(1, 1, n, l, r, ksm(qwe, x));
    } else
      writeln(query(1, 1, n, l, r).q[1][2] % 1000000007);
  }
}
