#include <bits/stdc++.h>
using namespace std;
const int64_t M = 1e9 + 7, N = 1e5 + 5;
struct node {
  int64_t v1, v2;
};
node t[2 * N];
int64_t d[N][4];
int64_t n, h;
node combine(node l, node r) {
  node tmp;
  tmp.v1 = (l.v1 % M + r.v1 % M) % M;
  tmp.v2 = (l.v2 % M + r.v2 % M) % M;
  return tmp;
}
void multiply(int64_t F[2][2], int64_t MM[2][2]) {
  int64_t a = (F[0][0] * MM[0][0]) % M + (F[0][1] * MM[1][0]) % M;
  int64_t b = (F[0][0] * MM[0][1]) % M + (F[0][1] * MM[1][1]) % M;
  int64_t c = (F[1][0] * MM[0][0]) % M + (F[1][1] * MM[1][0]) % M;
  int64_t d = (F[1][0] * MM[0][1]) % M + (F[1][1] * MM[1][1]) % M;
  F[0][0] = a % M;
  F[0][1] = b % M;
  F[1][0] = c % M;
  F[1][1] = d % M;
}
void apply(int64_t p, int64_t value[2][2]) {
  int64_t x1 = (t[p].v1 * value[0][0]) % M + (t[p].v2 * value[1][0]) % M;
  int64_t x2 = (t[p].v1 * value[0][1]) % M + (t[p].v2 * value[1][1]) % M;
  t[p].v1 = x1 % M;
  t[p].v2 = x2 % M;
  if (p < n) {
    int64_t temp[2][2] = {{d[p][0], d[p][1]}, {d[p][2], d[p][3]}};
    multiply(temp, value);
    d[p][0] = temp[0][0], d[p][1] = temp[0][1], d[p][2] = temp[1][0],
    d[p][3] = temp[1][1];
  }
}
void build() {
  for (int64_t i = n - 1; i > 0; --i) t[i] = combine(t[i << 1], t[i << 1 | 1]);
}
void build(int64_t p) {
  while (p > 1) {
    p >>= 1;
    t[p] = combine(t[p << 1], t[p << 1 | 1]);
    if (d[p][0] == 1 && d[p][1] == 0 && d[p][2] == 0 && d[p][3] == 1)
      ;
    else {
      int64_t x1 = (t[p].v1 * d[p][0]) % M + (t[p].v2 * d[p][2]) % M;
      int64_t x2 = (t[p].v1 * d[p][1]) % M + (t[p].v2 * d[p][3]) % M;
      t[p].v1 = x1 % M;
      t[p].v2 = x2 % M;
    }
  }
}
void push(int64_t p) {
  for (int64_t s = h; s > 0; --s) {
    int64_t i = p >> s;
    if (d[i][0] == 1 && d[i][1] == 0 && d[i][2] == 0 && d[i][3] == 1)
      ;
    else {
      int64_t value[2][2] = {{d[i][0], d[i][1]}, {d[i][2], d[i][3]}};
      apply(i << 1, value);
      apply(i << 1 | 1, value);
      d[i][0] = 1, d[i][1] = 0, d[i][2] = 0, d[i][3] = 1;
    }
  }
}
void update(int64_t l, int64_t r, int64_t value[2][2]) {
  l += n, r += n;
  int64_t l0 = l, r0 = r;
  for (; l < r; l >>= 1, r >>= 1) {
    if (l & 1) apply(l++, value);
    if (r & 1) apply(--r, value);
  }
  build(l0);
  build(r0 - 1);
}
node query(int64_t l, int64_t r) {
  l += n, r += n;
  push(l);
  push(r - 1);
  node resl = {0, 0};
  node resr = {0, 0};
  for (; l < r; l >>= 1, r >>= 1) {
    if (l & 1) resl = combine(resl, t[l++]);
    if (r & 1) resr = combine(t[--r], resr);
  }
  return combine(resl, resr);
}
void power(int64_t F[2][2], int64_t n) {
  if (n == 0 || n == 1) return;
  int64_t MM[2][2] = {{1, 1}, {1, 0}};
  power(F, n / 2);
  multiply(F, F);
  if (n % 2 != 0) multiply(F, MM);
}
int64_t fibonacci_matrix(int64_t n) {
  int64_t F[2][2] = {{1, 1}, {1, 0}};
  if (n == 0) return 0;
  power(F, n - 1);
  return F[0][0];
}
int main() {
  ios::sync_with_stdio(false), cin.tie(nullptr);
  for (int64_t i = 0; i < N; i++) d[i][0] = d[i][3] = 1;
  int64_t q;
  cin >> n >> q;
  for (int64_t i = 0; i < n; ++i) {
    int64_t x;
    cin >> x;
    t[n + i] = {fibonacci_matrix(x), fibonacci_matrix(x - 1)};
  }
  build();
  h = sizeof(int64_t) * 8 - __builtin_clz(n);
  while (q--) {
    int64_t tp, l, r;
    cin >> tp >> l >> r;
    if (tp == 1) {
      int64_t x;
      cin >> x;
      int64_t F[2][2] = {{1, 1}, {1, 0}};
      power(F, x);
      update(l - 1, r, F);
    } else {
      cout << query(l - 1, r).v1 << "\n";
    }
  }
}
