#include <bits/stdc++.h>
using namespace std;
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
#define lson l, mid, (rt << 1)
#define rson mid + 1, r, (rt << 1 | 1)
#define __mid__ int mid = (l + r) >> 1
typedef __int64 LL;
const int MAXN = 100000 + 5;
const int MOD = 1e9 + 7;
int N, M, tp, L, R, X;
struct Mat {
static const int MX = 2;
int v[MX][MX];
void O() {
memset(v, 0, sizeof(v));
}
void E() {
O();
for(int i = 0; i < MX; i++) v[i][i] = 1;
}
Mat operator + (const Mat& e) const {
Mat ret; ret.O();
for(int i = 0; i < MX; i++) {
for(int j = 0; j < MX; j++) {
ret.v[i][j] = ((LL)v[i][j] + e.v[i][j]) % MOD;
}
}
return ret;
}
Mat operator - (const Mat& e) const {
Mat ret; ret.O();
for(int i = 0; i < MX; i++) {
for(int j = 0; j < MX; j++) {
ret.v[i][j] = ((LL)v[i][j] - e.v[i][j] + MOD) % MOD;
}
}
return ret;
}
Mat operator * (const Mat& e) const {
Mat ret; ret.O();
for(int k = 0; k < MX; k++) {
for(int i = 0; i < MX; i++) {
if(v[i][k] == 0) continue;
for(int j = 0; j < MX; j++) {
ret.v[i][j] = (ret.v[i][j] + (LL) v[i][k] * e.v[k][j]) % MOD;
}
}
}
return ret;
}
Mat operator ^ (int b) const {
Mat a, ret; ret.E();
memcpy(a.v, v, sizeof(v));
while(b > 0) {
if(b & 1) ret = ret * a;
a = a * a;
b >>= 1;
}
return ret;
}
} ini, tra, mat;
struct Seg {
Mat sum, tag;
bool col;
} seg[MAXN * 3];
inline void pushUp(int rt) {
seg[rt].sum = seg[rt << 1].sum + seg[rt << 1 | 1].sum;
}
inline void down(int rt, int fa) {
seg[rt].col = seg[fa].col;
seg[rt].sum = seg[fa].tag * seg[rt].sum;
seg[rt].tag = seg[fa].tag * seg[rt].tag;
}
inline void pushDown(int rt) {
if(seg[rt].col) {
down(rt << 1, rt);
down(rt << 1 | 1, rt);
seg[rt].tag.E();
seg[rt].col = false;
}
}
void build(int l, int r, int rt) {
seg[rt].tag.E();
seg[rt].col = false;
if(l == r) {
scanf("%d", &X);
mat = tra ^ (X - 1);
seg[rt].sum = mat * ini;
return;
}
__mid__;
build(lson);
build(rson);
pushUp(rt);
}
void update(int l, int r, int rt) {
if(L <= l && r <= R) {
seg[rt].sum = mat * seg[rt].sum;
seg[rt].tag = mat * seg[rt].tag;
seg[rt].col = true;
return;
}
__mid__;
pushDown(rt);
if(L <= mid) update(lson);
if(R > mid) update(rson);
pushUp(rt);
}
int query(int l, int r, int rt) {
if(L <= l && r <= R) {
return seg[rt].sum.v[0][0];
}
__mid__;
pushDown(rt);
int ret = 0;
if(L <= mid) ret = query(lson);
if(R > mid) ret += query(rson);
return ret % MOD;
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
ini.v[0][0] = 1, ini.v[0][1] = 0;
ini.v[1][0] = 0, ini.v[1][1] = 0;
tra.v[0][0] = 1, tra.v[0][1] = 1;
tra.v[1][0] = 1, tra.v[1][1] = 0;
scanf("%d %d", &N, &M);
build(1, N, 1);
while(M --) {
scanf("%d %d %d", &tp, &L, &R);
if(tp == 1) {
scanf("%d", &X);
mat = tra ^ X; /// 因为把这个写在update里面,TLE了好几发...
update(1, N, 1);
} else {
printf("%d\n", query(1, N, 1));
}
}
return 0;
}