#include <bits/stdc++.h>   using namespace std;   const long long MOD = 1e9 + 7;   struct tree {     int l, r;     int tl, tr, parent;     long long sum, nextsum, occupy;   } trees[232222];   long long a[2][2], b[2][2];   int s[111111];   int ids = 0;   long long pre = -1;   void make_matrix(long long tm) {     if (tm <= 1) {       a[0][0] = 0;       a[0][1] = a[1][0] = a[1][1] = 1;       return;     }     make_matrix(tm / 2);     for (int i = 0; i < 2; ++i)       for (int j = 0; j < 2; ++j) b[i][j] = a[i][j];     for (int i = 0; i < 2; ++i)       for (int j = 0; j < 2; ++j)         a[i][j] = (b[i][0] * b[0][j] + b[i][1] * b[1][j]) % MOD;     if (tm % 2) {       for (int i = 0; i < 2; ++i)         for (int j = 0; j < 2; ++j) b[i][j] = a[i][j];       a[0][0] = b[0][1];       a[0][1] = (b[0][0] + b[0][1]) % MOD;       a[1][0] = b[1][1];       a[1][1] = (b[1][0] + b[1][1]) % MOD;     }   }   void cal(long long tm, long long &sum, long long &nextsum) {     if (pre != tm) {       make_matrix(tm);     }     pre = tm;     long long sum_temp = (sum * a[0][0] + nextsum * a[1][0]) % MOD;     nextsum = (sum * a[0][1] + nextsum * a[1][1]) % MOD;     sum = sum_temp;   }   int make_tree(int a[], int n, int start) {     int id = ids;     ++ids;     trees[id].l = start;     trees[id].r = start + n - 1;     trees[id].parent = 0;     if (n == 1) {       trees[id].sum = 0;       trees[id].nextsum = 1;       cal(a[0], trees[id].sum, trees[id].nextsum);       trees[id].occupy = 0;       trees[id].tl = 0;       trees[id].tr = 0;     } else {       int lid = make_tree(a, n / 2, start);       int rid = make_tree(a + n / 2, n - n / 2, start + n / 2);       trees[id].tl = lid;       trees[id].tr = rid;       trees[id].sum = (trees[lid].sum + trees[rid].sum) % MOD;       trees[id].nextsum = (trees[lid].nextsum + trees[rid].nextsum) % MOD;       trees[lid].parent = id;       trees[rid].parent = id;     }     return id;   }   void add_value(tree &node, long long value) {     long long psum = node.sum;     long long pnsum = node.nextsum;     cal(value, node.sum, node.nextsum);     node.occupy = node.occupy + value;     psum = node.sum - psum;     pnsum = node.nextsum - pnsum;     int p = node.parent;     while (p != 0) {       trees[p].nextsum = (trees[p].nextsum + pnsum + MOD) % MOD;       trees[p].sum = (trees[p].sum + psum + MOD) % MOD;       p = trees[p].parent;     }   }   void refresh_from_above(int l, int r, tree &node) {     if (node.l > r || node.r < l) return;     if (l <= node.l && node.r <= r) return;     if (node.occupy > 0) {       trees[node.tl].occupy = trees[node.tl].occupy + node.occupy;       cal(node.occupy, trees[node.tl].sum, trees[node.tl].nextsum);       trees[node.tr].occupy = trees[node.tr].occupy + node.occupy;       cal(node.occupy, trees[node.tr].sum, trees[node.tr].nextsum);       node.occupy = 0;     }     refresh_from_above(l, r, trees[node.tl]);     refresh_from_above(l, r, trees[node.tr]);   }   void add_area(int l, int r, tree &node, long long value) {     if (node.l > r || node.r < l) return;     if (l <= node.l && r >= node.r) {       add_value(node, value);       return;     }     add_area(l, r, trees[node.tl], value);     add_area(l, r, trees[node.tr], value);   }   long long cal_area(int l, int r, tree &node) {     if (node.l > r || node.r < l) return 0;     if (l <= node.l && r >= node.r) {       return node.sum;     }     return (cal_area(l, r, trees[node.tl]) + cal_area(l, r, trees[node.tr])) %            MOD;   }   int main() {     int n, m, p, l, r, x;     ids = 1;     scanf( %d%d , &n, &m);     for (int i = 0; i < n; ++i) scanf( %d , &s[i]);     int id = make_tree(s, n, 1);     for (int i = 0; i < m; ++i) {       scanf( %d , &p);       if (p == 1) {         scanf( %d%d%d , &l, &r, &x);         refresh_from_above(l, r, trees[id]);         add_area(l, r, trees[id], x);       } else {         scanf( %d%d , &l, &r);         refresh_from_above(l, r, trees[id]);         printf( %I64d n , cal_area(l, r, trees[id]));       }     }   }