#include <bits/stdc++.h>   const int mod = 1e9 + 7;   const int MAXN = 1e5 + 5, MAXSIZ = 3;   template <typename _T>   void read(_T &x) {     x = 0;     char s = getchar();     int f = 1;     while (s <  0  ||  9  < s) {       f = 1;       if (s ==  - ) f = -1;       s = getchar();     }     while ( 0  <= s && s <=  9 ) {       x = (x << 3) + (x << 1) + s -  0 , s = getchar();     }     x *= f;   }   template <typename _T>   void write(_T x) {     if (x < 0) {       putchar( - ), x = -x;     }     if (9 < x) {       write(x / 10);     }     putchar(x % 10 +  0 );   }   struct matrix {     int mat[MAXSIZ][MAXSIZ], n, m;     matrix() { n = m = 0, memset(mat, 0, sizeof mat); }     matrix(const int N, const int M) { n = N, m = M, memset(mat, 0, sizeof mat); }     int *operator[](const int indx) { return mat[indx]; }     matrix operator*(matrix other) const {       matrix ret = matrix(n, other.m);       for (int i = 1; i <= n; i++)         for (int j = 1; j <= m; j++)           if (mat[i][j])             for (int k = 1; k <= ret.m; k++) {               ret[i][k] += 1ll * mat[i][j] * other[j][k] % mod;               if (ret[i][k] > mod) ret[i][k] -= mod;             }       return ret;     }     bool operator==(matrix other) const {       if (n ^ other.n || m ^ other.m) return false;       for (int i = 1; i <= n; i++)         for (int j = 1; j <= m; j++)           if (mat[i][j] ^ other[i][j]) return false;       return true;     }     bool operator!=(matrix other) const { return !(*this == other); }     void operator*=(matrix other) { *this = *this * other; }   };   struct vector {     int vec[MAXSIZ], n;     vector() { n = 0, memset(vec, 0, sizeof vec); }     vector(const int N) { n = N, memset(vec, 0, sizeof vec); }     int &operator[](const int indx) { return vec[indx]; }     vector operator*(matrix other) const {       vector ret = vector(n);       for (int i = 1; i <= n; i++)         for (int j = 1; j <= ret.n; j++) {           ret[i] += 1ll * vec[j] * other[j][i] % mod;           if (ret[i] > mod) ret[i] -= mod;         }       return ret;     }     vector operator+(vector other) const {       vector ret = *this;       for (int i = 1; i <= n; i++) {         ret[i] += other[i];         if (ret[i] > mod) ret[i] -= mod;       }       return ret;     }     void operator*=(matrix other) { *this = *this * other; }     void operator+=(vector other) { *this = *this + other; }   };   struct segmentTreeNode {     vector s;     matrix tag;   } segTree[MAXN << 2];   matrix I, B;   vector A;   int a[MAXN];   int N, M;   void upt(const int x) {     (segTree[x].s) = (segTree[x << 1].s) + (segTree[x << 1 | 1].s);   }   void prod(const int x, const matrix v) {     (segTree[x].s) *= v, (segTree[x].tag) *= v;   }   void normalize(const int x) {     if ((segTree[x].tag) != I)       prod(x << 1, (segTree[x].tag)), prod(x << 1 | 1, (segTree[x].tag)),           (segTree[x].tag) = I;   }   void init() {     I = matrix(2, 2);     for (int i = 1; i <= 2; i++) I[i][i] = 1;     B = matrix(2, 2);     B[1][1] = B[2][1] = B[1][2] = 1;     A = vector(2);     A[1] = 1;   }   matrix qkpow(matrix base, int indx) {     if (indx < 0) return I;     matrix ret = I;     while (indx) {       if (indx & 1) ret *= base;       base *= base, indx >>= 1;     }     return ret;   }   void build(const int u, const int l, const int r) {     if (l > r) return;     (segTree[u].tag) = I;     int mid = l + r >> 1;     if (l == r) {       (segTree[u].s) = A * qkpow(B, a[l] - 1);       return;     }     build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);     upt(u);   }   void update(const int x, const int l, const int r, const int segL,               const int segR, const matrix v) {     int mid = l + r >> 1;     if (segL <= l && r <= segR) {       prod(x, v);       return;     }     if (l == r) return;     normalize(x);     if (segL <= mid) update(x << 1, l, mid, segL, segR, v);     if (segR > mid) update(x << 1 | 1, mid + 1, r, segL, segR, v);     upt(x);   }   int query(const int x, const int l, const int r, const int segL,             const int segR) {     int mid = l + r >> 1, ret = 0;     if (segL <= l && r <= segR) return (segTree[x].s)[1];     if (l == r) return 0;     normalize(x);     if (segL <= mid) (ret += query(x << 1, l, mid, segL, segR)) %= mod;     if (segR > mid) (ret += query(x << 1 | 1, mid + 1, r, segL, segR)) %= mod;     return ret;   }   int main() {     matrix tmp;     int opt, optL, optR, optV;     init();     read(N), read(M);     for (int i = 1; i <= N; i++) read(a[i]);     build(1, 1, N);     while (M--) {       read(opt), read(optL), read(optR);       if (opt == 1) {         read(optV);         tmp = qkpow(B, optV);         update(1, 1, N, optL, optR, tmp);       } else         write(query(1, 1, N, optL, optR)), putchar(  n );     }     return 0;   }