#include <bits/stdc++.h>   int n, m;   struct Matrix {     long long a[2][2];   } mt[205];   Matrix mult(Matrix x, Matrix y) {     Matrix c;     for (int i = 0; i < 2; i++)       for (int j = 0; j < 2; j++) c.a[i][j] = 0;     for (int i = 0; i < 2; i++)       for (int j = 0; j < 2; j++)         for (int k = 0; k < 2; k++)           c.a[i][j] = ((long long)c.a[i][j] + (long long)x.a[i][k] * y.a[k][j]) %                       1000000007;     return c;   }   void init(long long lim) {     mt[0].a[0][0] = 0;     mt[0].a[0][1] = 1;     mt[0].a[1][0] = 1;     mt[0].a[1][1] = 1;     long long t = 2;     for (int i = 1; t <= lim; i++, t <<= 1) {       mt[i] = mult(mt[i - 1], mt[i - 1]);     }   }   Matrix calc(long long b) {     Matrix res;     res.a[0][0] = 1;     res.a[0][1] = 0;     res.a[1][0] = 0;     res.a[1][1] = 1;     for (int i = 0; b; i++) {       if (b & 1) res = mult(res, mt[i]);       b >>= 1;     }     return res;   }   long long a1[800005], a2[800005], sum[800005];   Matrix prev[800005];   void update(int p) {     a1[p] =         (a1[p << 1] * prev[p << 1].a[0][0] + a2[p << 1] * prev[p << 1].a[0][1] +          a1[(p << 1) + 1] * prev[(p << 1) + 1].a[0][0] +          a2[(p << 1) + 1] * prev[(p << 1) + 1].a[0][1]) %         1000000007;     a2[p] =         (a1[p << 1] * prev[p << 1].a[1][0] + a2[p << 1] * prev[p << 1].a[1][1] +          a1[(p << 1) + 1] * prev[(p << 1) + 1].a[1][0] +          a2[(p << 1) + 1] * prev[(p << 1) + 1].a[1][1]) %         1000000007;   }   void pushdown(int p) {     prev[p << 1] = mult(prev[p << 1], prev[p]);     prev[(p << 1) + 1] = mult(prev[(p << 1) + 1], prev[p]);     prev[p].a[0][0] = 1;     prev[p].a[0][1] = 0;     prev[p].a[1][0] = 0;     prev[p].a[1][1] = 1;     update(p);   }   void merge(int p, int l, int r, int gl, int gr, Matrix val) {     if (l == gl && r == gr) {       if (l == r) {         prev[p] = mult(prev[p], val);       } else {         prev[p] = mult(prev[p], val);         pushdown(p);       }       return;     }     pushdown(p);     int mid = (l + r) >> 1;     if (gr <= mid)       merge(p << 1, l, mid, gl, gr, val);     else if (gl > mid)       merge((p << 1) + 1, mid + 1, r, gl, gr, val);     else       merge(p << 1, l, mid, gl, mid, val),           merge((p << 1) + 1, mid + 1, r, mid + 1, gr, val);     update(p);   }   long long query(int p, int l, int r, int gl, int gr) {     if (l != r) {       pushdown(p);     }     if (l == gl && r == gr) {       return (a1[p] * prev[p].a[0][0] + a2[p] * prev[p].a[0][1]) % 1000000007;     }     int mid = (l + r) >> 1;     if (gr <= mid)       return query(p << 1, l, mid, gl, gr);     else if (gl > mid)       return query((p << 1) + 1, mid + 1, r, gl, gr);     else       return (query(p << 1, l, mid, gl, mid) +               query((p << 1) + 1, mid + 1, r, mid + 1, gr)) %              1000000007;     update(p);   }   int it[800005];   void build(int p, int l, int r) {     prev[p].a[0][0] = 1;     prev[p].a[0][1] = 0;     prev[p].a[1][0] = 0;     prev[p].a[1][1] = 1;     if (l == r) {       if (it[l] == 1)         a1[p] = a2[p] = 1;       else {         Matrix r = calc(it[l] - 1);         a1[p] = (r.a[0][0] + r.a[0][1]) % 1000000007;         a2[p] = (r.a[1][0] + r.a[1][1]) % 1000000007;       }       return;     }     int mid = (l + r) >> 1;     build(p << 1, l, mid);     build((p << 1) + 1, mid + 1, r);     update(p);   }   int main() {     scanf( %d%d , &n, &m);     init(10000000000000000ll);     for (int i = 1; i <= n; i++) scanf( %d , &it[i]);     build(1, 1, n);     for (int i = 1; i <= m; i++) {       int tp;       scanf( %d , &tp);       if (tp == 1) {         int l, r, x;         scanf( %d%d%d , &l, &r, &x);         merge(1, 1, n, l, r, calc(x));       } else {         int l, r;         scanf( %d%d , &l, &r);         printf( %I64d n , query(1, 1, n, l, r) % 1000000007);       }     }   }