#include <bits/stdc++.h>
using namespace std;
const long long N = 1e5 + 12;
const long long D = 2;
const long long mod = 1000000007;
long long niz[N];
struct Matrix {
  long long a[D][D];
  Matrix() { a[0][0] = a[0][1] = a[1][0] = a[1][1] = 0; }
};
Matrix operator*(Matrix a, Matrix b) {
  Matrix ans;
  for (int i = 0; i < D; i++) {
    for (int k = 0; k < D; k++) {
      for (int j = 0; j < D; j++) {
        ans.a[i][j] += a.a[i][k] * b.a[k][j];
        ans.a[i][j] %= mod;
      }
    }
  }
  return ans;
}
Matrix operator+(Matrix a, Matrix b) {
  Matrix ans;
  for (int i = 0; i < D; i++) {
    for (int j = 0; j < D; j++) {
      ans.a[i][j] = a.a[i][j] + b.a[i][j];
      ans.a[i][j] %= mod;
    }
  }
  return ans;
}
Matrix mpow(Matrix a, long long p) {
  Matrix ans;
  for (int i = 0; i < D; i++) {
    ans.a[i][i] = 1;
  }
  while (p) {
    if (p & 1) {
      ans = ans * a;
    }
    a = a * a;
    p >>= 1;
  }
  return ans;
}
Matrix fib() {
  Matrix a;
  a.a[0][0] = a.a[0][1] = a.a[1][0] = 1;
  return a;
}
Matrix jedinicna() {
  Matrix a;
  a.a[0][0] = a.a[1][1] = 1;
  return a;
}
Matrix nula() {
  Matrix a;
  a.a[0][0] = a.a[0][1] = a.a[1][0] = a.a[1][1] = 0;
  return a;
}
Matrix drvo[4 * N], lazy[4 * N];
void build(long long i, long long j, long long node) {
  if (i == j) {
    drvo[node] = mpow(fib(), niz[i]);
    lazy[node] = jedinicna();
    return;
  }
  long long mid = i + (j - i) / 2;
  build(i, mid, 2 * node + 1);
  build(mid + 1, j, 2 * node + 2);
  drvo[node] = drvo[2 * node + 1] + drvo[2 * node + 2];
  lazy[node] = jedinicna();
}
void push(long long i, long long j, long long node) {
  drvo[node] = drvo[node] * lazy[node];
  if (i != j) {
    lazy[2 * node + 1] = lazy[2 * node + 1] * lazy[node];
    lazy[2 * node + 2] = lazy[2 * node + 2] * lazy[node];
  }
  lazy[node] = jedinicna();
}
void update(long long i, long long j, long long l, long long r, long long node,
            Matrix v) {
  push(i, j, node);
  if (j < l || i > r) {
    return;
  }
  if (l <= i && r >= j) {
    lazy[node] = lazy[node] * v;
    push(i, j, node);
    return;
  }
  long long mid = i + (j - i) / 2;
  update(i, mid, l, r, 2 * node + 1, v);
  update(mid + 1, j, l, r, 2 * node + 2, v);
  drvo[node] = drvo[2 * node + 1] + drvo[2 * node + 2];
}
Matrix get(long long i, long long j, long long l, long long r, long long node) {
  push(i, j, node);
  if (j < l || i > r) {
    return nula();
  }
  if (l <= i && r >= j) {
    return drvo[node];
  }
  long long mid = i + (j - i) / 2;
  Matrix m1 = get(i, mid, l, r, 2 * node + 1);
  Matrix m2 = get(mid + 1, j, l, r, 2 * node + 2);
  return m1 + m2;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  long long n, m;
  cin >> n >> m;
  for (long i = 1; i <= n; i++) {
    cin >> niz[i];
  }
  build(1, n, 0);
  while (m--) {
    long long t, l, r;
    cin >> t >> l >> r;
    if (t == 1) {
      long long x;
      cin >> x;
      Matrix t = mpow(fib(), x);
      update(1, n, l, r, 0, t);
    } else {
      Matrix m = get(1, n, l, r, 0);
      cout << m.a[0][1] << endl;
    }
  }
}
