#include <bits/stdc++.h>
using namespace std;
const int N = 1E5 + 10;
const int base = 1E9 + 7;
struct Matrix {
  int n, m;
  int d[2][2];
  Matrix(int _n = 0, int _m = 0) {
    n = _n;
    m = _m;
    memset(d, 0, sizeof(d));
  }
  Matrix operator+(const Matrix &a) const {
    Matrix c = (*this);
    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++) c.d[i][j] = (c.d[i][j] + a.d[i][j]) % base;
    return c;
  }
  Matrix operator*(const Matrix &a) const {
    int x = n, y = m, z = a.m;
    Matrix c(x, z);
    for (int i = 0; i < x; i++)
      for (int j = 0; j < z; j++)
        for (int k = 0; k < y; k++) {
          c.d[i][j] += (long long)d[i][k] * a.d[k][j] % base;
          c.d[i][j] %= base;
        }
    return c;
  }
  Matrix operator^(int k) const {
    Matrix ret, mul = (*this);
    bool foo = 1;
    while (k > 0) {
      if (k & 1) ret = foo ? mul : ret * mul, foo = 0;
      mul = mul * mul;
      k >>= 1;
    }
    return ret;
  }
};
int n, q, a[N];
Matrix fib(2, 2), non(2, 2), self(2, 2);
struct SegmentTree {
  Matrix sum[N * 4], lazy[N * 4];
  void Build(int id, int l, int r) {
    lazy[id] = self;
    if (l == r) {
      sum[id] = fib ^ a[l];
      return;
    }
    Build(id << 1, l, (l + r) / 2);
    Build(id << 1 | 1, (l + r) / 2 + 1, r);
    sum[id] = sum[id << 1] + sum[id << 1 | 1];
  }
  void Down(int id) {
    lazy[id << 1] = lazy[id << 1] * lazy[id];
    lazy[id << 1 | 1] = lazy[id << 1 | 1] * lazy[id];
    sum[id << 1] = sum[id << 1] * lazy[id];
    sum[id << 1 | 1] = sum[id << 1 | 1] * lazy[id];
    lazy[id] = self;
  }
  void Update(int id, int l, int r, int u, int v, Matrix val) {
    if (v < l || r < u || l > r) return;
    if (u <= l && r <= v) {
      lazy[id] = lazy[id] * val;
      sum[id] = sum[id] * val;
      return;
    }
    Down(id);
    if (u <= (l + r) / 2) Update(id << 1, l, (l + r) / 2, u, v, val);
    if ((l + r) / 2 + 1 <= v)
      Update(id << 1 | 1, (l + r) / 2 + 1, r, u, v, val);
    sum[id] = sum[id << 1] + sum[id << 1 | 1];
  }
  int Query(int id, int l, int r, int u, int v) {
    if (v < l || r < u || l > r) return 0;
    if (u <= l && r <= v) return sum[id].d[1][0];
    Down(id);
    return (Query(id << 1, l, (l + r) / 2, u, v) +
            Query(id << 1 | 1, (l + r) / 2 + 1, r, u, v)) %
           base;
  }
  void Update(int u, int v, Matrix val) { Update(1, 1, n, u, v, val); }
  int Query(int u, int v) { return Query(1, 1, n, u, v); }
} ST;
void Read_Input() {
  scanf("%d%d", &n, &q);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
}
void Init() {
  fib.d[0][0] = fib.d[0][1] = fib.d[1][0] = 1;
  self.d[0][0] = self.d[1][1] = 1;
  ST.Build(1, 1, n);
}
void Solve() {
  while (q--) {
    int type, l, r;
    scanf("%d%d%d", &type, &l, &r);
    if (type == 1) {
      int val;
      scanf("%d", &val);
      ST.Update(l, r, fib ^ val);
    } else
      printf("%d\n", ST.Query(l, r));
  }
}
int main() {
  Read_Input();
  Init();
  Solve();
  return 0;
}
