#include <bits/stdc++.h>
using namespace std;
const int Njz = 2;
const long long mod = 1e9 + 7;
struct Matrix {
  int a[2][2];
  Matrix() { memset(a, 0, sizeof(a)); }
  void init() {
    for (int i = 0; i < Njz; i++)
      for (int j = 0; j < Njz; j++) a[i][j] = (i == j);
  }
  Matrix operator+(const Matrix &B) const {
    Matrix C;
    for (int i = 0; i < Njz; i++)
      for (int j = 0; j < Njz; j++) C.a[i][j] = (a[i][j] + B.a[i][j]) % mod;
    return C;
  }
  Matrix operator*(const Matrix &B) const {
    Matrix C;
    for (int i = 0; i < Njz; i++)
      for (int k = 0; k < Njz; k++)
        for (int j = 0; j < Njz; j++)
          C.a[i][j] = (C.a[i][j] + 1LL * a[i][k] * B.a[k][j]) % mod;
    return C;
  }
  Matrix operator^(const int &t) const {
    Matrix A = (*this), res;
    res.init();
    int p = t;
    while (p) {
      if (p & 1) res = res * A;
      A = A * A;
      p >>= 1;
    }
    return res;
  }
} base, xishu;
const int N = 100005;
Matrix add[4 * N], sum[4 * N];
void pushup(int rt) { sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; }
void build(int l, int r, int i) {
  add[i].init();
  if (l == r) {
    sum[i] = base;
    return;
  }
  int mid = (l + r) >> 1;
  build(l, mid, i << 1);
  build(mid + 1, r, i << 1 | 1);
  pushup(i);
}
void pushDown(int i, int l, int r) {
  if (add[i].a[0][0] != 0) {
    int mid = (l + r) >> 1;
    add[i << 1] = add[i << 1] * add[i];
    sum[i << 1] = (sum[i << 1] * add[i]);
    add[i << 1 | 1] = (add[i << 1 | 1] * add[i]);
    sum[i << 1 | 1] = (sum[i << 1 | 1] * add[i]);
    add[i].init();
  }
}
void update(int i, int l, int r, int ql, int qr, Matrix &val) {
  if (l > qr || ql > r) return;
  if (l >= ql && r <= qr) {
    add[i] = (add[i] * val);
    sum[i] = (sum[i] * val);
    return;
  }
  pushDown(i, l, r);
  int mid = (l + r) >> 1;
  update(i << 1, l, mid, ql, qr, val);
  update(i << 1 | 1, mid + 1, r, ql, qr, val);
  pushup(i);
}
long long query(int i, int l, int r, int ql, int qr) {
  if (l > qr || ql > r) return 0;
  if (l >= ql && r <= qr) return sum[i].a[0][1];
  pushDown(i, l, r);
  int mid = (l + r) >> 1;
  return (query(i << 1, l, mid, ql, qr) +
          query(i << 1 | 1, mid + 1, r, ql, qr)) %
         mod;
}
void pre_fib() {
  base.a[0][0] = 1, base.a[0][1] = 1;
  base.a[1][0] = 0, base.a[1][1] = 0;
  xishu.a[0][0] = 1, xishu.a[0][1] = 1;
  xishu.a[1][0] = 1, xishu.a[1][1] = 0;
}
int aa[N];
int main() {
  pre_fib();
  int n, a, b, m;
  scanf("%d%d", &n, &m);
  build(1, n, 1);
  for (int i = 1; i <= n; i++) scanf("%d", &aa[i]);
  Matrix tmp;
  for (int i = 1; i <= n; i++) {
    tmp = xishu ^ (aa[i] - 1);
    update(1, 1, n, i, i, tmp);
  }
  int op, c;
  for (int i = 1; i <= m; i++) {
    scanf("%d%d%d", &op, &a, &b);
    if (op == 1) {
      scanf("%d", &c);
      tmp = xishu ^ (c);
      update(1, 1, n, a, b, tmp);
    } else
      printf("%lld\n", query(1, 1, n, a, b));
  }
  printf("\n");
  return 0;
}
