#include <bits/stdc++.h>   #pragma comment(linker,  /STACK:102400000,102400000 )   using namespace std;   const int maxn = 2e5 + 10;   const int inf = 0x7fffffff;   const long long INF = 9E18;   const int mod = 1e9 + 7;   const long long mod2 = 1e9 + 9;   const int eps = 1e-7;   const double pi = acos(-1.0);   template <typename T>   inline void read(T &x) {     T f = 1;     char ch = getchar();     for (; ch <  0  || ch >  9 ; ch = getchar())       if (ch ==  - ) f = -1;     for (x = 0; ch >=  0  && ch <=  9 ; ch = getchar()) x = x * 10 + ch -  0 ;     x *= f;   }   struct matrix {     long long a[2][2];     matrix() { memset(a, 0, sizeof a); }     matrix(long long x, long long y, long long p, long long q) {       a[0][0] = x;       a[0][1] = y;       a[1][0] = p;       a[1][1] = q;     }     matrix operator*(const matrix b) {       matrix c;       for (int i = 0; i <= 1; i++)         for (int j = 0; j <= 1; j++)           for (int k = 0; k <= 1; k++)             c.a[i][j] = (c.a[i][j] + ((a[i][k] * b.a[k][j]) % mod)) % mod;       return c;     }     matrix operator+(const matrix b) {       matrix c;       for (int i = 0; i <= 1; i++)         for (int j = 0; j <= 1; j++) c.a[i][j] = (a[i][j] + b.a[i][j]) % mod;       return c;     }     bool operator==(const matrix b) {       for (int i = 0; i <= 1; i++) {         for (int j = 0; j <= 1; j++) {           if (a[i][j] != b.a[i][j]) return 0;         }       }       return 1;     }     matrix operator^(long long x) {       matrix c(1, 0, 0, 1), b = *this;       while (x) {         if (x & 1) c = c * b;         b = b * b;         x >>= 1;       }       return c;     }   } change(1, 1, 1, 0), ori(1, 0, 0, 0), tree[maxn << 2], lazy[maxn << 2],       I(1, 0, 0, 1);   long long a[maxn];   int n, m;   void push_up(int rt) { tree[rt] = tree[rt << 1] + tree[rt << 1 | 1]; }   void push_down(int rt) {     if (lazy[rt] == I) return;     lazy[rt << 1] = lazy[rt << 1] * lazy[rt];     lazy[rt << 1 | 1] = lazy[rt << 1 | 1] * lazy[rt];     tree[rt << 1] = tree[rt << 1] * lazy[rt];     tree[rt << 1 | 1] = tree[rt << 1 | 1] * lazy[rt];     lazy[rt] = I;   }   void build(int l, int r, int rt) {     lazy[rt] = I;     if (l == r) {       tree[rt] = ori * (change ^ (a[l] - 1));       return;     }     int mid = (l + r) >> 1;     build(l, mid, rt << 1);     build(mid + 1, r, rt << 1 | 1);     push_up(rt);   }   void update(int l, int r, int rt, int x, int y, matrix val) {     if (x <= l && r <= y) {       tree[rt] = (tree[rt] * val);       lazy[rt] = lazy[rt] * val;       return;     }     push_down(rt);     int mid = (l + r) >> 1;     if (x <= mid) update(l, mid, rt << 1, x, y, val);     if (y > mid) update(mid + 1, r, rt << 1 | 1, x, y, val);     push_up(rt);   }   long long query(int l, int r, int rt, int x, int y) {     push_down(rt);     if (x <= l && r <= y) return ((tree[rt].a[0][0] + mod) % mod);     int mid = (l + r) >> 1;     long long ans = 0;     if (x <= mid) ans += query(l, mid, rt << 1, x, y);     if (y > mid) ans += query(mid + 1, r, rt << 1 | 1, x, y);     return ((ans + mod) % mod);   }   int main() {     scanf( %d%d , &n, &m);     for (int i = 1; i <= n; i++) read(a[i]);     build(1, n, 1);     while (m--) {       int op, l, r;       scanf( %d%d%d , &op, &l, &r);       if (op == 1) {         long long x;         read(x);         update(1, n, 1, l, r, change ^ x);       } else {         cout << query(1, n, 1, l, r) << endl;       }     }     return 0;   }