#include <bits/stdc++.h>
using namespace std;
const long long mod = 1e9 + 7;
struct Matrix {
  long long a, b, c, d;
  Matrix(long long _a = 0, long long _b = 0, long long _c = 0,
         long long _d = 0) {
    a = _a;
    b = _b;
    c = _c;
    d = _d;
  }
  void normalize(Matrix& mat) {
    mat.a %= mod;
    mat.b %= mod;
    mat.c %= mod;
    mat.d %= mod;
  }
  const Matrix operator+(const Matrix& mat) {
    Matrix tmp(this->a + mat.a, this->b + mat.b, this->c + mat.c,
               this->d + mat.d);
    normalize(tmp);
    return tmp;
  }
  const Matrix operator*(const Matrix& mat) {
    Matrix tmp(
        this->a * mat.a + this->b * mat.c, this->a * mat.b + this->b * mat.d,
        this->c * mat.a + this->d * mat.c, this->c * mat.b + this->d * mat.d);
    normalize(tmp);
    return tmp;
  }
  bool operator==(const Matrix& mat) const {
    if (this->a == mat.a && this->b == mat.b && this->c == mat.c &&
        this->d == mat.d)
      return true;
    return false;
  }
  bool operator!=(const Matrix& mat) const { return !(*this == mat); }
  void pprint() {
    return;
    cerr << "---------------------------" << endl;
    cerr << this->a << " | " << this->b << endl;
    cerr << this->c << " | " << this->d << endl;
    cerr << "---------------------------" << endl;
  }
};
class SegmentTree {
 private:
  vector<Matrix> A, st, lazy;
  int n;
  Matrix lazyId;
  int left(int p) { return p << 1; }
  int right(int p) { return (p << 1) + 1; }
  void build(int p, int l, int r) {
    if (r - l == 1) {
      st[p] = A[l];
      return;
    }
    int mid = (l + r) / 2;
    build(left(p), l, mid);
    build(right(p), mid, r);
    st[p] = st[left(p)] + st[right(p)];
  }
  void apply(int p, int l, int r) {
    st[p] = lazy[p] * st[p];
    if (r - l > 1) {
      lazy[left(p)] = lazy[p] * lazy[left(p)];
      lazy[right(p)] = lazy[p] * lazy[right(p)];
    }
    lazy[p] = lazyId;
  }
  void lazyUpdate(int p, int l, int r, int i, int j, Matrix& val) {
    if (lazy[p] != lazyId) apply(p, l, r);
    if (j <= l || r <= i) return;
    if (i <= l && r <= j) {
      lazy[p] = lazy[p] * val;
      apply(p, l, r);
      return;
    }
    int mid = (l + r) / 2;
    lazyUpdate(left(p), l, mid, i, j, val);
    lazyUpdate(right(p), mid, r, i, j, val);
    st[p] = st[left(p)] + st[right(p)];
  }
  Matrix query(int p, int l, int r, int i, int j) {
    if (j <= l || r <= i) return Matrix();
    if (lazy[p] != lazyId) apply(p, l, r);
    if (i <= l && r <= j) return st[p];
    int mid = (l + r) / 2;
    Matrix uno = query(left(p), l, mid, i, j);
    Matrix dos = query(right(p), mid, r, i, j);
    return uno + dos;
  }

 public:
  SegmentTree(vector<Matrix> v) {
    A = v;
    n = v.size();
    st.assign(4 * n, Matrix());
    lazyId = Matrix(1, 0, 0, 1);
    lazy.assign(4 * n, lazyId);
    build(1, 0, n);
  }
  void update(int i, int j, Matrix& val) { lazyUpdate(1, 0, n, i, j, val); }
  Matrix query(int i, int j) { return query(1, 0, n, i, j); }
};
Matrix pot(Matrix b, int k) {
  if (k == 0) return Matrix(1, 0, 0, 1);
  if (k % 2 == 0) {
    Matrix tmp = pot(b, k / 2);
    return tmp * tmp;
  } else {
    return b * pot(b, k - 1);
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  ;
  int n, m;
  cin >> n >> m;
  Matrix base = Matrix(1, 1, 1, 0);
  vector<Matrix> vec;
  for (int i = 0; i < n; i++) {
    int a;
    cin >> a;
    Matrix tmp = pot(base, a);
    vec.push_back(tmp);
    ;
    ;
    tmp.pprint();
  }
  SegmentTree st(vec);
  for (int i = 0; i < m; i++) {
    int t;
    cin >> t;
    if (t == 1) {
      int l, r, x;
      cin >> l >> r >> x;
      l--;
      r--;
      Matrix tmp = pot(base, x);
      ;
      ;
      tmp.pprint();
      st.update(l, r + 1, tmp);
    } else {
      int l, r;
      cin >> l >> r;
      l--;
      r--;
      Matrix tmp = st.query(l, r + 1);
      tmp.pprint();
      long long res = tmp.c % mod;
      cout << res << endl;
    }
  }
  return 0;
}
