#include <bits/stdc++.h>
using namespace std;
const long long wyx = (long long)(1e9 + 7), QAQ = (long long)(1e5 + 5);
struct matrix {
  long long c[4][4];
  matrix() { c[1][1] = c[2][2] = c[1][2] = c[2][1] = 0; }
};
matrix E() {
  matrix x;
  x.c[1][1] = x.c[2][2] = 1;
  return x;
}
matrix operator+(const matrix &a, const matrix &b) {
  matrix x;
  for (long long i = 1; i <= 2; i++) {
    for (long long j = 1; j <= 2; j++)
      x.c[i][j] = (a.c[i][j] + b.c[i][j]) % wyx;
  }
  return x;
}
matrix operator*(const matrix &a, const matrix &b) {
  matrix x;
  for (long long i = 1; i <= 2; i++) {
    for (long long j = 1; j <= 2; j++) {
      for (long long k = 1; k <= 2; k++)
        x.c[i][j] = (x.c[i][j] + a.c[i][k] * b.c[k][j]) % wyx;
    }
  }
  return x;
}
bool isE(matrix x) {
  if (x.c[1][1] == 1 && x.c[2][2] == 1 && x.c[1][2] == 0 && x.c[2][1] == 0)
    return 1;
  else
    return 0;
}
matrix ksm(matrix a, long long b) {
  matrix x = E();
  while (b) {
    if (b & 1) x = x * a;
    a = a * a;
    b >>= 1;
  }
  return x;
}
long long arr[QAQ];
matrix tree[QAQ << 2], lazy[QAQ << 2];
matrix T, fib;
void pushup(long long node) {
  tree[node] = tree[(node << 1)] + tree[(node << 1 | 1)];
}
void build(long long node, long long s, long long e) {
  lazy[node] = E();
  if (s == e) {
    tree[node] = fib * ksm(T, arr[s] - 1);
    return;
  }
  long long mid = (s + e) >> 1;
  build((node << 1), s, mid);
  build((node << 1 | 1), mid + 1, e);
  pushup(node);
}
void pushdown(long long node) {
  matrix val = lazy[node];
  tree[(node << 1)] = tree[(node << 1)] * val;
  lazy[(node << 1)] = lazy[(node << 1)] * val;
  tree[(node << 1 | 1)] = tree[(node << 1 | 1)] * val;
  lazy[(node << 1 | 1)] = lazy[(node << 1 | 1)] * val;
  lazy[node] = E();
}
void update(long long node, long long s, long long e, long long l, long long r,
            matrix val) {
  if (l <= s && r >= e) {
    lazy[node] = lazy[node] * val;
    tree[node] = tree[node] * val;
    return;
  }
  if (!isE(lazy[node])) pushdown(node);
  long long mid = (s + e) >> 1;
  if (l <= mid) update((node << 1), s, mid, l, r, val);
  if (r > mid) update((node << 1 | 1), mid + 1, e, l, r, val);
  pushup(node);
}
matrix query(long long node, long long s, long long e, long long l,
             long long r) {
  if (l <= s && r >= e) {
    ;
    return tree[node];
  }
  if (!isE(lazy[node])) pushdown(node);
  matrix res;
  long long mid = (s + e) >> 1;
  if (l <= mid) res = res + query((node << 1), s, mid, l, r);
  if (r > mid) res = res + query((node << 1 | 1), mid + 1, e, l, r);
  return res;
}
inline long long read() {
  char c = getchar();
  long long f = 1, x = 0;
  while (c < '0' || c > '9') {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = x * 10 + (c - '0');
    c = getchar();
  }
  return f * x;
}
signed main() {
  fib.c[1][1] = fib.c[1][2] = 1;
  T.c[1][1] = T.c[1][2] = T.c[2][1] = 1;
  long long n = read(), m = read();
  for (long long i = 1; i <= n; i++) arr[i] = read();
  build(1, 1, n);
  for (long long i = 1; i <= m; i++) {
    long long opt = read();
    if (opt == 1) {
      long long l = read(), r = read(), x = read();
      update(1, 1, n, l, r, ksm(T, x));
    }
    if (opt == 2) {
      long long l = read(), r = read();
      printf("%lld\n", query(1, 1, n, l, r).c[1][2] % wyx);
    }
  }
  return 0;
}
