#include <bits/stdc++.h>
using namespace std;
const long long mod = 1000000007;
struct Matrix {
  long long a[4];
  void init() {
    a[0] = 1;
    a[1] = 0;
    a[2] = 0;
    a[3] = 1;
  }
  void Finit() {
    a[0] = 1;
    a[1] = 1;
    a[2] = 1;
    a[3] = 0;
  }
  void clr() { memset(a, 0, sizeof(a)); }
  bool pss() { return (a[0] != 1 || a[1] != 0 || a[2] != 0 || a[3] != 1); }
  void Mplus(const Matrix b) {
    a[0] = (a[0] + b.a[0]) % mod;
    a[1] = (a[1] + b.a[1]) % mod;
    a[2] = (a[2] + b.a[2]) % mod;
    a[3] = (a[3] + b.a[3]) % mod;
  }
  void Msum(const Matrix c, const Matrix b) {
    a[0] = (c.a[0] + b.a[0]) % mod;
    a[1] = (c.a[1] + b.a[1]) % mod;
    a[2] = (c.a[2] + b.a[2]) % mod;
    a[3] = (c.a[3] + b.a[3]) % mod;
  }
  Matrix operator+(const Matrix b) {
    Matrix ans;
    ans.a[0] = (a[0] + b.a[0]) % mod;
    ans.a[1] = (a[1] + b.a[1]) % mod;
    ans.a[2] = (a[2] + b.a[2]) % mod;
    ans.a[3] = (a[3] + b.a[3]) % mod;
    return ans;
  }
  void Mmul(const Matrix b) {
    Matrix ans;
    ans.a[0] = (a[0] * b.a[0] + a[1] * b.a[2]) % mod;
    a[1] = (a[0] * b.a[1] + a[1] * b.a[3]) % mod;
    ans.a[2] = (a[2] * b.a[0] + a[3] * b.a[2]) % mod;
    a[3] = (a[2] * b.a[1] + a[3] * b.a[3]) % mod;
    a[0] = ans.a[0];
    a[2] = ans.a[2];
  }
} tr[400040], lazy[400040] = {0}, ttt;
int a[100005];
inline Matrix Mqpow(int n) {
  Matrix a;
  ttt.init();
  a.Finit();
  while (n) {
    if (n % 2) ttt.Mmul(a);
    a.Mmul(a);
    n >>= 1;
  }
  return ttt;
}
void buildtree(int l, int r, int x) {
  lazy[x].a[0] = 1;
  lazy[x].a[3] = 1;
  if (l == r) {
    tr[x] = Mqpow(a[l]);
    return;
  }
  int m = (l + r) >> 1;
  buildtree(l, m, x << 1);
  buildtree(m + 1, r, x << 1 | 1);
  tr[x].Msum(tr[x << 1], tr[x << 1 | 1]);
}
void pushdown(int x) {
  if (lazy[x].pss()) {
    tr[x << 1].Mmul(lazy[x]);
    tr[x << 1 | 1].Mmul(lazy[x]);
    lazy[x << 1].Mmul(lazy[x]);
    lazy[x << 1 | 1].Mmul(lazy[x]);
    lazy[x].init();
  }
}
void segmod(int L, int R, int val, int l, int r, int x) {
  if (L == l && R == r) {
    Mqpow(val);
    tr[x].Mmul(ttt);
    lazy[x].Mmul(ttt);
    return;
  }
  pushdown(x);
  int m = (l + r) >> 1;
  if (m >= R)
    segmod(L, R, val, l, m, x << 1);
  else if (m < L)
    segmod(L, R, val, m + 1, r, x << 1 | 1);
  else {
    segmod(L, m, val, l, m, x << 1);
    segmod(m + 1, R, val, m + 1, r, x << 1 | 1);
  }
  tr[x].Msum(tr[x << 1], tr[x << 1 | 1]);
}
Matrix query(int L, int R, int l, int r, int x) {
  if (L == l && R == r) {
    return tr[x];
  }
  pushdown(x);
  int m = (l + r) >> 1;
  if (m >= R)
    return query(L, R, l, m, x << 1);
  else if (m < L)
    return query(L, R, m + 1, r, x << 1 | 1);
  else
    return query(L, m, l, m, x << 1) + query(m + 1, R, m + 1, r, x << 1 | 1);
}
void otp(Matrix tmp) { printf("%I64d\n", tmp.a[1]); }
int main() {
  int n, m, i, cc, ll, rr, xx;
  scanf("%d%d", &n, &m);
  for (i = 1; i <= n; i++) scanf("%d", &a[i]);
  buildtree(1, n, 1);
  for (i = 0; i < m; i++) {
    scanf("%d%d%d", &cc, &ll, &rr);
    if (cc == 1) {
      scanf("%d", &xx);
      segmod(ll, rr, xx, 1, n, 1);
    } else
      otp(query(ll, rr, 1, n, 1));
  }
  return 0;
}
