#include <bits/stdc++.h>
using namespace std;
struct Mat {
  int len;
  int m[2][2];
  void cl() {
    len = 0;
    memset(m, 0, sizeof(m));
  }
} m, f, t, c[410000], lazy[410000];
bool col[410000];
Mat operator*(const Mat &a, const Mat &b) {
  Mat c;
  int i, j, k;
  c.cl();
  c.len = a.len;
  for (i = 0; i < c.len; ++i)
    for (j = 0; j < c.len; ++j)
      for (k = 0; k < c.len; ++k)
        c.m[i][j] = (1LL * a.m[i][k] * b.m[k][j] + c.m[i][j]) % 1000000007;
  return c;
}
Mat operator+(const Mat &a, const Mat &b) {
  Mat c;
  c.cl();
  c.len = a.len;
  for (int i = 0; i < c.len; ++i)
    for (int j = 0; j < c.len; ++j)
      c.m[i][j] = (a.m[i][j] + b.m[i][j]) % 1000000007;
  return c;
}
Mat matrix_pow(Mat m, int n) {
  Mat e;
  e.cl();
  e.len = m.len;
  for (int i = 0; i < e.len; ++i) e.m[i][i] = 1;
  while (n) {
    if (n & 1) e = e * m;
    m = m * m;
    n >>= 1;
  }
  return e;
}
void Push_up(int node) { c[node] = c[node << 1] + c[node << 1 | 1]; }
void Push_down(int node, int l, int r) {
  if (l == r) {
    return;
  }
  if (col[node]) {
    if (col[node << 1] == 0) {
      col[node << 1] = 1;
      lazy[node << 1] = lazy[node];
      c[node << 1] = lazy[node] * c[node << 1];
    } else {
      lazy[node << 1] = lazy[node] * lazy[node << 1];
      c[node << 1] = lazy[node] * c[node << 1];
    }
    if (col[node << 1 | 1] == 0) {
      col[node << 1 | 1] = 1;
      lazy[node << 1 | 1] = lazy[node];
      c[node << 1 | 1] = lazy[node] * c[node << 1 | 1];
    } else {
      lazy[node << 1 | 1] = lazy[node] * lazy[node << 1 | 1];
      c[node << 1 | 1] = lazy[node] * c[node << 1 | 1];
    }
    col[node] = 0;
  }
}
void update(int node, int left, int right, int l, int r, Mat pp) {
  if (left >= l && right <= r) {
    if (col[node] == 1) {
      lazy[node] = pp * lazy[node];
      c[node] = pp * c[node];
    } else {
      col[node] = 1;
      lazy[node] = pp;
      c[node] = pp * c[node];
    }
    return;
  }
  Push_down(node, left, right);
  int mid = (left + right) / 2;
  if (mid >= l) update(node << 1, left, mid, l, r, pp);
  if (mid < r) update(node << 1 | 1, mid + 1, right, l, r, pp);
  Push_up(node);
}
int query(int node, int left, int right, int l, int r) {
  if (left >= l && right <= r) return c[node].m[0][0];
  int q = 0;
  Push_down(node, left, right);
  int mid = (left + right) / 2;
  if (mid >= l) q = (q + query(node << 1, left, mid, l, r)) % 1000000007;
  if (mid < r)
    q = (q + query(node << 1 | 1, mid + 1, right, l, r)) % 1000000007;
  return q;
}
void build(int node, int l, int r) {
  int x;
  lazy[node].cl();
  lazy[node].len = 2;
  col[node] = 0;
  if (l == r) {
    scanf("%d", &x);
    c[node] = matrix_pow(m, x - 1) * f;
    return;
  }
  int mid = (l + r) / 2;
  build(node << 1, l, mid);
  build(node << 1 | 1, mid + 1, r);
  Push_up(node);
}
int main() {
  int l, r, n, q, k, d;
  Mat pp;
  m.cl();
  m.len = 2;
  m.m[0][0] = m.m[0][1] = m.m[1][0] = 1;
  f.cl();
  f.len = 2;
  f.m[0][0] = 1;
  while (~scanf("%d%d", &n, &q)) {
    build(1, 1, n);
    while (q--) {
      scanf("%d", &k);
      if (k == 1) {
        scanf("%d%d%d", &l, &r, &d);
        pp = matrix_pow(m, d);
        update(1, 1, n, l, r, pp);
      } else {
        scanf("%d%d", &l, &r);
        printf("%d\n", query(1, 1, n, l, r));
      }
    }
  }
  return 0;
}
