#include <bits/stdc++.h>
using namespace std;
const int maxn = 100005;
const int MOD = (int)1e9 + 7;
int a[maxn];
struct Matrix {
  int d[2][2];
  Matrix() { memset(d, 0, sizeof(d)); }
  Matrix operator*(const Matrix &I) const {
    Matrix ans;
    for (int k = 0; k < 2; k++) {
      for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
          ans.d[i][j] += (long long)d[i][k] * I.d[k][j] % MOD;
          if (ans.d[i][j] >= MOD) ans.d[i][j] -= MOD;
        }
      }
    }
    return ans;
  }
  bool operator==(const Matrix &I) const {
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2; j++) {
        if (d[i][j] != I.d[i][j]) return false;
      }
    }
    return true;
  }
  void operator*=(const Matrix &I) { *this = *this * I; }
};
Matrix A, I;
Matrix modExp(Matrix a, long long b) {
  Matrix t = I;
  Matrix y = a;
  while (b) {
    if (b & 1) t = t * y;
    y = y * y;
    b >>= 1;
  }
  return t;
}
struct SegTree {
  int left, right, vec[2];
  Matrix lazy;
} T[maxn << 2];
int Fib(int x) {
  x--;
  Matrix ansm = modExp(A, x);
  return (ansm.d[0][0] + ansm.d[1][0]) % MOD;
}
void multi(int &p, int &q, Matrix y) {
  long long tx = (long long)p * y.d[0][0] + (long long)q * y.d[1][0];
  long long ty = (long long)p * y.d[0][1] + (long long)q * y.d[1][1];
  p = tx % MOD;
  q = ty % MOD;
}
void push_down(int t) {
  T[(t << 1)].lazy *= T[t].lazy;
  T[(t << 1 | 1)].lazy *= T[t].lazy;
  multi(T[(t << 1)].vec[0], T[(t << 1)].vec[1], T[t].lazy);
  multi(T[(t << 1 | 1)].vec[0], T[(t << 1 | 1)].vec[1], T[t].lazy);
  T[t].lazy = I;
}
void push_up(int t) {
  T[t].vec[0] = (T[(t << 1)].vec[0] + T[(t << 1 | 1)].vec[0]) % MOD;
  T[t].vec[1] = (T[(t << 1)].vec[1] + T[(t << 1 | 1)].vec[1]) % MOD;
}
void build(int l, int r, int t = 1) {
  T[t].left = l;
  T[t].right = r;
  T[t].lazy = I;
  if (l == r) {
    T[t].vec[0] = Fib(a[l]);
    T[t].vec[1] = Fib(a[l] + 1);
    return;
  }
  int mid = (l + r) >> 1;
  build(l, mid, (t << 1));
  build(mid + 1, r, (t << 1 | 1));
  push_up(t);
}
void update(int l, int r, Matrix x, int t = 1) {
  if (T[t].left == l && T[t].right == r) {
    T[t].lazy *= x;
    multi(T[t].vec[0], T[t].vec[1], x);
    return;
  }
  push_down(t);
  if (r <= T[(t << 1)].right) {
    update(l, r, x, (t << 1));
  } else if (l >= T[(t << 1 | 1)].left) {
    update(l, r, x, (t << 1 | 1));
  } else {
    update(l, T[(t << 1)].right, x, (t << 1));
    update(T[(t << 1 | 1)].left, r, x, (t << 1 | 1));
  }
  push_up(t);
}
int query(int l, int r, int t = 1) {
  if (T[t].left == l && T[t].right == r) {
    return T[t].vec[0];
  }
  push_down(t);
  if (r <= T[(t << 1)].right) {
    return query(l, r, (t << 1));
  } else if (l >= T[(t << 1 | 1)].left) {
    return query(l, r, (t << 1 | 1));
  } else {
    return (query(l, T[(t << 1)].right, (t << 1)) +
            query(T[(t << 1 | 1)].left, r, (t << 1 | 1))) %
           MOD;
  }
}
int main() {
  A.d[0][1] = A.d[1][0] = A.d[1][1] = 1;
  I.d[0][0] = I.d[1][1] = 1;
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  build(1, n);
  int tp, l, r, x;
  while (m--) {
    scanf("%d%d%d", &tp, &l, &r);
    if (tp == 1) {
      scanf("%d", &x);
      Matrix y = modExp(A, x);
      update(l, r, y);
    } else {
      printf("%d\n", query(l, r));
    }
  }
  return 0;
}
