#include <bits/stdc++.h>
using namespace std;
const long long mod = 1e9 + 7;
long long n, m, a[100010];
struct Matrix {
  long long val[2][2];
  void init() {
    for (register int i = 0; i < 2; i++) {
      for (register int j = 0; j < 2; j++) {
        val[i][j] = 0;
      }
    }
  }
  void debug() {
    for (register int i = 0; i < 2; i++) {
      for (register int j = 0; j < 2; j++) {
        printf("%lld ", val[i][j]);
      }
      printf("\n");
    }
  }
} tree[400010], lazy[400010], I, ori, swi;
Matrix operator*(Matrix A, Matrix B) {
  Matrix C;
  for (register int i = 0; i < 2; i++) {
    for (register int j = 0; j < 2; j++) {
      C.val[i][j] = 0;
      for (register int k = 0; k < 2; k++) {
        C.val[i][j] = (C.val[i][j] + A.val[i][k] * B.val[k][j] % mod) % mod;
      }
    }
  }
  return C;
}
Matrix operator+(Matrix A, Matrix B) {
  Matrix C;
  for (register int i = 0; i < 2; i++) {
    for (register int j = 0; j < 2; j++) {
      C.val[i][j] = (A.val[i][j] + B.val[i][j]) % mod;
    }
  }
  return C;
}
bool operator==(Matrix A, Matrix B) {
  for (register int i = 0; i < 2; i++) {
    for (register int j = 0; j < 2; j++) {
      if (A.val[i][j] != B.val[i][j]) return false;
    }
  }
  return true;
}
Matrix fpm(Matrix x, long long y) {
  Matrix res = I;
  while (y) {
    if (y & 1) {
      res = res * x;
    }
    x = x * x;
    y >>= 1;
  }
  return res;
}
void pushdown(int id) {
  if (!(lazy[id] == I)) {
    lazy[id << 1] = lazy[id << 1] * lazy[id];
    lazy[id << 1 | 1] = lazy[id << 1 | 1] * lazy[id];
    tree[id << 1] = tree[id << 1] * lazy[id];
    tree[id << 1 | 1] = tree[id << 1 | 1] * lazy[id];
    lazy[id] = I;
  }
}
void pushup(int id) { tree[id] = tree[id << 1] + tree[id << 1 | 1]; }
void build(int id, int l, int r) {
  lazy[id] = I;
  if (l == r) {
    Matrix fucker = fpm(swi, a[l] - 1);
    tree[id] = ori * fucker;
    return;
  }
  int mid = (l + r) >> 1;
  build(id << 1, l, mid);
  build(id << 1 | 1, mid + 1, r);
  pushup(id);
}
void update(int id, int l, int r, int x, int y, Matrix v) {
  if (x <= l && r <= y) {
    tree[id] = tree[id] * v;
    lazy[id] = lazy[id] * v;
    return;
  }
  pushdown(id);
  int mid = (l + r) >> 1;
  if (x <= mid) {
    update(id << 1, l, mid, x, y, v);
  }
  if (y > mid) {
    update(id << 1 | 1, mid + 1, r, x, y, v);
  }
  pushup(id);
}
Matrix query(int id, int l, int r, int x, int y) {
  if (x <= l && r <= y) {
    return tree[id];
  }
  pushdown(id);
  int mid = (l + r) >> 1;
  Matrix res;
  res.init();
  if (x <= mid) {
    res = res + query(id << 1, l, mid, x, y);
  }
  if (y > mid) {
    res = res + query(id << 1 | 1, mid + 1, r, x, y);
  }
  return res;
}
int main() {
  scanf("%lld%lld", &n, &m);
  for (register int i = 1; i <= n; i++) {
    scanf("%lld", &a[i]);
  }
  I.val[0][0] = I.val[1][1] = 1;
  I.val[0][1] = I.val[1][0] = 0;
  ori.val[0][0] = ori.val[1][0] = ori.val[1][1] = 0;
  ori.val[0][1] = 1;
  swi.val[0][0] = 0;
  swi.val[0][1] = swi.val[1][0] = swi.val[1][1] = 1;
  build(1, 1, n);
  for (register int i = 1; i <= m; i++) {
    int op, l, r, x;
    scanf("%d", &op);
    if (op == 1) {
      scanf("%d%d%d", &l, &r, &x);
      Matrix f = fpm(swi, x);
      update(1, 1, n, l, r, f);
    } else {
      scanf("%d%d", &l, &r);
      printf("%lld\n", query(1, 1, n, l, r).val[0][1]);
    }
  }
  return 0;
}
