#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
const int mod = 1000000007;
int n, m, l, r, x, c[N], W;
char E[20000000];
struct matrix {
  int a[2][2];
  matrix operator*(matrix p) const {
    matrix ret;
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++) {
        ret.a[i][j] = 0;
        for (int k = 0; k < 2; k++)
          ret.a[i][j] = (ret.a[i][j] + 1ll * a[i][k] * p.a[k][j] % mod) % mod;
      }
    return ret;
  }
  matrix operator+(matrix p) const {
    matrix ret;
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++) ret.a[i][j] = (a[i][j] + p.a[i][j]) % mod;
    return ret;
  }
  bool operator==(matrix p) const {
    if (a[0][0] != p.a[0][0]) return 0;
    if (a[0][1] != p.a[0][1]) return 0;
    if (a[1][0] != p.a[1][0]) return 0;
    if (a[1][1] != p.a[1][1]) return 0;
    return 1;
  }
} C, D;
void mul(matrix &A, long long y) {
  matrix B = C;
  for (; y; y >>= 1, B = B * B)
    if (y & 1) A = A * B;
}
struct segment {
  int l, r;
  matrix Mat, tag;
} a[N << 2];
void build(int pos, int l, int r) {
  a[pos].l = l;
  a[pos].r = r;
  a[pos].tag = D;
  if (l == r) {
    a[pos].Mat = D;
    mul(a[pos].Mat, c[l]);
    return;
  }
  int mid = l + r >> 1;
  build(pos << 1, l, mid);
  build(pos << 1 | 1, mid + 1, r);
  a[pos].Mat = a[pos << 1].Mat + a[pos << 1 | 1].Mat;
  return;
}
void pushdown(int pos) {
  if (a[pos].tag == D) return;
  a[pos << 1].Mat = a[pos << 1].Mat * a[pos].tag;
  a[pos << 1 | 1].Mat = a[pos << 1 | 1].Mat * a[pos].tag;
  a[pos << 1].tag = a[pos << 1].tag * a[pos].tag;
  a[pos << 1 | 1].tag = a[pos << 1 | 1].tag * a[pos].tag;
  a[pos].tag = D;
  return;
}
void modify(int pos, int l, int r, matrix x) {
  if (a[pos].l == l && a[pos].r == r) {
    a[pos].tag = a[pos].tag * x;
    a[pos].Mat = a[pos].Mat * x;
    return;
  }
  pushdown(pos);
  int mid = a[pos].l + a[pos].r >> 1;
  if (r <= mid)
    modify(pos << 1, l, r, x);
  else if (l > mid)
    modify(pos << 1 | 1, l, r, x);
  else
    modify(pos << 1, l, mid, x), modify(pos << 1 | 1, mid + 1, r, x);
  a[pos].Mat = a[pos << 1].Mat + a[pos << 1 | 1].Mat;
}
int query(int pos, int l, int r) {
  if (a[pos].l == l && a[pos].r == r) return a[pos].Mat.a[0][1];
  pushdown(pos);
  int mid = a[pos].l + a[pos].r >> 1;
  if (r <= mid)
    return query(pos << 1, l, r);
  else if (l > mid)
    return query(pos << 1 | 1, l, r);
  else
    return (query(pos << 1, l, mid) + query(pos << 1 | 1, mid + 1, r)) % mod;
}
inline int read() {
  char c = E[W++];
  int t = 0;
  for (; c < 48; c = E[W++])
    ;
  for (; c > 47; c = E[W++]) t = (t << 1) + (t << 3) + c - 48;
  return t;
}
inline void write(int x) {
  if (!x) return;
  write(x / 10);
  putchar(x % 10 + 48);
}
int main() {
  fread(E, 1, 19999999, stdin);
  C.a[0][0] = 1;
  C.a[0][1] = 1;
  C.a[1][0] = 1;
  C.a[1][1] = 0;
  D.a[0][0] = 1;
  D.a[1][1] = 1;
  D.a[1][0] = 0;
  D.a[0][1] = 0;
  n = read(), m = read();
  for (int i = 1; i <= n; i++) c[i] = read();
  build(1, 1, n);
  for (int opt, i = 1; i <= m; i++) {
    opt = read();
    if (opt == 1) {
      l = read(), r = read(), x = read();
      matrix tmp = D;
      mul(tmp, x);
      modify(1, l, r, tmp);
    }
    if (opt == 2) {
      l = read(), r = read();
      write(query(1, l, r)), putchar('\n');
    }
  }
  return 0;
}
