#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;
struct Vec2 {
  long long a[2];
  Vec2() { a[0] = a[1] = 0; }
  Vec2(int x, int y) {
    a[0] = x;
    a[1] = y;
  }
  Vec2 operator+(Vec2 o) const {
    o.a[0] = (a[0] + o.a[0]) % MOD;
    o.a[1] = (a[1] + o.a[1]) % MOD;
    return o;
  }
};
struct Mat2 {
  long long m[2][2];
  Mat2() {
    m[0][0] = m[1][1] = 1;
    m[1][0] = m[0][1] = 0;
  }
  Mat2(int x1, int x2, int x3, int x4) {
    m[0][0] = x1;
    m[0][1] = x2;
    m[1][0] = x3;
    m[1][1] = x4;
  }
  Mat2 operator*(const Mat2& o) const {
    Mat2 res;
    res.m[0][0] = res.m[1][1] = 0;
    for (int i = 0; i < 2; ++i)
      for (int j = 0; j < 2; ++j)
        for (int k = 0; k < 2; ++k) {
          res.m[i][j] += (m[i][k] * o.m[k][j]) % MOD;
          res.m[i][j] %= MOD;
        }
    return res;
  }
  Vec2 operator*(Vec2 o) const {
    Vec2 res;
    res.a[0] = (o.a[0] * m[0][0] + o.a[1] * m[0][1]) % MOD;
    res.a[1] = (o.a[0] * m[1][0] + o.a[1] * m[1][1]) % MOD;
    return res;
  }
};
Mat2 mpow(Mat2 x, int st) {
  if (st == 0) return Mat2();
  Mat2 res = mpow(x, st / 2);
  res = res * res;
  if (st % 2) res = res * x;
  return res;
}
const Mat2 trMat(1, 1, 1, 0);
class SegmTree {
  vector<Vec2> tree;
  vector<Mat2> pv;
  int n;
  void build(int v, int l, int r, const vector<Vec2>& a) {
    if (l == r) {
      tree[v] = a[l];
      return;
    }
    int tm = (l + r) / 2;
    build(2 * v + 1, l, tm, a);
    build(2 * v + 2, tm + 1, r, a);
    tree[v] = tree[2 * v + 1] + tree[2 * v + 2];
  }
  void push(int v, int l, int r) {
    tree[v] = pv[v] * tree[v];
    if (l != r) {
      pv[2 * v + 1] = pv[2 * v + 1] * pv[v];
      pv[2 * v + 2] = pv[2 * v + 2] * pv[v];
    }
    pv[v] = Mat2();
  }
  Vec2 get(int v, int l, int r, int L, int R) {
    push(v, l, r);
    if (L > R) return Vec2();
    if (l == L && r == R) return tree[v];
    int tm = (l + r) / 2;
    Vec2 a = get(2 * v + 1, l, tm, L, min(R, tm));
    Vec2 b = get(2 * v + 2, tm + 1, r, max(L, tm + 1), R);
    return a + b;
  }
  void upd(int v, int l, int r, int L, int R, Mat2 x) {
    push(v, l, r);
    if (L > R) return;
    if (l == L && r == R) {
      pv[v] = x;
      push(v, l, r);
      return;
    }
    int tm = (l + r) / 2;
    upd(2 * v + 1, l, tm, L, min(R, tm), x);
    upd(2 * v + 2, tm + 1, r, max(L, tm + 1), R, x);
    tree[v] = tree[2 * v + 1] + tree[2 * v + 2];
  }

 public:
  void build(const vector<int>& x) {
    n = x.size();
    tree.assign(4 * n, Vec2());
    pv.assign(4 * n, Mat2());
    vector<Vec2> tmp(n);
    for (int i = 0; i < n; ++i) tmp[i] = mpow(trMat, x[i] - 1) * Vec2(1, 0);
    build(0, 0, n - 1, tmp);
  }
  int get(int l, int r) { return get(0, 0, n - 1, l, r).a[0]; }
  void upd(int l, int r, int x) { upd(0, 0, n - 1, l, r, mpow(trMat, x)); }
};
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  SegmTree tree;
  int n, m;
  cin >> n >> m;
  vector<int> a(n);
  for (int& x : a) cin >> x;
  tree.build(a);
  for (int i = 0; i < m; ++i) {
    int tp;
    int l, r;
    cin >> tp >> l >> r;
    --l;
    --r;
    if (tp == 1) {
      int x;
      cin >> x;
      tree.upd(l, r, x);
    } else {
      int res = tree.get(l, r);
      cout << res << endl;
    }
  }
}
