#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;   }