#include <bits/stdc++.h>
using namespace std;
const long long mod = 1e9 + 7;
const int maxn = 110000;
struct Matrix {
  int size;
  long long data[5][5];
} tmp;
long long a[maxn];
struct Node {
  int left, right;
  Matrix m;
} tree[maxn * 4];
Matrix add[maxn * 4];
void init(Matrix &x, int size) {
  x.size = size;
  memset(x.data, 0, sizeof(x.data));
}
void unit(Matrix &x) {
  for (int i = 1; i <= x.size; i++) x.data[i][i] = 1;
}
Matrix multiply(Matrix &x, Matrix &y, long long m) {
  Matrix ans;
  init(ans, x.size);
  for (int i = 1; i <= x.size; i++)
    for (int j = 1; j <= x.size; j++)
      for (int k = 1; k <= x.size; k++) {
        ans.data[i][j] += x.data[i][k] * y.data[k][j];
        ans.data[i][j] %= m;
      }
  return ans;
}
Matrix power(Matrix &a, long long n, long long m) {
  Matrix ans, tmp = a;
  init(ans, a.size);
  unit(ans);
  while (n) {
    if (n & 1) ans = multiply(ans, tmp, m);
    tmp = multiply(tmp, tmp, m);
    n >>= 1;
  }
  return ans;
}
void pushup(int i) {
  tree[i].m.data[1][1] =
      (tree[i * 2].m.data[1][1] + tree[i * 2 + 1].m.data[1][1]) % mod;
  tree[i].m.data[1][2] =
      (tree[i * 2].m.data[1][2] + tree[i * 2 + 1].m.data[1][2]) % mod;
  tree[i].m.data[2][1] =
      (tree[i * 2].m.data[2][1] + tree[i * 2 + 1].m.data[2][1]) % mod;
  tree[i].m.data[2][2] =
      (tree[i * 2].m.data[2][2] + tree[i * 2 + 1].m.data[2][2]) % mod;
}
void pushdown(int i) {
  tree[i * 2].m = multiply(tree[i * 2].m, add[i], mod);
  tree[i * 2 + 1].m = multiply(tree[i * 2 + 1].m, add[i], mod);
  add[i * 2] = multiply(add[i * 2], add[i], mod);
  add[i * 2 + 1] = multiply(add[i * 2 + 1], add[i], mod);
  init(add[i], 2);
  unit(add[i]);
}
void build(int i, int begin, int end) {
  tree[i].left = begin;
  tree[i].right = end;
  init(tree[i].m, 2);
  init(add[i], 2);
  unit(add[i]);
  if (begin == end) {
    tree[i].m = power(tmp, a[begin], mod);
    return;
  }
  int mid = (begin + end) / 2;
  build(i * 2, begin, mid);
  build(i * 2 + 1, mid + 1, end);
  pushup(i);
}
void update(int i, int begin, int end, Matrix t) {
  if (tree[i].left >= begin && tree[i].right <= end) {
    tree[i].m = multiply(tree[i].m, t, mod);
    add[i] = multiply(add[i], t, mod);
    return;
  }
  pushdown(i);
  int mid = (tree[i].left + tree[i].right) / 2;
  if (mid >= begin) update(i * 2, begin, end, t);
  if (mid < end) update(i * 2 + 1, begin, end, t);
  pushup(i);
}
long long query(int i, int begin, int end) {
  if (tree[i].left >= begin && tree[i].right <= end)
    return tree[i].m.data[1][2];
  pushdown(i);
  int mid = (tree[i].left + tree[i].right) / 2;
  long long ans = 0;
  if (mid >= begin) ans = (ans + query(i * 2, begin, end)) % mod;
  if (mid < end) ans = (ans + query(i * 2 + 1, begin, end)) % mod;
  return ans;
}
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) scanf("%I64d", &a[i]);
  init(tmp, 2);
  tmp.data[1][1] = 1;
  tmp.data[1][2] = 1;
  tmp.data[2][1] = 1;
  tmp.data[2][2] = 0;
  build(1, 1, n);
  int tp;
  long long l, r, x;
  for (int i = 1; i <= m; i++) {
    scanf("%d", &tp);
    if (tp == 1) {
      scanf("%I64d%I64d%I64d", &l, &r, &x);
      update(1, l, r, power(tmp, x, mod));
    } else {
      scanf("%I64d%I64d", &l, &r);
      long long ans = query(1, l, r);
      printf("%I64d\n", ans);
    }
  }
  return 0;
}
