#include <bits/stdc++.h>
int n, m;
struct Matrix {
  long long a[2][2];
} mt[205];
Matrix mult(Matrix x, Matrix y) {
  Matrix c;
  for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++) c.a[i][j] = 0;
  for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++)
      for (int k = 0; k < 2; k++)
        c.a[i][j] = ((long long)c.a[i][j] + (long long)x.a[i][k] * y.a[k][j]) %
                    1000000007;
  return c;
}
void init(long long lim) {
  mt[0].a[0][0] = 0;
  mt[0].a[0][1] = 1;
  mt[0].a[1][0] = 1;
  mt[0].a[1][1] = 1;
  long long t = 2;
  for (int i = 1; t <= lim; i++, t <<= 1) {
    mt[i] = mult(mt[i - 1], mt[i - 1]);
  }
}
Matrix calc(long long b) {
  Matrix res;
  res.a[0][0] = 1;
  res.a[0][1] = 0;
  res.a[1][0] = 0;
  res.a[1][1] = 1;
  for (int i = 0; b; i++) {
    if (b & 1) res = mult(res, mt[i]);
    b >>= 1;
  }
  return res;
}
long long a1[800005], a2[800005], sum[800005];
Matrix prev[800005];
void update(int p) {
  a1[p] =
      (a1[p << 1] * prev[p << 1].a[0][0] + a2[p << 1] * prev[p << 1].a[0][1] +
       a1[(p << 1) + 1] * prev[(p << 1) + 1].a[0][0] +
       a2[(p << 1) + 1] * prev[(p << 1) + 1].a[0][1]) %
      1000000007;
  a2[p] =
      (a1[p << 1] * prev[p << 1].a[1][0] + a2[p << 1] * prev[p << 1].a[1][1] +
       a1[(p << 1) + 1] * prev[(p << 1) + 1].a[1][0] +
       a2[(p << 1) + 1] * prev[(p << 1) + 1].a[1][1]) %
      1000000007;
}
void pushdown(int p) {
  prev[p << 1] = mult(prev[p << 1], prev[p]);
  prev[(p << 1) + 1] = mult(prev[(p << 1) + 1], prev[p]);
  prev[p].a[0][0] = 1;
  prev[p].a[0][1] = 0;
  prev[p].a[1][0] = 0;
  prev[p].a[1][1] = 1;
  update(p);
}
void merge(int p, int l, int r, int gl, int gr, Matrix val) {
  if (l == gl && r == gr) {
    if (l == r) {
      prev[p] = mult(prev[p], val);
    } else {
      prev[p] = mult(prev[p], val);
      pushdown(p);
    }
    return;
  }
  pushdown(p);
  int mid = (l + r) >> 1;
  if (gr <= mid)
    merge(p << 1, l, mid, gl, gr, val);
  else if (gl > mid)
    merge((p << 1) + 1, mid + 1, r, gl, gr, val);
  else
    merge(p << 1, l, mid, gl, mid, val),
        merge((p << 1) + 1, mid + 1, r, mid + 1, gr, val);
  update(p);
}
long long query(int p, int l, int r, int gl, int gr) {
  if (l != r) {
    pushdown(p);
  }
  if (l == gl && r == gr) {
    return (a1[p] * prev[p].a[0][0] + a2[p] * prev[p].a[0][1]) % 1000000007;
  }
  int mid = (l + r) >> 1;
  if (gr <= mid)
    return query(p << 1, l, mid, gl, gr);
  else if (gl > mid)
    return query((p << 1) + 1, mid + 1, r, gl, gr);
  else
    return (query(p << 1, l, mid, gl, mid) +
            query((p << 1) + 1, mid + 1, r, mid + 1, gr)) %
           1000000007;
  update(p);
}
int it[800005];
void build(int p, int l, int r) {
  prev[p].a[0][0] = 1;
  prev[p].a[0][1] = 0;
  prev[p].a[1][0] = 0;
  prev[p].a[1][1] = 1;
  if (l == r) {
    if (it[l] == 1)
      a1[p] = a2[p] = 1;
    else {
      Matrix r = calc(it[l] - 1);
      a1[p] = (r.a[0][0] + r.a[0][1]) % 1000000007;
      a2[p] = (r.a[1][0] + r.a[1][1]) % 1000000007;
    }
    return;
  }
  int mid = (l + r) >> 1;
  build(p << 1, l, mid);
  build((p << 1) + 1, mid + 1, r);
  update(p);
}
int main() {
  scanf("%d%d", &n, &m);
  init(10000000000000000ll);
  for (int i = 1; i <= n; i++) scanf("%d", &it[i]);
  build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    int tp;
    scanf("%d", &tp);
    if (tp == 1) {
      int l, r, x;
      scanf("%d%d%d", &l, &r, &x);
      merge(1, 1, n, l, r, calc(x));
    } else {
      int l, r;
      scanf("%d%d", &l, &r);
      printf("%I64d\n", query(1, 1, n, l, r) % 1000000007);
    }
  }
}
