#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000000 + 7, N = 100500;
int n, q;
struct Matrix {
  long long a[2][2];
  Matrix() { memset(a, 0, sizeof a); }
  void clear() { memset(a, 0, sizeof a); }
  void operator*=(const Matrix &T) {
    Matrix res;
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 2; ++j) {
        for (int k = 0; k < 2; ++k) {
          res.a[i][j] += a[i][k] * T.a[k][j];
        }
      }
    }
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 2; ++j) {
        a[i][j] = res.a[i][j] % mod;
      }
    }
  }
  Matrix operator*(const Matrix &T) {
    Matrix res;
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 2; ++j) {
        for (int k = 0; k < 2; ++k) {
          res.a[i][j] += a[i][k] * T.a[k][j];
        }
        res.a[i][j] %= mod;
      }
    }
    return res;
  }
  Matrix operator+(const Matrix &T) {
    Matrix res;
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 2; ++j) {
        res.a[i][j] = (a[i][j] + T.a[i][j]);
        if (res.a[i][j] >= mod) res.a[i][j] -= mod;
      }
    }
    return res;
  }
  void operator*=(int x) {
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 2; ++j) {
        a[i][j] = (a[i][j] * x) % mod;
      }
    }
  }
  void operator+=(const Matrix &T) {
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 2; ++j) {
        a[i][j] += T.a[i][j];
        if (a[i][j] >= mod) a[i][j] -= mod;
      }
    }
  }
  bool operator==(const Matrix &T) {
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 2; ++j) {
        if (a[i][j] != T.a[i][j]) return 0;
      }
    }
    return 1;
  }
  void out() {
    for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 2; ++j) {
        cout << a[i][j] << " ";
      }
      cout << endl;
    }
    cout << endl;
  }
} first, empty;
struct Tree {
  Matrix m, add;
  Tree() {
    add.clear();
    add.a[0][0] = add.a[1][1] = 1;
  }
} t[4 * N];
int nn = 1;
inline Matrix Merge(Matrix A, Matrix B) { return A + B; }
inline Matrix MyGet(Matrix now, int x) {
  Matrix a;
  a.a[0][0] = a.a[1][1] = 1;
  while (x) {
    if (x & 1) a *= now;
    now *= now;
    x >>= 1;
  }
  return a;
}
inline void push(int v, int tl, int tr) {
  if (v + v <= nn + nn - 1) t[v + v].add *= t[v].add;
  if (v + v + 1 <= nn + nn - 1) t[v + v + 1].add *= t[v].add;
  t[v].m *= t[v].add;
  t[v].add.clear();
  t[v].add.a[0][0] = t[v].add.a[1][1] = 1;
}
void upd(int l, int r, const Matrix &CUR, int v = 1, int tl = 1, int tr = nn) {
  push(v, tl, tr);
  if (l > r || l > tr || tl > r) return;
  if (l <= tl && tr <= r) {
    t[v].add *= CUR;
    push(v, tl, tr);
    return;
  }
  int mid = (tl + tr) >> 1;
  upd(l, r, CUR, v + v, tl, mid);
  upd(l, r, CUR, v + v + 1, mid + 1, tr);
  t[v].m = Merge(t[v + v].m, t[v + v + 1].m);
}
Matrix get(int l, int r, int v = 1, int tl = 1, int tr = nn) {
  push(v, tl, tr);
  if (l > r || l > tr || tl > r) return empty;
  if (l <= tl && tr <= r) {
    return t[v].m;
  }
  int mid = (tl + tr) >> 1;
  return Merge(get(l, r, v + v, tl, mid), get(l, r, v + v + 1, mid + 1, tr));
}
int main() {
  first.a[0][0] = 1;
  first.a[1][0] = 1;
  first.a[0][1] = 1;
  scanf("%d%d", &n, &q);
  while (nn < n) nn <<= 1;
  for (int i = 1; i <= n; ++i) {
    int x;
    scanf("%d", &x);
    t[i + nn - 1].m = MyGet(first, x);
  }
  for (int i = nn - 1; i > 0; --i) t[i].m = Merge(t[i + i].m, t[i + i + 1].m);
  while (q--) {
    int type;
    scanf("%d", &type);
    if (type == 1) {
      int l, r, x;
      scanf("%d%d%d", &l, &r, &x);
      upd(l, r, MyGet(first, x));
    } else {
      int l, r;
      scanf("%d%d", &l, &r);
      Matrix ans = get(l, r);
      printf("%lld\n", ans.a[0][1]);
    }
  }
  return 0;
}
