#include <bits/stdc++.h>
using namespace std;
template <class T>
inline void read(T &x) {
  char c = getchar();
  x = 0;
  while (!isdigit(c)) c = getchar();
  while (isdigit(c)) {
    x = x * 10 + c - '0';
    c = getchar();
  }
}
template <class T>
inline void rd(T &res) {
  static char ch;
  bool sgn = false;
  while (ch = getchar(), ch < '0' || ch > '9')
    if (ch == '-') sgn = true;
  res = ch - 48;
  while (ch = getchar(), ch >= '0' && ch <= '9') res = res * 10 + ch - 48;
  res = sgn ? -res : res;
}
template <class T>
void Out(T a) {
  if (a < 0) {
    putchar('-');
    a = -a;
  }
  if (a >= 10) Out(a / 10);
  putchar(a % 10 + '0');
}
const int N = 1e5 + 10;
const long long M = 1e9 + 7;
struct mart {
  long long a[2][2];
  mart() {}
  mart(int x) {
    memset(a, 0, sizeof(a));
    if (x == 1)
      for (int i = 0; i < 2; i++) a[i][i] = 1;
    if (x == 2) {
      a[0][0] = a[0][1] = a[1][0] = 1;
      a[1][1] = 0;
    }
  };
  mart operator*(mart &b) {
    mart c(0);
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++)
        if (a[i][j])
          for (int k = 0; k < 2; k++)
            c.a[i][k] = (c.a[i][k] + a[i][j] * b.a[j][k]) % M;
    return c;
  }
  mart operator+(mart &b) {
    mart c(0);
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++) c.a[i][j] = (a[i][j] + b.a[i][j]) % M;
    return c;
  }
  void show() {
    puts("_________________");
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2; j++) printf("%d ", a[i][j]);
      puts("");
    }
    puts("_________________");
  }
} tree[N << 2], add[N << 2];
mart pow(long long k) {
  mart ret(1), a(2);
  while (k) {
    if (k & 1) ret = ret * a;
    a = a * a;
    k >>= 1;
  }
  return ret;
}
void build(int p, int l, int r) {
  add[p] = mart(1);
  if (l == r) {
    long long x;
    rd(x);
    tree[p] = pow(x);
    return;
  }
  int m = r + l >> 1;
  build((p << 1), l, m);
  build(((p << 1) | 1), m + 1, r);
  tree[p] = tree[(p << 1)] + tree[((p << 1) | 1)];
}
void update(int p, int l, int r, int s, int t, mart val) {
  if (s <= l && r <= t) {
    add[p] = add[p] * val;
    tree[p] = tree[p] * val;
    return;
  }
  if (add[p].a[0][1]) {
    add[(p << 1)] = add[p] * add[(p << 1)];
    add[((p << 1) | 1)] = add[p] * add[((p << 1) | 1)];
    tree[(p << 1)] = tree[(p << 1)] * add[p];
    tree[((p << 1) | 1)] = tree[((p << 1) | 1)] * add[p];
    add[p] = mart(1);
  }
  int m = r + l >> 1;
  if (s <= m) update((p << 1), l, m, s, t, val);
  if (t > m) update(((p << 1) | 1), m + 1, r, s, t, val);
  tree[p] = tree[(p << 1)] + tree[((p << 1) | 1)];
}
mart query(int p, int l, int r, int s, int t) {
  if (s <= l && r <= t) return tree[p];
  if (add[p].a[0][1]) {
    add[(p << 1)] = add[p] * add[(p << 1)];
    add[((p << 1) | 1)] = add[p] * add[((p << 1) | 1)];
    tree[(p << 1)] = tree[(p << 1)] * add[p];
    tree[((p << 1) | 1)] = tree[((p << 1) | 1)] * add[p];
    add[p] = mart(1);
  }
  int m = r + l >> 1;
  mart ans = mart(1), tmp;
  if (s <= m) tmp = query((p << 1), l, m, s, t), ans = ans + tmp;
  if (t > m) tmp = query(((p << 1) | 1), m + 1, r, s, t), ans = ans + tmp;
  return ans;
}
int main() {
  int n, m;
  while (~scanf("%d%d", &n, &m)) {
    build(1, 1, n);
    while (m--) {
      int op, l, r;
      long long x;
      rd(op), rd(l), rd(r);
      if (op == 1) {
        rd(x);
        update(1, 1, n, l, r, pow(x));
      } else {
        Out(query(1, 1, n, l, r).a[0][1]), puts("");
      }
    }
  }
  return 0;
}
