#include <bits/stdc++.h>   using namespace std;   template <typename base_type, base_type _MOD>   struct IntMod {     static const int INVERSE_CACHE_SIZE = (1 << 20);     static base_type MOD;     static void set_mod(base_type new_mod) { MOD = new_mod; }     base_type n;     IntMod(long long d = 0) { n = (d >= 0 ? d % MOD : (d % MOD + MOD) % MOD); }     virtual ~IntMod() = default;     IntMod operator-() const { return build(n == 0 ? 0 : MOD - n); }     IntMod& operator+=(IntMod a) {       n = (n >= MOD - a.n ? n - MOD + a.n : n + a.n);       return *this;     }     IntMod& operator-=(IntMod a) {       n = (n >= a.n) ? n - a.n : n - a.n + MOD;       return *this;     }     IntMod& operator*=(IntMod a) {       *this = *this * a;       return *this;     }     IntMod& operator/=(IntMod a) {       *this = *this / a;       return *this;     }     static IntMod build(base_type n) {       IntMod L;       L.n = n;       return L;     }     static base_type inverse_cache[INVERSE_CACHE_SIZE];     static bool inverse_cache_ready;     friend IntMod inverse(IntMod n) { return build(inverse_internal(n.n)); }     static base_type inverse_internal(base_type n) {       if (!inverse_cache_ready) {         inverse_cache_ready = true;         inverse_cache[0] = 0;         inverse_cache[1] = 1;         for (int n = 2; n < INVERSE_CACHE_SIZE; ++n)           inverse_cache[n] =               (MOD -                (base_type)((long long)inverse_cache[MOD % n] * (MOD / n) % MOD));       }       return n < INVERSE_CACHE_SIZE                  ? inverse_cache[n]                  : MOD - (base_type)((long long)inverse_internal(MOD % n) *                                      (MOD / n) % MOD);     }     friend bool operator==(IntMod a, IntMod b) { return a.n == b.n; }     friend bool operator!=(IntMod a, IntMod b) { return a.n != b.n; }     friend IntMod operator+(IntMod a, IntMod b) {       return build(a.n >= MOD - b.n ? a.n - MOD + b.n : a.n + b.n);     }     friend IntMod operator-(IntMod a, IntMod b) {       return build(a.n >= b.n ? a.n - b.n : a.n - b.n + MOD);     }     friend IntMod operator*(IntMod a, IntMod b) {       return build(           static_cast<base_type>(static_cast<long long>(a.n) * b.n % MOD));     }     friend IntMod operator/(IntMod a, IntMod b) { return a * inverse(b); }     friend IntMod xpow(IntMod p, long long e) {       if (e <= 0) return IntMod(1);       IntMod L = IntMod(1);       while (e) {         if (e & 1) L *= p;         p *= p;         e >>= 1;       }       return L;     }     friend ostream& operator<<(ostream& os, const IntMod& p) {       os << p.n;       return os;     }     friend istream& operator>>(istream& is, IntMod& p) {       is >> p.n;       return is;     }   };   template <typename base_type, base_type _MOD>   base_type IntMod<base_type, _MOD>::inverse_cache[INVERSE_CACHE_SIZE];   template <typename base_type, base_type _MOD>   bool IntMod<base_type, _MOD>::inverse_cache_ready;   template <typename base_type, base_type _MOD>   base_type IntMod<base_type, _MOD>::MOD = _MOD;   template <typename T, typename U>   ostream& operator<<(ostream& os, const pair<T, U>& p) {     os << p.first <<     << p.second << endl;     return os;   }   template <typename T>   ostream& operator<<(ostream& os, const vector<T>& vec) {     for (const auto& v : vec) os << v <<    ;     return os;   }   long long SQRT(long long x) {     long long ret = sqrt(x) + 5;     while (1) {       if (ret * ret <= x) break;       ret--;     }     return ret;   }   const int maxm = 1e5 + 5;   const int maxn = 2;   const long long MOD = 1e9 + 7;   using Int = IntMod<int, MOD>;   struct Matrix {     Int m[maxn][maxn];     bool empty() {       for (int i = 0; i < maxn; i++)         for (int j = 0; j < maxn; j++)           if (m[i][j] != (i == j)) return false;       return true;     }     void clear() {       for (int i = 0; i < maxn; i++)         for (int j = 0; j < maxn; j++) m[i][j] = (i == j);     }     friend Matrix operator*(const Matrix& a, const Matrix& b) {       Matrix c;       for (int i = 0; i < maxn; i++)         for (int j = 0; j < maxn; j++) c.m[i][j] = 0;       for (int i = 0; i < maxn; i++)         for (int j = 0; j < maxn; j++)           for (int k = 0; k < maxn; k++) c.m[i][j] += a.m[i][k] * b.m[k][j];       return c;     }     friend Matrix pow(Matrix a, long long n) {       Matrix res;       for (int i = 0; i < maxn; i++)         for (int j = 0; j < maxn; j++) res.m[i][j] = (i == j);       while (n) {         if (n & 1) res = res * a;         n >>= 1;         a = a * a;       }       return res;     }   } bs4, E;   struct Vector {     Int m[maxn];     void clear() {       for (int i = 0; i < maxn; i++) m[i] = 0;     }     friend Vector operator*(const Vector& a, const Matrix& b) {       Vector c;       c.clear();       for (int i = 0; i < maxn; i++)         for (int j = 0; j < maxn; j++) c.m[i] += a.m[j] * b.m[i][j];       return c;     }     friend Vector operator+(const Vector& a, const Vector& b) {       Vector c;       for (int i = 0; i < maxn; i++) c.m[i] = a.m[i] + b.m[i];       return c;     }   } I;   Int calc(int idx) {     if (idx <= 1)       return 1;     else {       Matrix p = pow(bs4, idx - 2);       return p.m[1][0] + p.m[1][1];     }   }   struct node {     Vector val;     Matrix lazy;     int l, r;   } tree[maxm * 8];   void push_down(int root) {     if (!tree[root].lazy.empty()) {       tree[root * 2 + 1].val = tree[root * 2 + 1].val * tree[root].lazy;       tree[root * 2 + 2].val = tree[root * 2 + 2].val * tree[root].lazy;       tree[root * 2 + 1].lazy = tree[root * 2 + 1].lazy * tree[root].lazy;       tree[root * 2 + 2].lazy = tree[root * 2 + 2].lazy * tree[root].lazy;       tree[root].lazy.clear();     }   }   void push_up(int root) {     tree[root].val = tree[root * 2 + 1].val + tree[root * 2 + 2].val;   }   void build(int root, int l, int r) {     tree[root].l = l;     tree[root].r = r;     tree[root].lazy.clear();     if (l == r) {       int x;       scanf( %d , &x);       tree[root].val.m[0] = calc(x);       tree[root].val.m[1] = calc(x + 1);       return;     }     int mid = (l + r) / 2;     build(root * 2 + 1, l, mid);     build(root * 2 + 2, mid + 1, r);     push_up(root);   }   void change(int root, int l, int r, const Matrix& val) {     int op = tree[root].l;     int ed = tree[root].r;     if (op > ed) return;     push_down(root);     if (op == l && ed == r) {       tree[root].val = tree[root].val * val;       tree[root].lazy = tree[root].lazy * val;       return;     }     int mid = (op + ed) / 2;     if (r <= mid)       change(root * 2 + 1, l, r, val);     else if (l > mid)       change(root * 2 + 2, l, r, val);     else {       change(root * 2 + 1, l, mid, val);       change(root * 2 + 2, mid + 1, r, val);     }     push_up(root);   }   Vector sum(int root, int l, int r) {     int op = tree[root].l;     int ed = tree[root].r;     if (op > ed) return I;     push_down(root);     if (op == l && ed == r) return tree[root].val;     int mid = (op + ed) / 2;     if (r <= mid)       return sum(root * 2 + 1, l, r);     else if (l > mid)       return sum(root * 2 + 2, l, r);     return sum(root * 2 + 1, l, mid) + sum(root * 2 + 2, mid + 1, r);   }   int main() {     bs4.m[0][0] = 0;     bs4.m[0][1] = 1;     bs4.m[1][0] = 1;     bs4.m[1][1] = 1;     E.clear();     I.clear();     int n, q, op, l, r, val;     scanf( %d%d , &n, &q);     build(0, 1, n);     while (q--) {       scanf( %d%d%d , &op, &l, &r);       if (op == 1) {         scanf( %d , &val);         change(0, l, r, pow(bs4, val));       } else         printf( %d n , sum(0, l, r).m[0].n);     }     return 0;   }