Rt
#include<bits/stdc++.h>
#pragma GCC optimize(3, "Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
using namespace std;
#define int long long
#define kg putchar(' ')
#define endl puts("")
inline int read(){
int vis=1,ans=0;
char x=getchar();
while(x<'0'||x>'9'){
if(x=='-')vis=-1;
x=getchar();
}
while(x>='0'&&x<='9'){
ans=ans*10+x-'0';
x=getchar();
}
return vis*ans;
}
inline void print(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10+'0');
}
const int Mod=1e9+7,N=5;
struct Matrix{
int a[N][N];
int *operator[](int i){
return a[i];
}
void MemsetMatrix(){
memset(a,0,sizeof(a));
}
void init(){
a[1][1]=a[1][2]=1;
}
Matrix operator *(const Matrix &b)const{
Matrix c;
c.MemsetMatrix();
for(int i=1;i<=2;i++){
for(int j=1;j<=2;j++){
for(int k=1;k<=2;k++){
c.a[i][j]+=(1ll*a[i][k]*b.a[k][j])%Mod;
c[i][j]%=Mod;
}
}
}
return c;
}
bool empty(){
if(a[1][1]!=1||a[1][2]!=0||a[2][1]!=0||a[2][2]!=1)return 0;
return 1;
}
Matrix operator +(const Matrix &b)const{
Matrix c;
c.MemsetMatrix();
for(int i=1;i<=2;i++){
for(int j=1;j<=2;j++){
c.a[i][j]+=(1ll*a[i][j]+b.a[i][j])%Mod;
c[i][j]%=Mod;
}
}
return c;
}
}S,T;
Matrix qpowMatrix(Matrix aa,int b){
Matrix ret; ret.MemsetMatrix(); ret.init();
while(b){
if(b&1) ret=ret*aa;
aa=aa*aa;
b>>=1;
}
return ret;
}
void init(){
S[1][1]=S[1][2]=1;
T[1][1]=T[1][2]=T[2][1]=1;
}
int n=read(),m=read();
const int M=1e5+9;
int val[M];
struct node{
int l,r;
Matrix sum,lazy;
}e[4*M];
inline void pushup(int p){
e[p].sum=e[p<<1].sum+e[p<<1|1].sum;
}
inline void pushdown(int p){
if(e[p].lazy.empty())return;
e[p<<1].lazy=e[p<<1].lazy*e[p].lazy;
e[p<<1|1].lazy=e[p<<1|1].lazy*e[p].lazy;
e[p<<1].sum=e[p<<1].sum*e[p].lazy;
e[p<<1|1].sum=e[p<<1|1].sum*e[p].lazy;
e[p].lazy.MemsetMatrix();
e[p].lazy.init();
}
inline void build(int p,int l,int r){
e[p].l=l,e[p].r=r,e[p].sum.MemsetMatrix(),e[p].lazy.MemsetMatrix(),e[p].lazy.init();
if(e[p].l==e[p].r){
if(val[e[p].l]<2)e[p].sum=S;
else e[p].sum=S*qpowMatrix(T,val[e[p].l]-2);
return;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
return;
}
inline void modify(int p,int l,int r,Matrix L){
if(e[p].l<=l&&r<=e[p].r){
e[p].sum=e[p].sum*L;
e[p].lazy=e[p].lazy*L;
return;
}
pushdown(p);
int mid=(e[p].l+e[p].r)>>1;
if(l<=mid)modify(p<<1,l,r,L);
if(r>mid)modify(p<<1|1,l,r,L);
pushup(p);
}
inline Matrix ask(int p,int l,int r){
if(l<=e[p].l&&e[p].r<=r)return e[p].sum;
pushdown(p);
int mid=(e[p].l+e[p].r)>>1;
Matrix ans;
ans.MemsetMatrix();
if(l<=mid)ans=ans+ask(p<<1,l,r);
if(mid<r)ans=ans+ask(p<<1|1,l,r);
return ans;
}
signed main(){
init();
for(int i=1;i<=n;i++)val[i]=read();
build(1,1,n);
while(m--){
int opt=read();
if(opt==1){
int l=read(),r=read(),x=read();
modify(1,l,r,qpowMatrix(T,x));
}else{
int l=read(),r=read();
print(ask(1,l,r).a[1][1]%Mod),endl;
}
}
return 0;
}