const int MAXN=1e5+5,MAX_size=2,MAXS=35,Mod=1e9+7;
struct Matrix{
int r,c,ele[MAX_size][MAX_size];
Matrix(int r=0,int c=0){
this->r=r,this->c=c;
mem(ele,0);
}
Matrix operator + (const Matrix &b)const{
Matrix C;
C.r=r,C.c=c;
_for(i,0,r)_for(j,0,c)
C.ele[i][j]=(ele[i][j]+b.ele[i][j])%Mod;
return C;
}
Matrix operator * (const Matrix &b)const{
Matrix C;
C.r=r,C.c=b.c;
_for(i,0,C.r)_for(j,0,C.c){
C.ele[i][j]=0;
_for(k,0,c)
C.ele[i][j]=(C.ele[i][j]+1LL*ele[i][k]*b.ele[k][j])%Mod;
}
return C;
}
bool operator != (const Matrix &b)const{
_for(i,0,r)_for(j,0,c)if(ele[i][j]!=b.ele[i][j])
return true;
return false;
}
}A[MAXS],I,X1;
Matrix quick_pow(int k){
Matrix ans=I;
int pos=0;
while(k){
if(k&1)ans=ans*A[pos];
pos++;
k>>=1;
}
return ans;
}
int a[MAXN],lef[MAXN<<2],rig[MAXN<<2];
Matrix s[MAXN<<2],lazy[MAXN<<2];
void push_up(int k){
s[k]=s[k<<1]+s[k<<1|1];
}
void push_tag(int k,Matrix lazy_tag){
s[k]=lazy_tag*s[k];
lazy[k]=lazy_tag*lazy[k];
}
void push_down(int k){
if(lazy[k]!=I){
push_tag(k<<1,lazy[k]);
push_tag(k<<1|1,lazy[k]);
lazy[k]=I;
}
}
void build(int k,int L,int R){
lef[k]=L,rig[k]=R,lazy[k]=I;
int M=L+R>>1;
if(L==R)
return s[k]=quick_pow(a[M]-1)*X1,void();
build(k<<1,L,M);
build(k<<1|1,M+1,R);
push_up(k);
}
void update(int k,int L,int R,int v){
if(L<=lef[k]&&rig[k]<=R)
return push_tag(k,quick_pow(v));
push_down(k);
int mid=lef[k]+rig[k]>>1;
if(mid>=L)
update(k<<1,L,R,v);
if(mid<R)
update(k<<1|1,L,R,v);
push_up(k);
}
Matrix query(int k,int L,int R){
if(L<=lef[k]&&rig[k]<=R)
return s[k];
push_down(k);
int mid=lef[k]+rig[k]>>1;
if(mid>=R)
return query(k<<1,L,R);
else if(mid<L)
return query(k<<1|1,L,R);
else
return query(k<<1,L,R)+query(k<<1|1,L,R);
}
int main()
{
A[0]=Matrix(2,2);I=Matrix(2,2);X1=Matrix(2,1);
A[0].ele[0][1]=A[0].ele[1][0]=A[0].ele[1][1]=I.ele[0][0]=I.ele[1][1]=X1.ele[0][0]=X1.ele[1][0]=1;
_for(i,1,MAXS)
A[i]=A[i-1]*A[i-1];
int n=read_int(),m=read_int();
_rep(i,1,n)a[i]=read_int();
build(1,1,n);
while(m--){
int tp=read_int(),l=read_int(),r=read_int();
if(tp==1)update(1,l,r,read_int());
else
enter(query(1,l,r).ele[0][0]);
}
return 0;
}