#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000 + 100;
const int MODULE = 1e9 + 7;
const int INF = numeric_limits<int>::max();
const double EXP = 0.0001;
void files() {
  freopen("input.txt", "r", stdin);
  freopen("output.txt", "w", stdout);
}
struct Matrix {
  int m[2][2];
  void clear() { m[0][0] = m[0][1] = m[1][0] = m[1][1] = 0; }
  void basic() {
    m[0][1] = m[1][0] = 0;
    m[0][0] = m[1][1] = 1;
  }
  Matrix operator+(const Matrix &x) {
    Matrix temp;
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++) temp.m[i][j] = (m[i][j] + x.m[i][j]) % MODULE;
    return temp;
  }
  Matrix operator*(const Matrix &x) {
    Matrix temp;
    temp.clear();
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++)
        for (int d = 0; d < 2; d++) {
          temp.m[i][j] += m[i][d] * 1ll * x.m[d][j] % MODULE;
          temp.m[i][j] %= MODULE;
        }
    return temp;
  }
  Matrix power(int n) {
    Matrix result, a = *this;
    result.basic();
    while (n) {
      if (n & 1) {
        result = result * a;
      }
      a = a * a;
      n >>= 1;
    }
    return result;
  }
};
struct Tree {
  Matrix mod;
  Matrix sum;
};
int a[MAXN];
Tree t[4 * MAXN];
Matrix fib, temp;
void build(int v, int tl, int tr) {
  t[v].mod.basic();
  if (tl == tr) {
    t[v].sum = fib.power(a[tl]);
  } else {
    int tm = (tl + tr) / 2;
    build(v * 2, tl, tm);
    build(v * 2 + 1, tm + 1, tr);
    t[v].sum = t[v * 2].sum + t[v * 2 + 1].sum;
  }
}
void push(int v, int tl, int tr) {
  t[v * 2].mod = t[v * 2].mod * t[v].mod;
  t[v * 2 + 1].mod = t[v * 2 + 1].mod * t[v].mod;
  t[v * 2].sum = t[v * 2].sum * t[v].mod;
  t[v * 2 + 1].sum = t[v * 2 + 1].sum * t[v].mod;
  t[v].mod.basic();
}
void update_range(int v, int tl, int tr, int l, int r) {
  if (r < tl || tr < l) return;
  if (l <= tl && tr <= r) {
    t[v].sum = t[v].sum * temp;
    t[v].mod = t[v].mod * temp;
    if (tl == tr) t[v].mod.basic();
    return;
  }
  push(v, tl, tr);
  int tm = (tl + tr) / 2;
  update_range(v * 2, tl, tm, l, r);
  update_range(v * 2 + 1, tm + 1, tr, l, r);
  t[v].sum = t[v * 2].sum + t[v * 2 + 1].sum;
}
Matrix getSum(int v, int tl, int tr, int l, int r) {
  Matrix result;
  result.clear();
  if (r < tl || l > tr) return result;
  if (l <= tl && tr <= r) return t[v].sum;
  push(v, tl, tr);
  int tm = (tl + tr) / 2;
  result = getSum(v * 2, tl, tm, l, r) + getSum(v * 2 + 1, tm + 1, tr, l, r);
  return result;
}
int main() {
  ios_base::sync_with_stdio(false);
  int n, m;
  cin >> n >> m;
  for (int i = 1; i <= n; i++) cin >> a[i];
  fib.m[0][0] = 0;
  fib.m[1][0] = fib.m[0][1] = fib.m[1][1] = 1;
  build(1, 1, n);
  int type, l, r, x;
  for (int i = 1; i <= m; i++) {
    cin >> type;
    if (type == 1) {
      cin >> l >> r >> x;
      temp = fib.power(x);
      update_range(1, 1, n, l, r);
    } else {
      cin >> l >> r;
      cout << getSum(1, 1, n, l, r).m[1][0] << endl;
    }
  }
  return 0;
}
