#include <bits/stdc++.h>
using namespace std;
const long long N = 100000 + 20;
const long long MOD = 1e9 + 7;
long long n, m, val[N];
struct Matrix {
  long long m[4][4];
  inline void clear() {
    for (long long i = 0; i < 4; i++)
      for (long long j = 0; j < 4; j++) m[i][j] = 0;
  }
  inline void init() {
    for (long long i = 0; i < 4; i++) m[i][i] = 1;
  }
  bool empty() {
    return ((m[1][1] != 1) || (m[1][2] != 0) || (m[2][1] != 0) ||
            (m[2][2] != 1))
               ? 0
               : 1;
  }
  Matrix operator*(const Matrix &x) const {
    Matrix a;
    a.clear();
    for (long long i = 1; i <= 2; i++)
      for (long long k = 1; k <= 2; k++)
        for (long long j = 1; j <= 2; j++)
          a.m[i][j] = (a.m[i][j] + m[i][k] * x.m[k][j]) % MOD;
    return a;
  }
  friend Matrix operator+(Matrix a, Matrix b) {
    Matrix x;
    x.clear();
    for (long long i = 1; i <= 2; i++)
      for (long long j = 1; j <= 2; j++)
        x.m[i][j] = (a.m[i][j] + b.m[i][j]) % MOD;
    return x;
  }
} node[N << 2], lazy[N << 2], first_blood, second;
void pre() {
  first_blood.clear();
  second.clear();
  first_blood.m[1][1] = 1;
  second.m[1][1] = 1;
  first_blood.m[1][2] = 1;
  second.m[1][2] = 1;
  first_blood.m[2][1] = 0;
  second.m[2][1] = 1;
  first_blood.m[2][2] = 0;
  second.m[2][2] = 0;
}
Matrix quick_pow(Matrix a, long long b) {
  Matrix ans;
  ans.clear();
  ans.init();
  while (b) {
    if (b & 1) ans = ans * a;
    a = a * a;
    b >>= 1;
  }
  return ans;
}
void update(long long o) { node[o] = node[o << 1] + node[o << 1 | 1]; }
void build(long long o, long long l, long long r) {
  node[o].clear();
  lazy[o].clear();
  lazy[o].init();
  if (l == r) {
    node[o] = first_blood * quick_pow(second, val[l] - 1);
    return;
  }
  long long mid = l + r >> 1;
  build(o << 1, l, mid);
  build(o << 1 | 1, mid + 1, r);
  update(o);
}
void push_down(long long o) {
  node[o << 1] = node[o << 1] * lazy[o];
  lazy[o << 1] = lazy[o << 1] * lazy[o];
  node[o << 1 | 1] = node[o << 1 | 1] * lazy[o];
  lazy[o << 1 | 1] = lazy[o << 1 | 1] * lazy[o];
  lazy[o].clear();
  lazy[o].init();
}
void modify(long long o, long long l, long long r, long long ql, long long qr,
            Matrix x) {
  if (ql <= l && r <= qr) {
    node[o] = node[o] * x;
    lazy[o] = lazy[o] * x;
    return;
  }
  if (!lazy[o].empty()) push_down(o);
  long long mid = l + r >> 1;
  if (ql <= mid) modify(o << 1, l, mid, ql, qr, x);
  if (mid < qr) modify(o << 1 | 1, mid + 1, r, ql, qr, x);
  update(o);
}
Matrix query(long long o, long long l, long long r, long long ql,
             long long qr) {
  if (ql <= l && r <= qr) return node[o];
  if (!lazy[o].empty()) push_down(o);
  long long mid = l + r >> 1;
  Matrix x;
  x.clear();
  if (ql <= mid) x = x + query(o << 1, l, mid, ql, qr);
  if (mid < qr) x = x + query(o << 1 | 1, mid + 1, r, ql, qr);
  return x;
}
signed main() {
  scanf("%lld%lld", &n, &m);
  pre();
  for (long long i = 1; i <= n; i++) scanf("%lld", &val[i]);
  build(1, 1, n);
  long long k, l, r, x;
  for (long long i = 1; i <= m; i++) {
    scanf("%lld", &k);
    if (k == 1) {
      scanf("%lld%lld%lld", &l, &r, &x);
      modify(1, 1, n, l, r, quick_pow(second, x));
    } else {
      scanf("%lld%lld", &l, &r);
      printf("%lld\n", query(1, 1, n, l, r).m[1][2] % MOD);
    }
  }
}
