#include <bits/stdc++.h>
using namespace std;
const int MOD = 1E9 + 7;
const int maxn = 100000 + 5;
int d[maxn];
struct Matrix {
  long long v[2][2];
  void clr() { memset(v, 0, sizeof(v)); }
  void E() {
    clr();
    for (int i = 0; i < 2; ++i) v[i][i] = 1;
  }
  void debug() {
    for (int i = 0; i < 2; ++i)
      for (int j = 0; j < 2; ++j) cout << v[i][j] << (j == 1 ? "\n" : " ");
  }
  Matrix operator*(Matrix b) {
    Matrix res;
    res.clr();
    for (int i = 0; i < 2; ++i)
      for (int j = 0; j < 2; ++j)
        for (int k = 0; k < 2; ++k)
          res.v[i][j] = (res.v[i][j] + v[i][k] * b.v[k][j]) % MOD;
    return res;
  }
  Matrix operator+(Matrix b) {
    Matrix res;
    for (int i = 0; i < 2; ++i)
      for (int j = 0; j < 2; ++j) res.v[i][j] = (v[i][j] + b.v[i][j]) % MOD;
    return res;
  }
  Matrix operator^(int b) {
    Matrix res, a;
    res.E();
    memcpy(a.v, v, sizeof(v));
    while (b) {
      if (b & 1) res = res * a;
      a = a * a;
      b >>= 1;
    }
    return res;
  }
} mat, tmp;
struct node {
  int lazy;
  Matrix sum, la;
} a[maxn << 2];
void pushUp(int rt) { a[rt].sum = a[rt << 1].sum + a[rt << 1 | 1].sum; }
void build(int rt, int l, int r) {
  a[rt].la.E();
  a[rt].lazy = 0;
  if (l == r) {
    cin >> d[l];
    a[rt].sum = mat ^ d[l];
    return;
  }
  build(rt << 1, l, ((l + r) >> 1));
  build(rt << 1 | 1, ((l + r) >> 1) + 1, r);
  pushUp(rt);
}
void down(int s, int f) {
  a[s].lazy = a[f].lazy;
  a[s].la = a[s].la * a[f].la;
  a[s].sum = a[s].sum * a[f].la;
}
void pushDown(int rt) {
  if (a[rt].lazy) {
    down(rt << 1, rt);
    down(rt << 1 | 1, rt);
    a[rt].lazy = 0;
    a[rt].la.E();
  }
}
void update(int rt, int l, int r, int L, int R) {
  if (L <= l && R >= r) {
    a[rt].sum = a[rt].sum * tmp;
    a[rt].la = a[rt].la * tmp;
    a[rt].lazy = 1;
    return;
  }
  pushDown(rt);
  if (L <= ((l + r) >> 1)) update(rt << 1, l, ((l + r) >> 1), L, R);
  if (R > ((l + r) >> 1)) update(rt << 1 | 1, ((l + r) >> 1) + 1, r, L, R);
  pushUp(rt);
}
long long query(int rt, int l, int r, int L, int R) {
  if (L <= l && R >= r) return a[rt].sum.v[0][1];
  pushDown(rt);
  long long res = 0;
  if (L <= ((l + r) >> 1)) res += query(rt << 1, l, ((l + r) >> 1), L, R);
  if (R > ((l + r) >> 1))
    res += query(rt << 1 | 1, ((l + r) >> 1) + 1, r, L, R);
  return res;
}
int main() {
  cin.tie(0);
  cin.sync_with_stdio(false);
  mat.clr();
  mat.v[0][1] = mat.v[1][0] = mat.v[1][1] = 1;
  int n, m, op, l, r, x;
  while (cin >> n >> m) {
    build(1, 1, n);
    while (m--) {
      cin >> op >> l >> r;
      if (op == 1) {
        cin >> x;
        tmp = mat ^ x;
        update(1, 1, n, l, r);
      } else {
        long long ans = query(1, 1, n, l, r);
        cout << ans % MOD << endl;
      }
    }
  }
  return 0;
}
