#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:16777222")
using namespace std;
const long long mod = (long long)1e9 + 7;
const int inf = (int)2e9;
const long long INF = (long long)1e18;
const int base = 1000 * 1000 * 1000;
const int maxn = 505;
const long double pi = acosl(-1.0);
const long double eps = 1e-9;
struct matrix {
  long long a[2][2];
  matrix(){};
  matrix(int x1, int x2, int x3, int x4) {
    a[0][0] = x1;
    a[0][1] = x2;
    a[1][0] = x3;
    a[1][1] = x4;
  }
};
matrix multi(matrix a, matrix b) {
  matrix res(0, 0, 0, 0);
  for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++)
      for (int k = 0; k < 2; k++) {
        res.a[i][j] = (res.a[i][j] + a.a[i][k] * b.a[k][j]) % mod;
      }
  return res;
}
matrix fib(int p) {
  if (p == 1) return matrix(0, 1, 1, 1);
  matrix res = fib(p / 2);
  res = multi(res, res);
  if (p & 1) res = multi(res, matrix(0, 1, 1, 1));
  return res;
}
matrix sum(matrix a, matrix b) {
  matrix res(0, 0, 0, 0);
  for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++) {
      res.a[i][j] = (res.a[i][j] + a.a[i][j] + b.a[i][j]) % mod;
    }
  return res;
}
struct Tree {
  vector<matrix> t;
  vector<matrix> add;
  int size = 1;
  void init(vector<int> &d) {
    while (size <= (int)d.size()) size <<= 1;
    t.resize(size << 1, matrix(0, 0, 0, 0));
    add.resize(size << 1, matrix(1, 0, 0, 1));
    for (int i = 0; i < (int)d.size(); i++) t[i + size] = fib(d[i]);
    for (int i = size - 1; i >= 1; i--) t[i] = sum(t[2 * i], t[2 * i + 1]);
  }
  void push(int v) {
    add[2 * v] = multi(add[2 * v], add[v]);
    add[2 * v + 1] = multi(add[2 * v + 1], add[v]);
    add[v] = matrix(1, 0, 0, 1);
  }
  void update(int v) {
    t[v] =
        sum(multi(t[2 * v], add[2 * v]), multi(t[2 * v + 1], add[2 * v + 1]));
  }
  matrix get(int v, int l, int r, int L, int R) {
    if (L > R) return matrix(0, 0, 0, 0);
    if (l == L && r == R) {
      return multi(t[v], add[v]);
    }
    push(v);
    int mid = (l + r) / 2;
    matrix a = get(2 * v, l, mid, L, min(R, mid));
    matrix b = get(2 * v + 1, mid + 1, r, max(L, mid + 1), R);
    update(v);
    return sum(a, b);
  }
  void set(int v, int l, int r, int L, int R, matrix val) {
    if (L > R) return;
    if (l == L && r == R) {
      add[v] = multi(add[v], val);
      return;
    }
    push(v);
    int mid = (l + r) / 2;
    set(2 * v, l, mid, L, min(R, mid), val);
    set(2 * v + 1, mid + 1, r, max(L, mid + 1), R, val);
    update(v);
  }
};
void solve() {
  int n, q;
  scanf("%d %d", &n, &q);
  vector<int> d(n);
  for (int i = 0; i < n; i++) scanf("%d", &d[i]);
  Tree tree;
  tree.init(d);
  while (q--) {
    int t, l, r;
    scanf("%d %d %d", &t, &l, &r);
    l--, r--;
    if (t == 1) {
      int x;
      scanf("%d", &x);
      tree.set(1, 0, tree.size - 1, l, r, fib(x));
    }
    if (t == 2) {
      printf("%I64d\n", tree.get(1, 0, tree.size - 1, l, r).a[0][1]);
    }
  }
}
int main() {
  solve();
  return 0;
}
