#include <bits/stdc++.h>
using namespace std;
int n, m, x[100005], tpi, li, ri, xi;
struct matrix {
  int n, m, a[2][2];
};
void print(matrix c) {
  for (int i = 0; i < c.n; i++) {
    for (int j = 0; j < c.m; j++) cout << c.a[i][j] << ' ';
    cout << endl;
  }
  cout << "******" << endl;
}
matrix operator+(const matrix &a, const matrix &b) {
  matrix c;
  c.n = a.n;
  c.m = a.m;
  memset(c.a, 0, sizeof c.a);
  for (int i = 0; i < c.n; i++)
    for (int j = 0; j < c.m; j++) {
      c.a[i][j] = (a.a[i][j] + b.a[i][j]);
      if (c.a[i][j] >= 1000000007) c.a[i][j] -= 1000000007;
    }
  return c;
}
matrix operator*(const matrix &a, const matrix &b) {
  matrix c;
  c.n = a.n;
  c.m = b.m;
  memset(c.a, 0, sizeof c.a);
  for (int k = 0; k < a.m; k++)
    for (int i = 0; i < c.n; i++)
      for (int j = 0; j < c.m; j++) {
        c.a[i][j] += ((long long)a.a[i][k] * b.a[k][j]) % 1000000007;
        if (c.a[i][j] >= 1000000007) c.a[i][j] -= 1000000007;
      }
  return c;
}
matrix modpow(const matrix &a, int p) {
  if (p == 0) {
    matrix c;
    c.n = a.n;
    c.m = a.m;
    for (int i = 0; i < c.n; i++)
      for (int j = 0; j < c.m; j++) c.a[i][j] = (i == j);
    return c;
  } else if ((p % 2) == 1) {
    return a * modpow(a, p - 1);
  } else {
    matrix c = modpow(a, p / 2);
    return c * c;
  }
}
matrix I, lazy[4 * 100005], tree[4 * 100005], trans, cur_trans;
void build(int i, int L, int R) {
  lazy[i] = I;
  if (L == R) {
    tree[i].n = 2;
    tree[i].m = 1;
    tree[i].a[0][0] = 1;
    tree[i].a[1][0] = 0;
    tree[i] = modpow(trans, x[L] - 1) * tree[i];
  } else {
    int mid = (L + R) / 2;
    build(2 * i, L, mid);
    build(2 * i + 1, mid + 1, R);
    tree[i] = tree[2 * i] + tree[2 * i + 1];
  }
}
void push(int i, int L, int R) {
  if (2 * i < 4 * 100005) {
    lazy[2 * i] = lazy[2 * i] * lazy[i];
  }
  if (2 * i + 1 < 4 * 100005) {
    lazy[2 * i + 1] = lazy[2 * i + 1] * lazy[i];
  }
  tree[i] = lazy[i] * tree[i];
  lazy[i] = I;
}
matrix query(int i, int L, int R, int p, int q) {
  push(i, L, R);
  if ((p <= L) && (R <= q)) return tree[i];
  if ((R < p) || (q < L)) {
    matrix c;
    c.n = 2;
    c.m = 1;
    c.a[0][0] = c.a[1][0] = 0;
    return c;
  }
  int mid = (L + R) / 2;
  return query(2 * i, L, mid, p, q) + query(2 * i + 1, mid + 1, R, p, q);
}
void update(int i, int L, int R, int p, int q, int x) {
  push(i, L, R);
  if ((p <= L) && (R <= q)) {
    lazy[i] = lazy[i] * cur_trans;
    push(i, L, R);
    return;
  }
  if ((R < p) || (q < L)) return;
  int mid = (L + R) / 2;
  update(2 * i, L, mid, p, q, x);
  update(2 * i + 1, mid + 1, R, p, q, x);
  tree[i] = tree[2 * i] + tree[2 * i + 1];
}
int main() {
  scanf("%d %d", &n, &m);
  for (int i = 0; i < n; i++) {
    scanf("%d", &x[i]);
  }
  trans.n = 2;
  trans.m = 2;
  trans.a[0][0] = 1, trans.a[0][1] = 1;
  trans.a[1][0] = 1, trans.a[1][1] = 0;
  I.n = 2;
  I.m = 2;
  I.a[0][0] = 1, I.a[0][1] = 0;
  I.a[1][0] = 0, I.a[1][1] = 1;
  matrix c;
  c.n = 2;
  c.m = 1;
  c.a[0][0] = 1, c.a[1][0] = 0;
  build(1, 0, n - 1);
  while (m--) {
    scanf("%d", &tpi);
    if (tpi == 1) {
      scanf("%d %d %d", &li, &ri, &xi);
      li--, ri--;
      cur_trans = modpow(trans, xi);
      update(1, 0, n - 1, li, ri, xi);
    } else {
      scanf("%d %d", &li, &ri);
      li--, ri--;
      matrix r = query(1, 0, n - 1, li, ri);
      printf("%d\n", r.a[0][0]);
    }
  }
  return 0;
}
