#include <bits/stdc++.h>
using namespace std;
void read_file(bool outToFile = true) {}
const int nMax = 100 * 1000;
int n, nq;
int A[nMax];
const int matMax = 2;
inline void add(int &x, int v) {
  x += v;
  if (x >= (1000000007)) x -= (1000000007);
}
struct matrix {
  int n, m;
  int mat[matMax][matMax];
  matrix() {}
  matrix(int nn, int nm, int d = 0) {
    n = nn, m = nm;
    memset(mat, 0, sizeof mat);
    if (d) {
      for (int i = 0; i < n; i++) mat[i][i] = d;
    }
  }
  bool operator==(const matrix &B) const {
    if (n == B.n && m == B.m)
      ;
    else
      return 0;
    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++) {
        if (mat[i][j] != B.mat[i][j]) return 0;
      }
    return 1;
  }
  matrix operator+(const matrix &B) const {
    assert(n == B.n && m == B.m);
    matrix C = *this;
    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++) add(C.mat[i][j], B.mat[i][j]);
    return C;
  }
  matrix operator*(const matrix &B) const {
    int p = B.m;
    assert(B.n == m);
    matrix C(n, p);
    for (int i = 0; i < n; i++) {
      for (int k = 0; k < m; k++) {
        if (mat[i][k] == 0) continue;
        for (int j = 0; j < p; j++)
          add(C.mat[i][j], 1LL * mat[i][k] * B.mat[k][j] % (1000000007));
      }
    }
    return C;
  }
};
const int TMax = 30;
matrix T[TMax], F0;
map<int, matrix> mp;
void build_T() {
  F0 = matrix(2, 1);
  F0.mat[0][0] = 1;
  T[0] = matrix(2, 2);
  T[0].mat[0][0] = T[0].mat[0][1] = T[0].mat[1][0] = 1;
  for (int i = 1; i < TMax; i++) {
    T[i] = T[i - 1] * T[i - 1];
  }
}
matrix pow(int n) {
  if (mp.count(n)) return mp[n];
  matrix ret = matrix(2, 2, 1);
  int tmp = n;
  int bit = 0;
  while (tmp) {
    if (tmp & 1) {
      ret = ret * T[bit];
    }
    tmp >>= 1;
    bit++;
  }
  return mp[n] = ret;
}
const int stMax = 1 << 18;
struct node {
  matrix S;
  matrix lazy;
};
node ST[stMax];
int fr, to;
void init(int s = 0, int e = n - 1, int p = 1) {
  if (s == e) {
    ST[p].lazy = matrix(2, 2, 1);
    ST[p].S = pow(A[s]) * F0;
    return;
  }
  int m = s + e >> 1;
  init(s, m, p << 1);
  init(m + 1, e, p << 1 | 1);
  ST[p].lazy = matrix(2, 2, 1);
  ST[p].S = ST[p << 1].S + ST[p << 1 | 1].S;
}
void update_node(matrix tmp, int p) {
  ST[p].lazy = tmp * ST[p].lazy;
  ST[p].S = tmp * ST[p].S;
}
void update_child(int p) {
  if (ST[p].lazy == matrix(2, 2, 1)) return;
  update_node(ST[p].lazy, p << 1);
  update_node(ST[p].lazy, p << 1 | 1);
  ST[p].lazy = matrix(2, 2, 1);
}
void update(int x, int s = 0, int e = n - 1, int p = 1) {
  if (e < fr || s > to) return;
  if (fr <= s && e <= to) {
    update_node(pow(x), p);
    return;
  }
  update_child(p);
  int m = s + e >> 1;
  update(x, s, m, p << 1);
  update(x, m + 1, e, p << 1 | 1);
  ST[p].S = ST[p << 1].S + ST[p << 1 | 1].S;
}
matrix query(int s = 0, int e = n - 1, int p = 1) {
  if (e < fr || s > to) return matrix(2, 1);
  if (fr <= s && e <= to) return ST[p].S;
  update_child(p);
  int m = s + e >> 1;
  matrix ql = query(s, m, p << 1);
  matrix qr = query(m + 1, e, p << 1 | 1);
  matrix ret = ql + qr;
  return ret;
}
int main() {
  read_file();
  build_T();
  while (scanf("%d%d", &n, &nq) != EOF) {
    for (int i = 0; i < n; i++) scanf("%d", &A[i]);
    init();
    while (nq--) {
      int cmd;
      scanf("%d", &cmd);
      if (cmd == 1) {
        int x;
        scanf("%d%d%d", &fr, &to, &x);
        fr--, to--;
        update(x);
      } else {
        assert(cmd == 2);
        scanf("%d%d", &fr, &to);
        fr--, to--;
        matrix ansm = query();
        int ans = ansm.mat[1][0];
        printf("%d\n", ans);
      }
    }
  }
}
