#include<bits/stdc++.h>

using namespace std;

#define LL long long
#define pb push_back
#define pLL pair<LL,LL>
#define ff first
#define ss second
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define repb(i,a,b) for(int i=a;i>=b;--i)
#define ld double
#define mp make_pair
#define vLL vector<LL>
#define vpLL vector<pLL>
#define vld vector<ld>
#define pld pair<ld,ld>
#define vpld vector<pld>
#define SLL set<LL>
#define SpLL set<pLL>
#define FIO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define mod 1000000007

LL matpow[32][2][2];

inline void multiply(LL a[2][2],LL b[2][2])
{
    LL c[][2]={{0,0},{0,0}};
    rep(i,0,1) rep(j,0,1) rep(k,0,1) c[i][j]=((a[i][k]*b[k][j])+c[i][j])%mod;
    rep(i,0,1) rep(j,0,1) a[i][j]=c[i][j];
}

inline void power(LL a[2][2],LL n)
{
    a[0][0]=a[1][1]=1;
    a[1][0]=a[0][1]=0;
    rep(i,0,30){
        if((1<<i)>n) break;
        if(n&(1<<i)) multiply(a,matpow[i+1]);
    }
}

LL n,m,ar[100005];
LL lazy[800005][2][2];
pLL seg[800005];

inline pLL fib(LL i)
{
    if(i==1) return mp(1,0);
    if(i==2) return mp(1,1);
    LL ret[2][2];
    power(ret,i-2);
    return mp((ret[0][0]+ret[0][1])%mod,(ret[1][0]+ret[1][1])%mod);
}

inline void init(LL v=1,LL l=1,LL r=n)
{
    if(l==r){
        seg[v]=fib(ar[l]);
        lazy[v][0][0]=lazy[v][1][1]=1;
        return;
    }
    init(2*v,l,(l+r)/2);
    init(2*v+1,(l+r)/2+1,r);
    seg[v]=mp((seg[2*v].ff+seg[2*v+1].ff)%mod,(seg[2*v].ss+seg[2*v+1].ss)%mod);
    lazy[v][0][0]=lazy[v][1][1]=1;
    return;
}

inline void upd(LL v,LL ret[2][2])
{
    multiply(lazy[v],ret);
    LL fff=seg[v].ff,sss=seg[v].ss;
    seg[v]=mp((ret[0][0]*fff+ret[0][1]*sss)%mod,(ret[1][0]*fff+ret[1][1]*sss)%mod);
    return;
}

inline void prop(LL v)
{
    upd(2*v,lazy[v]);
    upd(2*v+1,lazy[v]);
    lazy[v][0][0]=lazy[v][1][1]=1;
    lazy[v][1][0]=lazy[v][0][1]=0;
    return;
}

inline void update(LL a,LL b,LL val,LL v=1,LL l=1,LL r=n)
{
    if(a<=l&&r<=b){
        LL ret[2][2];
        power(ret,val);
        upd(v,ret);
        return;
    }
    prop(v);
    LL mid=(l+r)/2;
    if(b<=mid) update(a,b,val,2*v,l,mid);
    else if(a>mid) update(a,b,val,2*v+1,mid+1,r);
    else{
        update(a,b,val,2*v+1,mid+1,r);
        update(a,b,val,2*v,l,mid);
    }
    seg[v]=mp((seg[2*v].ff+seg[2*v+1].ff)%mod,(seg[2*v].ss+seg[2*v+1].ss)%mod);
    return;
}

inline LL query(LL a,LL b,LL v=1,LL l=1,LL r=n)
{
    if(a<=l&&r<=b) return seg[v].ff;
    prop(v);
    LL mid=(l+r)/2;
    if(b<=mid) return query(a,b,2*v,l,mid);
    if(a>mid) return query(a,b,2*v+1,mid+1,r);
    return (query(a,b,2*v+1,mid+1,r)+query(a,b,2*v,l,mid))%mod;
}

int main()
{
    matpow[1][0][0]=matpow[1][0][1]=matpow[1][1][0]=1;
    matpow[1][1][1]=0;
    rep(k,2,30){
        rep(i,0,1) rep(j,0,1) matpow[k][i][j]=matpow[k-1][i][j];
        multiply(matpow[k],matpow[k]);
    }
    scanf("%I64d%I64d",&n,&m);
    rep(i,1,n) scanf("%I64d",&ar[i]);
    init();
    while(m--){
        LL ty,l,r;
        scanf("%I64d%I64d%I64d",&ty,&l,&r);
        if(ty==1){
            LL x;
            scanf("%I64d",&x);
            update(l,r,x);
        }
        else printf("%I64d\n",query(l,r));
    }
    return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

ll read()
{
	ll res=0,c=getchar();
	while(c<'0' || '9'<c)c=getchar();
	while('0'<=c && c<='9'){res=res*10+c-'0';c=getchar();}
	return res;
}

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

mat mem[100001];

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
	if(k<=100000ll && mem[k].a[0][0]>0ll)return mem[k];
	mat res;
	ll p=k;
	res.a[0][0]=res.a[1][1]=1ll;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	if(p<=100000ll)mem[p]=res;
//	cout<<' '<<mem[k].a[0][0]<<endl;
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	if(tree[k].tag==0ll)return;
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=(tree[k*2].a1+tree[k*2+1].a1)%mod;
	tree[k].a2=(tree[k*2].a2+tree[k*2+1].a2)%mod;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	n=read();m=read();
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op=read();
		if(op==1){
			ll x=read(),y=read(),z=read();
			add(1,x,y,z);
		}
		else{
			ll x=read(),y=read();
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
	mat res;
	res.a[0][0]=res.a[1][1]=1;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=(tree[k*2].tag+u)%mod;
	tree[k*2+1].tag=(tree[k*2+1].tag+u)%mod;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=(tree[k*2].a1+tree[k*2+1].a1)%mod;
	tree[k].a2=(tree[k*2].a2+tree[k*2+1].a2)%mod;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag=(tree[k].tag+x)%mod;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	scanf("%I64d%I64d",&n,&m);
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op;
		scanf("%I64d",&op);
		if(op==1){
			ll x,y,z;
			scanf("%I64d%I64d%I64d",&x,&y,&z);
			add(1,x,y,z);
		}
		else{
			ll x,y;
			scanf("%I64d%I64d",&x,&y);
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

ll read()
{
	ll res=0,c=getchar();
	while(c<'0' || '9'<c)c=getchar();
	while('0'<=c && c<='9'){res=res*10+c-'0';c=getchar();}
	return res;
}

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

mat mem[100001];

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
	if(k<=100000ll && mem[k].a[0][0]>0)return mem[k];
	mat res;
	ll p=k;
	res.a[0][0]=res.a[1][1]=1ll;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	if(p<=100000ll)mem[p]=res;
//	cout<<' '<<mem[k].a[0][0]<<endl;
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	if(tree[k].tag==0ll)return;
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=tree[k*2].a1+tree[k*2+1].a1;
	tree[k].a2=tree[k*2].a2+tree[k*2+1].a2;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	n=read();m=read();
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op=read();
		if(op==1){
			ll x=read(),y=read(),z=read();
			add(1,x,y,z);
		}
		else{
			ll x=read(),y=read();
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
	mat res;
	res.a[0][0]=res.a[1][1]=1;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=tree[k*2].a1+tree[k*2+1].a1;
	tree[k].a2=tree[k*2].a2+tree[k*2+1].a2;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	scanf("%I64d%I64d",&n,&m);
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op;
		scanf("%I64d",&op);
		if(op==1){
			ll x,y,z;
			scanf("%I64d%I64d%I64d",&x,&y,&z);
			add(1,x,y,z);
		}
		else{
			ll x,y;
			scanf("%I64d%I64d",&x,&y);
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
	mat res;
	res.a[0][0]=res.a[1][1]=1;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=tree[k*2].a1+tree[k*2+1].a1;
	tree[k].a2=tree[k*2].a2+tree[k*2+1].a2;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag=(tree[k].tag+x)%mod;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	scanf("%I64d%I64d",&n,&m);
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op;
		scanf("%I64d",&op);
		if(op==1){
			ll x,y,z;
			scanf("%I64d%I64d%I64d",&x,&y,&z);
			add(1,x,y,z);
		}
		else{
			ll x,y;
			scanf("%I64d%I64d",&x,&y);
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

ll read()
{
	ll res=0,c=getchar();
	while(c<'0' || '9'<c)c=getchar();
	while('0'<=c && c<='9'){res=res*10+c-'0';c=getchar();}
	return res;
}

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

mat mem[1000001];

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
	if(k<=100000ll && mem[k].a[0][0]>0ll)return mem[k];
	mat res;
	ll p=k;
	res.a[0][0]=res.a[1][1]=1ll;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	if(p<=100000ll)mem[p]=res;
//	cout<<' '<<mem[k].a[0][0]<<endl;
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	if(tree[k].tag==0ll)return;
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
//	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=(tree[k*2].a1+tree[k*2+1].a1)%mod;
	tree[k].a2=(tree[k*2].a2+tree[k*2+1].a2)%mod;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	n=read();m=read();
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op=read();
		if(op==1){
			ll x=read(),y=read(),z=read();
			add(1,x,y,z);
		}
		else{
			ll x=read(),y=read();
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

ll read()
{
	ll res=0,c=getchar();
	while(c<'0' || '9'<c)c=getchar();
	while('0'<=c && c<='9'){res=res*10+c-'0';c=getchar();}
	return res;
}

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

mat mem[100001];

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
	if(k<=100000ll && mem[k].a[0][0]>0)return mem[k];
	mat res;
	ll p=k;
	res.a[0][0]=res.a[1][1]=1ll;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	if(p<=100000ll)mem[p]=res;
//	cout<<' '<<mem[k].a[0][0]<<endl;
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	if(tree[k].tag==0ll)return;
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
//	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=tree[k*2].a1+tree[k*2+1].a1;
	tree[k].a2=tree[k*2].a2+tree[k*2+1].a2;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	n=read();m=read();
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op=read();
		if(op==1){
			ll x=read(),y=read(),z=read();
			add(1,x,y,z);
		}
		else{
			ll x=read(),y=read();
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

ll read()
{
	ll res=0,c=getchar();
	while(c<'0' || '9'<c)c=getchar();
	while('0'<=c && c<='9'){res=res*10+c-'0';c=getchar();}
	return res;
}

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

mat mem[1000001];

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
	if(k<=1000000ll && mem[k].a[0][0]>0ll)return mem[k];
	mat res;
	ll p=k;
	res.a[0][0]=res.a[1][1]=1ll;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	if(p<=1000000ll)mem[p]=res;
//	cout<<' '<<mem[k].a[0][0]<<endl;
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	if(tree[k].tag==0ll)return;
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=(tree[k*2].a1+tree[k*2+1].a1)%mod;
	tree[k].a2=(tree[k*2].a2+tree[k*2+1].a2)%mod;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	n=read();m=read();
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op=read();
		if(op==1){
			ll x=read(),y=read(),z=read();
			add(1,x,y,z);
		}
		else{
			ll x=read(),y=read();
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

ll read()
{
	ll res=0,c=getchar();
	while(c<'0' || '9'<c)c=getchar();
	while('0'<=c && c<='9'){res=res*10+c-'0';c=getchar();}
	return res;
}

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

mat mem[100001];

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
//	if(k<=100000ll && mem[k].a[0][0]>0ll)return mem[k];
	mat res;
	ll p=k;
	res.a[0][0]=res.a[1][1]=1ll;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
//	if(p<=100000ll)mem[p]=res;
//	cout<<' '<<mem[k].a[0][0]<<endl;
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	if(tree[k].tag==0ll)return;
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=tree[k*2].a1+tree[k*2+1].a1;
	tree[k].a2=tree[k*2].a2+tree[k*2+1].a2;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	n=read();m=read();
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op=read();
		if(op==1){
			ll x=read(),y=read(),z=read();
			add(1,x,y,z);
		}
		else{
			ll x=read(),y=read();
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

ll read()
{
	ll res=0,c=getchar();
	while(c<'0' || '9'<c)c=getchar();
	while('0'<=c && c<='9'){res=res*10+c-'0';c=getchar();}
	return res;
}

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

mat mem[1000001];

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
	if(k<=100000ll && mem[k].a[0][0]>0ll)return mem[k];
//	cout<<'#';
	mat res;
	ll p=k;
	res.a[0][0]=res.a[1][1]=1ll;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	if(p<=100000ll)mem[p]=res;
//	cout<<' '<<mem[k].a[0][0]<<endl;
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	if(tree[k].tag==0ll)return;
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
//	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=(tree[k*2].a1+tree[k*2+1].a1)%mod;
	tree[k].a2=(tree[k*2].a2+tree[k*2+1].a2)%mod;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	n=read();m=read();
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op=read();
		if(op==1){
			ll x=read(),y=read(),z=read();
			add(1,x,y,z);
		}
		else{
			ll x=read(),y=read();
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

ll read()
{
	ll res=0,c=getchar();
	while(c<'0' || '9'<c)c=getchar();
	while('0'<=c && c<='9'){res=res*10+c-'0';c=getchar();}
	return res;
}

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

mat mem[100001];

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
//	if(k<=100000ll && mem[k].a[0][0]>0ll)return mem[k];
	mat res;
	ll p=k;
	res.a[0][0]=res.a[1][1]=1ll;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
//	if(p<=100000ll)mem[p]=res;
//	cout<<' '<<mem[k].a[0][0]<<endl;
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	if(tree[k].tag==0ll)return;
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=(tree[k*2].a1+tree[k*2+1].a1)%mod;
	tree[k].a2=(tree[k*2].a2+tree[k*2+1].a2)%mod;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	n=read();m=read();
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op=read();
		if(op==1){
			ll x=read(),y=read(),z=read();
			add(1,x,y,z);
		}
		else{
			ll x=read(),y=read();
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

ll read()
{
	ll res=0,c=getchar();
	while(c<'0' || '9'<c)c=getchar();
	while('0'<=c && c<='9'){res=res*10+c-'0';c=getchar();}
	return res;
}

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

mat mem[100001];

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
//	if(k<=100000ll && mem[k].a[0][0]>0)return mem[k];
	mat res;
	ll p=k;
	res.a[0][0]=res.a[1][1]=1ll;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	if(p<=100000ll)mem[p]=res;
//	cout<<' '<<mem[k].a[0][0]<<endl;
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	if(tree[k].tag==0ll)return;
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
//	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=tree[k*2].a1+tree[k*2+1].a1;
	tree[k].a2=tree[k*2].a2+tree[k*2+1].a2;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	n=read();m=read();
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op=read();
		if(op==1){
			ll x=read(),y=read(),z=read();
			add(1,x,y,z);
		}
		else{
			ll x=read(),y=read();
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0;
	tree[k].a2=1;
	if(l==r)return;
	ll mid=(l+r)>>1;
	build_tree(k*2,l,mid);
	build_tree(k*2+1,mid+1,r);
}

mat quickp(mat y,ll k)
{
	mat res;
	res.a[0][0]=res.a[1][1]=1;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=(tree[k*2].tag+u)%mod;
	tree[k*2+1].tag=(tree[k*2+1].tag+u)%mod;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=(tree[k*2].a1+tree[k*2+1].a1)%mod;
	tree[k].a2=(tree[k*2].a2+tree[k*2+1].a2)%mod;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag=(tree[k].tag+x)%mod;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	scanf("%I64d%I64d",&n,&m);
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op;
		scanf("%I64d",&op);
		if(op==1){
			ll x,y,z;
			scanf("%I64d%I64d%I64d",&x,&y,&z);
			add(1,x,y,z);
		}
		else{
			ll x,y;
			scanf("%I64d%I64d",&x,&y);
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0;
	tree[k].a2=1;
	if(l==r)return;
	ll mid=(l+r)>>1;
	build_tree(k*2,l,mid);
	build_tree(k*2+1,mid+1,r);
}

mat quickp(mat y,ll k)
{
	mat res;
	res.a[0][0]=res.a[1][1]=1;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=(tree[k*2].tag+u)%mod;
	tree[k*2+1].tag=(tree[k*2+1].tag+u)%mod;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=(tree[k*2].a1+tree[k*2+1].a1)%mod;
	tree[k].a2=(tree[k*2].a2+tree[k*2+1].a2)%mod;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	scanf("%I64d%I64d",&n,&m);
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op;
		scanf("%I64d",&op);
		if(op==1){
			ll x,y,z;
			scanf("%I64d%I64d%I64d",&x,&y,&z);
			add(1,x,y,z);
		}
		else{
			ll x,y;
			scanf("%I64d%I64d",&x,&y);
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

ll read()
{
	ll res=0,c=getchar();
	while(c<'0' || '9'<c)c=getchar();
	while('0'<=c && c<='9'){res=res*10+c-'0';c=getchar();}
	return res;
}

struct mat{
	ll a[2][2];
	mat(){
		a[0][1]=a[1][0]=0ll;
		a[0][0]=a[1][1]=1ll;
	}
	friend mat operator*(const mat a,const mat &b){
		mat uo;
		uo.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		uo.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		uo.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		uo.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return uo;
	}
};

struct node{
	ll l,r,a1,a2;
	mat tag;
}tree[500001];

//mat mem[1000001];
mat zero,one;

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat q,ll k)
{
//	if(k<=10000ll && mem[k].a[0][0]>0ll)return mem[k];
//	cout<<'#';
	mat res;
	ll p=k;
//	mat uo;
	while(k)
	{
		if(k%2ll)res=res*q;
		q=q*q;
		k>>=1;
	}
//	if(p<=10000ll)mem[p]=res;
//	cout<<' '<<mem[k].a[0][0]<<endl;
	return res;
}

void push_down(ll k)
{
	if(tree[k].tag.a[0][1]==0ll)return;
	mat u=tree[k].tag;tree[k].tag=zero;
//	cout<<k<<' '<<tree[k].a1<<' '<<tree[k].a2<<' '<<u.a[0][0]<<' '<<u.a[0][1]<<' '<<u.a[1][0]<<' '<<u.a[1][1]<<endl;
	ll x=(tree[k].a1*u.a[0][0]+tree[k].a2*u.a[1][0])%mod,y=(tree[k].a1*u.a[0][1]+tree[k].a2*u.a[1][1])%mod;
	tree[k].a1=x;tree[k].a2=y;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag*u;
	tree[k*2+1].tag=tree[k*2+1].tag*u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
//	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=(tree[k*2].a1+tree[k*2+1].a1)%mod;
	tree[k].a2=(tree[k*2].a2+tree[k*2+1].a2)%mod;
}

void add(ll k,ll l,ll r,const mat &x)
{
//	cout<<x.a[0][0]<<' '<<x.a[0][1]<<' '<<x.a[1][0]<<' '<<x.a[1][1]<<endl;
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag=tree[k].tag*x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
	one.a[0][0]=one.a[0][1]=one.a[1][0]=1;one.a[1][1]=0;
//	cout<<calc(1,0,999999994).first<<endl;
//	for(ll i=1;i<=10;i++){
//		mat x=quickp(one,i);
//		cout<<x.a[0][0]<<' '<<x.a[0][1]<<' '<<x.a[1][0]<<' '<<x.a[1][1]<<endl;
//	}
	ll n,m;
	n=read();m=read();
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,quickp(one,u));
	}
	for(ll i=1;i<=m;i++){
		ll op=read();
		if(op==1){
			ll x=read(),y=read(),z=read();
			mat u=quickp(one,z);
			add(1,x,y,u);
		}
		else{
			ll x=read(),y=read();
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag.a[0][0]<<' '<<tree[j].tag.a[0][1]<<' '<<tree[j].tag.a[1][0]<<' '<<tree[j].tag.a[1][1]<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]+a.a[0][1]*b.a[1][0])%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]+a.a[0][1]*b.a[1][1])%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]+a.a[1][1]*b.a[1][0])%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]+a.a[1][1]*b.a[1][1])%mod;
		return c;
	}
};

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0;
	tree[k].a2=1;
	if(l==r)return;
	ll mid=(l+r)>>1;
	build_tree(k*2,l,mid);
	build_tree(k*2+1,mid+1,r);
}

mat quickp(mat y,ll k)
{
	mat res;
	res.a[0][0]=res.a[1][1]=1;
	while(k)
	{
		if(k%2)res=res*y;
		y=y*y;
		k/=2;
	}
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]+y*q.a[0][1])%mod,(x*q.a[1][0]+y*q.a[1][1])%mod);
}

void push_down(ll k)
{
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=(tree[k*2].tag+u)%mod;
	tree[k*2+1].tag=(tree[k*2+1].tag+u)%mod;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=(tree[k*2].a1+tree[k*2+1].a1)%mod;
	tree[k].a2=(tree[k*2].a2+tree[k*2+1].a2)%mod;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
	ll n,m;
	scanf("%I64d%I64d",&n,&m);
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op;
		scanf("%I64d",&op);
		if(op==1){
			ll x,y,z;
			scanf("%I64d%I64d%I64d",&x,&y,&z);
			add(1,x,y,z);
		}
		else{
			ll x,y;
			scanf("%I64d%I64d",&x,&y);
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1000000007;

struct node{
	ll l,r,a1,a2,tag;
}tree[500001];

ll read()
{
	ll res=0,c=getchar();
	while(c<'0' || '9'<c)c=getchar();
	while('0'<=c && c<='9'){res=res*10+c-'0';c=getchar();}
	return res;
}

struct mat{
	ll a[2][2];
	mat(){
		a[0][0]=a[0][1]=a[1][0]=a[1][1]=0ll;
	}
	friend mat operator*(mat a,mat b)
	{
		mat c;
		c.a[0][0]=(a.a[0][0]*b.a[0][0]%mod+a.a[0][1]*b.a[1][0]%mod)%mod;
		c.a[0][1]=(a.a[0][0]*b.a[0][1]%mod+a.a[0][1]*b.a[1][1]%mod)%mod;
		c.a[1][0]=(a.a[1][0]*b.a[0][0]%mod+a.a[1][1]*b.a[1][0]%mod)%mod;
		c.a[1][1]=(a.a[1][0]*b.a[0][1]%mod+a.a[1][1]*b.a[1][1]%mod)%mod;
		return c;
	}
};

mat mem[100001];

void build_tree(ll k,ll l,ll r)
{
	tree[k].l=l;tree[k].r=r;
	tree[k].a1=0ll;
	tree[k].a2=1ll;
	if(l==r)return;
	ll mid=(l+r)>>1ll;
	build_tree(k*2ll,l,mid);
	build_tree(k*2ll+1ll,mid+1ll,r);
}

mat quickp(mat y,ll k)
{
	if(k<=100000ll && mem[k].a[0][0]>0)return mem[k];
	mat res;
	ll p=k;
	res.a[0][0]=res.a[1][1]=1ll;
	while(k)
	{
		if(k%2ll)res=res*y;
		y=y*y;
		k/=2ll;
	}
	if(p<=100000ll)mem[p]=res;
//	cout<<' '<<mem[k].a[0][0]<<endl;
	return res;
}

pair<ll,ll> calc(ll x,ll y,ll k)
{
	mat q;
	q.a[0][0]=q.a[0][1]=q.a[1][0]=1ll;
	q=quickp(q,k);
	return make_pair((x*q.a[0][0]%mod+y*q.a[0][1]%mod)%mod,(x*q.a[1][0]%mod+y*q.a[1][1]%mod)%mod);
}

void push_down(ll k)
{
	if(tree[k].tag==0)return;
	ll u=tree[k].tag;tree[k].tag=0;
	pair<ll,ll> op=calc(tree[k].a1,tree[k].a2,u);
	tree[k].a1=op.first;tree[k].a2=op.second;
	if(tree[k].l==tree[k].r)return;
	tree[k*2].tag=tree[k*2].tag+u;
	tree[k*2+1].tag=tree[k*2+1].tag+u;
}

void update(ll k)
{
	if(tree[k].l==tree[k].r)return;
//	push_down(k);
	push_down(k*2);push_down(k*2+1);
	tree[k].a1=tree[k*2].a1+tree[k*2+1].a1;
	tree[k].a2=tree[k*2].a2+tree[k*2+1].a2;
}

void add(ll k,ll l,ll r,ll x)
{
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re){
		tree[k].tag+=x;
//		push_down(k);
		return;
	}
	push_down(k);
	ll mid=(le+re)>>1;
	if(r<=mid)add(k*2,l,r,x);
	else if(l>mid)add(k*2+1,l,r,x);
	else{
		add(k*2,l,mid,x);
		add(k*2+1,mid+1,r,x);
	}
	update(k);
}

ll query(ll k,ll l,ll r)
{
//	cout<<k<<endl;
	push_down(k);
	ll le=tree[k].l,re=tree[k].r;
	if(l==le && r==re)return tree[k].a1;
	ll mid=(le+re)>>1ll;
	if(r<=mid)return query(k*2,l,r);
	else if(l>mid)return query(k*2+1,l,r);
	else return (query(k*2,l,mid)+query(k*2+1,mid+1,r))%mod;
}

int main()
{
//	cout<<calc(1,0,999999994).first<<endl;
	ll n,m;
	n=read();m=read();
	build_tree(1,1,n);
	for(ll i=1;i<=n;i++){
		ll u;
		scanf("%I64d",&u);
		add(1,i,i,u);
	}
	for(ll i=1;i<=m;i++){
		ll op=read();
		if(op==1){
			ll x=read(),y=read(),z=read();
			add(1,x,y,z);
		}
		else{
			ll x=read(),y=read();
			printf("%I64d\n",query(1,x,y));
		}
//		for(ll j=1;j<=n*4;j++)cout<<j<<' '<<tree[j].l<<' '<<tree[j].r<<' '<<tree[j].a1<<' '<<tree[j].a2<<' '<<tree[j].tag<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007

struct matrix
{
    ll v[5][5];
    ll row,col;
};
struct data
{
    ll po;
    matrix mul,sum;
};

matrix m1,identity;
data tree[4*100005];
ll A[100005];

matrix add(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            ret.v[i][j]=(a.v[i][j]%mod+b.v[i][j]%mod)%mod;
        }
    }
    return ret;
}

matrix multiply(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            sum=0;
            for(k=0; k<a.col; k++)
            {
                sum=(sum+(a.v[i][k]*b.v[k][j])%mod)%mod;
            }
            ret.v[i][j]=sum%mod;
        }
    }
    return ret;
}

matrix power(matrix mat, ll p)
{
    matrix ret;
    ret=identity;

    while(p>0)
    {
        if(p%2==1)
            ret = multiply(ret,mat);

        mat=multiply(mat,mat);
        p=p/2;
    }
    return ret;
}

void init(ll node,ll b,ll e)
{
    if(e==b)
    {
        tree[node].sum=power(m1,A[b]);
        tree[node].po=0;
        return;
    }

    ll left=0,right=0,mid=0;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    init(left,b,mid);
    init(right,mid+1,e);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].po=0;
}

void update(ll node, ll b, ll e, ll i, ll j, ll val)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].po+=val;
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;
        return;
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    update(left,b,mid,i,j,val);
    update(right,mid+1,e,i,j,val);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
//    tree[node].po=0;
}

ll query(ll node, ll b, ll e, ll i, ll j)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return 0;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;

        return tree[node].sum.v[0][1];
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    ll aa=query(left,b,mid,i,j);
    ll bb=query(right,mid+1,e,i,j);
    tree[node].po=0;
//    cout<<aa<<" "<<bb<<endl;
    return (aa%mod+bb%mod)%mod;
}

int main()
{
    ll t,T,n,m,q,i,j,x,y,val,ans;

    while(scanf("%lld %lld",&n,&q)!=EOF)
    {
        m1.row=2;
        m1.col=2;

        m1.v[0][0]=m1.v[0][1]=m1.v[1][0]=1;
        m1.v[1][1]=0;

        identity.row=2;
        identity.col=2;

        identity.v[0][0]=identity.v[1][1]=1;
        identity.v[0][1]=identity.v[1][0]=0;

        for(i=1; i<=4*n; i++)
        {
            tree[i].sum.row=2;
            tree[i].sum.col=2;
            tree[i].sum.v[0][0]=0;
            tree[i].sum.v[0][1]=0;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][1]=0;
        }

        for(i=1; i<=n; i++)
        {
            scanf("%lld",&A[i]);
        }
        init(1,1,n);
        for(i=1; i<=q; i++)
        {
            scanf("%lld",&m);
//            cout<<tree[1].sum.v[0][1]<<endl;
            if(m==1)
            {
                scanf("%lld %lld %lld",&x,&y,&val);
                update(1,1,n,x,y,val);
            }
            if(m==2)
            {
                scanf("%lld %lld",&x,&y);
                ans=query(1,1,n,x,y)%mod;
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007

struct matrix
{
    ll v[5][5];
    ll row,col;
};
struct data
{
    ll po;
    matrix mul,sum;
};

matrix m1,identity;
data tree[4*100005];
ll A[100005];

matrix add(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            ret.v[i][j]=(a.v[i][j]+b.v[i][j]);
        }
    }
    return ret;
}

matrix multiply(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            sum=0;
            for(k=0; k<a.col; k++)
            {
                sum=(sum+(a.v[i][k]*b.v[k][j]));
            }
            ret.v[i][j]=sum;
        }
    }
    return ret;
}

matrix power(matrix mat, ll p)
{
    matrix ret;
    ret=identity;

    while(p>0)
    {
        if(p%2==1)
            ret = multiply(ret,mat);

        mat=multiply(mat,mat);
        p=p/2;
    }
    return ret;
}

void init(ll node,ll b,ll e)
{
    if(e==b)
    {
        tree[node].sum=power(m1,A[b]);
        tree[node].po=0;
        return;
    }

    ll left=0,right=0,mid=0;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    init(left,b,mid);
    init(right,mid+1,e);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].po=0;
}

void update(ll node, ll b, ll e, ll i, ll j, ll val)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].po+=val;
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;
        return;
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    update(left,b,mid,i,j,val);
    update(right,mid+1,e,i,j,val);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
//    tree[node].po=0;
}

ll query(ll node, ll b, ll e, ll i, ll j)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return 0;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;

        return tree[node].sum.v[0][1];
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    ll aa=query(left,b,mid,i,j);
    ll bb=query(right,mid+1,e,i,j);
    tree[node].po=0;
//    cout<<aa<<" "<<bb<<endl;
    return (aa%mod+bb%mod)%mod;
}

int main()
{
    ll t,T,n,m,q,i,j,x,y,val,ans;

    while(scanf("%lld %lld",&n,&q)!=EOF)
    {
        m1.row=2;
        m1.col=2;

        m1.v[0][0]=m1.v[0][1]=m1.v[1][0]=1;
        m1.v[1][1]=0;

        identity.row=2;
        identity.col=2;

        identity.v[0][0]=identity.v[1][1]=1;
        identity.v[0][1]=identity.v[1][0]=0;

        for(i=1; i<=4*n; i++)
        {
            tree[i].sum.row=2;
            tree[i].sum.col=2;
            tree[i].sum.v[0][0]=0;
            tree[i].sum.v[0][1]=0;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][1]=0;
        }

        for(i=1; i<=n; i++)
        {
            scanf("%lld",&A[i]);
        }
        init(1,1,n);
        for(i=1; i<=q; i++)
        {
            scanf("%lld",&m);
//            cout<<tree[1].sum.v[0][1]<<endl;
            if(m==1)
            {
                scanf("%lld %lld %lld",&x,&y,&val);
                update(1,1,n,x,y,val);
            }
            if(m==2)
            {
                scanf("%lld %lld",&x,&y);
                ans=query(1,1,n,x,y)%mod;
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007

struct matrix
{
    ll v[2][2];
    ll row,col;
};
struct data
{
    matrix mul,sum;
};

matrix m1,m2,identity;
data tree[4*100005];
ll A[100005];

matrix add(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            ret.v[i][j]=(a.v[i][j]%mod+b.v[i][j]%mod)%mod;
        }
    }
    return ret;
}

matrix multiply(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            sum=0;
            for(k=0; k<a.col; k++)
            {
                sum=(sum+(a.v[i][k]%mod*b.v[k][j]%mod)%mod)%mod;
            }
            ret.v[i][j]=sum%mod;
        }
    }
    return ret;
}

matrix power(matrix mat, ll p)
{
    matrix ret;
    ret=identity;

    while(p>0)
    {
        if(p%2==1)
            ret = multiply(ret,mat);

        mat=multiply(mat,mat);
        p=p/2;
    }
    return ret;
}

void pushdown(ll node)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;

    tree[left].mul=multiply(tree[left].mul,tree[node].mul);
    tree[right].mul=multiply(tree[right].mul,tree[node].mul);

    tree[left].sum=multiply(tree[left].sum,tree[node].mul);
    tree[right].sum=multiply(tree[right].sum,tree[node].mul);

    tree[node].mul=identity;
}

void init(ll node,ll b,ll e)
{
    if(e==b)
    {
        tree[node].sum=power(m1,A[b]);
        tree[node].mul=identity;
        return;
    }

    ll left=0,right=0,mid=0;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    init(left,b,mid);
    init(right,mid+1,e);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].mul=identity;
}

void update(ll node, ll b, ll e, ll i, ll j, ll val)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return;
    if(b>=i && e<=j)
    {
        tree[node].sum=multiply(tree[node].sum,m2);
        tree[node].mul=multiply(tree[node].mul,m2);
        return;
    }

    pushdown(node);

    update(left,b,mid,i,j,val);
    update(right,mid+1,e,i,j,val);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
}

ll query(ll node, ll b, ll e, ll i, ll j)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return 0;
    if(b>=i && e<=j)
    {
        return tree[node].sum.v[0][1];
    }

    pushdown(node);

    ll aa=query(left,b,mid,i,j);
    ll bb=query(right,mid+1,e,i,j);
    tree[node].sum=add(tree[left].sum,tree[right].sum);
//    cout<<aa<<" "<<bb<<endl;
    if(aa>=mod)
        aa=aa%mod;
    if(bb>=mod)
        bb=bb%mod;
    aa+=bb;
    if(aa>=mod)
        aa=aa%mod;
    return aa;
}

int main()
{
    ll t,T,n,m,q,i,j,x,y,val,ans;

    while(scanf("%lld %lld",&n,&q)!=EOF)
    {
        m1.row=2;
        m1.col=2;

        m1.v[0][0]=m1.v[0][1]=m1.v[1][0]=1;
        m1.v[1][1]=0;

        identity.row=2;
        identity.col=2;

        identity.v[0][0]=identity.v[1][1]=1;
        identity.v[0][1]=identity.v[1][0]=0;

        for(i=1; i<=n; i++)
        {
            scanf("%lld",&A[i]);
        }

        init(1,1,n);

        for(i=1; i<=q; i++)
        {
            scanf("%lld",&m);
//            cout<<tree[1].sum.v[0][1]<<endl;
            if(m==1)
            {
                scanf("%lld %lld %lld",&x,&y,&val);
                m2=power(m1,val);
                update(1,1,n,x,y,val);
            }
            if(m==2)
            {
                scanf("%lld %lld",&x,&y);
                ans=query(1,1,n,x,y);
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007

struct matrix
{
    ll v[2][2];
    int row,col;
};
struct data
{
    matrix mul,sum;
};

matrix m1,m2,identity;
data tree[4*100005];
ll A[100005];

matrix add(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            if(a.v[i][j]>=mod)
                a.v[i][j]%=mod;
            if(b.v[i][j]>=mod)
                b.v[i][j]%=mod;
            ret.v[i][j]=(a.v[i][j]+b.v[i][j]);
            if(ret.v[i][j]>=mod)
                ret.v[i][j]%=mod;
        }
    }
    return ret;
}

matrix multiply(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum,aa;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            sum=0;
            for(k=0; k<a.col; k++)
            {
                if(a.v[i][j]>=mod)
                    a.v[i][j]%=mod;
                if(b.v[i][j]>=mod)
                    b.v[i][j]%=mod;
                aa=(a.v[i][k]*b.v[k][j]);
                if(aa>=mod)
                    aa%=mod;
                sum=sum+aa;
                if(sum>=mod)
                    sum%=mod;
            }
            ret.v[i][j]=sum;
        }
    }
    return ret;
}

matrix power(matrix mat, ll p)
{
    matrix ret;
    ret=identity;

    while(p>0)
    {
        if(p%2==1)
            ret = multiply(ret,mat);

        mat=multiply(mat,mat);
        p=p/2;
    }
    return ret;
}

void pushdown(ll node)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;

    tree[left].mul=multiply(tree[left].mul,tree[node].mul);
    tree[right].mul=multiply(tree[right].mul,tree[node].mul);

    tree[left].sum=multiply(tree[left].sum,tree[node].mul);
    tree[right].sum=multiply(tree[right].sum,tree[node].mul);

    tree[node].mul=identity;
}

void init(ll node,ll b,ll e)
{
    if(e==b)
    {
        tree[node].sum=power(m1,A[b]);
        tree[node].mul=identity;
        return;
    }

    ll left=0,right=0,mid=0;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    init(left,b,mid);
    init(right,mid+1,e);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].mul=identity;
}

void update(ll node, ll b, ll e, ll i, ll j, ll val)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return;
    if(b>=i && e<=j)
    {
        tree[node].sum=multiply(tree[node].sum,m2);
        tree[node].mul=multiply(tree[node].mul,m2);
        return;
    }

    pushdown(node);

    update(left,b,mid,i,j,val);
    update(right,mid+1,e,i,j,val);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
}

ll query(ll node, ll b, ll e, ll i, ll j)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return 0;
    if(b>=i && e<=j)
    {
        return tree[node].sum.v[0][1];
    }

    pushdown(node);

    ll aa=query(left,b,mid,i,j);
    ll bb=query(right,mid+1,e,i,j);
    tree[node].sum=add(tree[left].sum,tree[right].sum);
//    cout<<aa<<" "<<bb<<endl;
    if(aa>=mod)
        aa=aa%mod;
    if(bb>=mod)
        bb=bb%mod;
    aa+=bb;
    if(aa>=mod)
        aa=aa%mod;
    return aa;
}

int main()
{
    ll t,T,n,m,q,i,j,x,y,val,ans;

    while(scanf("%lld %lld",&n,&q)!=EOF)
    {
        m1.row=2;
        m1.col=2;

        m1.v[0][0]=m1.v[0][1]=m1.v[1][0]=1;
        m1.v[1][1]=0;

        identity.row=2;
        identity.col=2;

        identity.v[0][0]=identity.v[1][1]=1;
        identity.v[0][1]=identity.v[1][0]=0;

        for(i=1; i<=n; i++)
        {
            scanf("%lld",&A[i]);
        }

        init(1,1,n);

        for(i=1; i<=q; i++)
        {
            scanf("%lld",&m);
//            cout<<tree[1].sum.v[0][1]<<endl;
            if(m==1)
            {
                scanf("%lld %lld %lld",&x,&y,&val);
                m2=power(m1,val);
                update(1,1,n,x,y,val);
            }
            if(m==2)
            {
                scanf("%lld %lld",&x,&y);
                ans=query(1,1,n,x,y);
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007

struct matrix
{
    ll v[5][5];
    ll row,col;
};
struct data
{
    ll po;
    matrix mul,sum;
};

matrix m1,identity;
data tree[4*100005];
ll A[100005];

matrix add(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            ret.v[i][j]=(a.v[i][j]%mod+b.v[i][j]%mod)%mod;
        }
    }
    return ret;
}

matrix multiply(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            sum=0;
            for(k=0; k<a.col; k++)
            {
                sum=(sum+(a.v[i][k]%mod*b.v[k][j]%mod)%mod)%mod;
            }
            ret.v[i][j]=sum%mod;
        }
    }
    return ret;
}

matrix power(matrix mat, ll p)
{
    matrix ret;
    ret=identity;

    while(p>0)
    {
        if(p%2==1)
            ret = multiply(ret,mat);

        mat=multiply(mat,mat);
        p=p/2;
    }
    return ret;
}

void init(ll node,ll b,ll e)
{
    if(e==b)
    {
        tree[node].sum=power(m1,A[b]);
        tree[node].po=0;
        return;
    }

    ll left=0,right=0,mid=0;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    init(left,b,mid);
    init(right,mid+1,e);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].po=0;
}

void update(ll node, ll b, ll e, ll i, ll j, ll val)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].po+=val;
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;
        return;
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    update(left,b,mid,i,j,val);
    update(right,mid+1,e,i,j,val);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    if(tree[left].po==0 && tree[right].po==0)
    tree[node].po=0;
}

ll query(ll node, ll b, ll e, ll i, ll j)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return 0;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;

        return tree[node].sum.v[0][1];
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    ll aa=query(left,b,mid,i,j);
    ll bb=query(right,mid+1,e,i,j);
    if(tree[left].po==0 && tree[right].po==0)
    tree[node].po=0;
//    cout<<aa<<" "<<bb<<endl;
    return (aa%mod+bb%mod)%mod;
}

int main()
{
    ll t,T,n,m,q,i,j,x,y,val,ans;

    while(scanf("%lld %lld",&n,&q)!=EOF)
    {
        m1.row=2;
        m1.col=2;

        m1.v[0][0]=m1.v[0][1]=m1.v[1][0]=1;
        m1.v[1][1]=0;

        identity.row=2;
        identity.col=2;

        identity.v[0][0]=identity.v[1][1]=1;
        identity.v[0][1]=identity.v[1][0]=0;

        for(i=1; i<=4*n; i++)
        {
            tree[i].sum.row=2;
            tree[i].sum.col=2;
            tree[i].sum.v[0][0]=0;
            tree[i].sum.v[0][1]=0;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][1]=0;
        }

        for(i=1; i<=n; i++)
        {
            scanf("%lld",&A[i]);
        }
        init(1,1,n);
        for(i=1; i<=q; i++)
        {
            scanf("%lld",&m);
//            cout<<tree[1].sum.v[0][1]<<endl;
            if(m==1)
            {
                scanf("%lld %lld %lld",&x,&y,&val);
                update(1,1,n,x,y,val);
            }
            if(m==2)
            {
                scanf("%lld %lld",&x,&y);
                ans=query(1,1,n,x,y)%mod;
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007

struct matrix
{
    ll v[5][5];
    ll row,col;
};
struct data
{
    ll po;
    matrix mul,sum;
};

matrix m1,identity;
data tree[4*100005];
ll A[100005];

matrix add(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            ret.v[i][j]=(a.v[i][j]%mod+b.v[i][j]%mod)%mod;
        }
    }
    return ret;
}

matrix multiply(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            sum=0;
            for(k=0; k<a.col; k++)
            {
                sum=(sum+(a.v[i][k]*b.v[k][j])%mod)%mod;
            }
            ret.v[i][j]=sum%mod;
        }
    }
    return ret;
}

matrix power(matrix mat, ll p)
{
    matrix ret;
    ret=identity;

    while(p>0)
    {
        if(p%2==1)
            ret = multiply(ret,mat);

        mat=multiply(mat,mat);
        p=p/2;
    }
    return ret;
}

void init(ll node,ll b,ll e)
{
    if(e==b)
    {
        tree[node].sum=power(m1,A[b]);
        tree[node].po=0;
        return;
    }

    ll left=0,right=0,mid=0;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    init(left,b,mid);
    init(right,mid+1,e);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].po=0;
}

void update(ll node, ll b, ll e, ll i, ll j, ll val)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].po+=val;
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;
        return;
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    update(left,b,mid,i,j,val);
    update(right,mid+1,e,i,j,val);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
//    tree[node].po=0;
}

ll query(ll node, ll b, ll e, ll i, ll j)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return 0;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;

        return tree[node].sum.v[0][1];
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    ll aa=query(left,b,mid,i,j);
    ll bb=query(right,mid+1,e,i,j);
    tree[node].po=0;
//    cout<<aa<<" "<<bb<<endl;
    return (aa%mod+bb%mod)%mod;
}

int main()
{
    ll t,T,n,m,q,i,j,x,y,val,ans;

    while(scanf("%lld %lld",&n,&q)!=EOF)
    {
        m1.row=2;
        m1.col=2;

        m1.v[0][0]=m1.v[0][1]=m1.v[1][0]=1;
        m1.v[1][1]=0;

        identity.row=2;
        identity.col=2;

        identity.v[0][0]=identity.v[1][1]=1;
        identity.v[0][1]=identity.v[1][0]=0;

        for(i=1; i<=4*n; i++)
        {
            tree[i].sum.row=2;
            tree[i].sum.col=2;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][0]=0;
        }

        for(i=1; i<=n; i++)
        {
            scanf("%lld",&A[i]);
        }
        init(1,1,n);
        for(i=1; i<=q; i++)
        {
            scanf("%lld",&m);
//            cout<<tree[1].sum.v[0][1]<<endl;
            if(m==1)
            {
                scanf("%lld %lld %lld",&x,&y,&val);
                update(1,1,n,x,y,val);
            }
            if(m==2)
            {
                scanf("%lld %lld",&x,&y);
                ans=query(1,1,n,x,y)%mod;
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007

struct matrix
{
    ll v[5][5];
    ll row,col;
};
struct data
{
    ll po;
    matrix mul,sum;
};

matrix m1,identity;
data tree[4*100005];
ll A[100005];

matrix add(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            ret.v[i][j]=(a.v[i][j]+b.v[i][j])%mod;
        }
    }
    return ret;
}

matrix multiply(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            sum=0;
            for(k=0; k<a.col; k++)
            {
                sum=(sum+(a.v[i][k]*b.v[k][j])%mod)%mod;
            }
            ret.v[i][j]=sum%mod;
        }
    }
    return ret;
}

matrix power(matrix mat, ll p)
{
    matrix ret;
    ret=identity;

    while(p>0)
    {
        if(p%2==1)
            ret = multiply(ret,mat);

        mat=multiply(mat,mat);
        p=p/2;
    }
    return ret;
}

void init(ll node,ll b,ll e)
{
    if(e==b)
    {
        tree[node].sum=power(m1,A[b]);
        tree[node].po=0;
        return;
    }

    ll left=0,right=0,mid=0;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    init(left,b,mid);
    init(right,mid+1,e);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].po=0;
}

void update(ll node, ll b, ll e, ll i, ll j, ll val)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].po+=val;
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;
        return;
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    update(left,b,mid,i,j,val);
    update(right,mid+1,e,i,j,val);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
//    tree[node].po=0;
}

ll query(ll node, ll b, ll e, ll i, ll j)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return 0;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;

        return tree[node].sum.v[0][1];
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    ll aa=query(left,b,mid,i,j);
    ll bb=query(right,mid+1,e,i,j);
    tree[node].po=0;
//    cout<<aa<<" "<<bb<<endl;
    return aa+bb;
}

int main()
{
    ll t,T,n,m,q,i,j,x,y,val,ans;

    while(scanf("%lld %lld",&n,&q)!=EOF)
    {
        m1.row=2;
        m1.col=2;

        m1.v[0][0]=m1.v[0][1]=m1.v[1][0]=1;
        m1.v[1][1]=0;

        identity.row=2;
        identity.col=2;

        identity.v[0][0]=identity.v[1][1]=1;
        identity.v[0][1]=identity.v[1][0]=0;

        for(i=1; i<=4*n; i++)
        {
            tree[i].sum.row=2;
            tree[i].sum.col=2;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][0]=0;
        }

        for(i=1; i<=n; i++)
        {
            scanf("%lld",&A[i]);
        }
        init(1,1,n);
        for(i=1; i<=q; i++)
        {
            scanf("%lld",&m);
//            cout<<tree[1].sum.v[0][1]<<endl;
            if(m==1)
            {
                scanf("%lld %lld %lld",&x,&y,&val);
                update(1,1,n,x,y,val);
            }
            if(m==2)
            {
                scanf("%lld %lld",&x,&y);
                ans=query(1,1,n,x,y);
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007

struct matrix
{
    ll v[5][5];
    ll row,col;
};
struct data
{
    ll po;
    matrix mul,sum;
};

matrix m1,identity;
data tree[4*100005];
ll A[100005];

matrix add(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            ret.v[i][j]=(a.v[i][j]+b.v[i][j])%mod;
        }
    }
    return ret;
}

matrix multiply(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            sum=0;
            for(k=0; k<a.col; k++)
            {
                sum=(sum+(a.v[i][k]*b.v[k][j])%mod)%mod;
            }
            ret.v[i][j]=sum%mod;
        }
    }
    return ret;
}

matrix power(matrix mat, ll p)
{
    matrix ret;
    ret=identity;

    while(p>0)
    {
        if(p%2==1)
            ret = multiply(ret,mat);

        mat=multiply(mat,mat);
        p=p/2;
    }
    return ret;
}

void init(ll node,ll b,ll e)
{
    if(e==b)
    {
        tree[node].sum=power(m1,A[b]);
        tree[node].po=0;
        return;
    }

    ll left=0,right=0,mid=0;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    init(left,b,mid);
    init(right,mid+1,e);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].po=0;
}

void update(ll node, ll b, ll e, ll i, ll j, ll val)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].po+=val;
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;
        return;
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    update(left,b,mid,i,j,val);
    update(right,mid+1,e,i,j,val);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].po=0;
}

ll query(ll node, ll b, ll e, ll i, ll j)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return 0;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;

        return tree[node].sum.v[0][1];
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    ll aa=query(left,b,mid,i,j);
    ll bb=query(right,mid+1,e,i,j);
    tree[node].po=0;
    return aa+bb;
}

int main()
{
    ll t,T,n,m,q,i,j,x,y,val,ans;

    while(scanf("%lld %lld",&n,&q)!=EOF)
    {
        m1.row=2;
        m1.col=2;

        m1.v[0][0]=m1.v[0][1]=m1.v[1][0]=1;
        m1.v[1][1]=0;

        identity.row=2;
        identity.col=2;

        identity.v[0][0]=identity.v[1][1]=1;
        identity.v[0][1]=identity.v[1][0]=0;

        for(i=1; i<=4*n; i++)
        {
            tree[i].sum.row=2;
            tree[i].sum.col=2;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][0]=0;
        }

        for(i=1; i<=n; i++)
        {
            scanf("%lld",&A[i]);
        }
        init(1,1,n);
        for(i=1; i<=q; i++)
        {
            scanf("%lld",&m);
//            cout<<tree[1].sum.v[0][1]<<endl;
            if(m==1)
            {
                scanf("%lld %lld %lld",&x,&y,&val);
                update(1,1,n,x,y,val);
            }
            if(m==2)
            {
                scanf("%lld %lld",&x,&y);
                ans=query(1,1,n,x,y);
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007

struct matrix
{
    ll v[5][5];
    ll row,col;
};
struct data
{
    ll po;
    matrix mul,sum;
};

matrix m1,identity;
data tree[4*100005];
ll A[100005];

matrix add(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            ret.v[i][j]=(a.v[i][j]%mod+b.v[i][j]%mod)%mod;
        }
    }
    return ret;
}

matrix multiply(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            sum=0;
            for(k=0; k<a.col; k++)
            {
                sum=(sum+(a.v[i][k]%mod*b.v[k][j]%mod)%mod)%mod;
            }
            ret.v[i][j]=sum%mod;
        }
    }
    return ret;
}

matrix power(matrix mat, ll p)
{
    matrix ret;
    ret=identity;

    while(p>0)
    {
        if(p%2==1)
            ret = multiply(ret,mat);

        mat=multiply(mat,mat);
        p=p/2;
    }
    return ret;
}

void init(ll node,ll b,ll e)
{
    if(e==b)
    {
        tree[node].sum=power(m1,A[b]);
        tree[node].po=0;
        return;
    }

    ll left=0,right=0,mid=0;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    init(left,b,mid);
    init(right,mid+1,e);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].po=0;
}

void update(ll node, ll b, ll e, ll i, ll j, ll val)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].po+=val;
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;
        return;
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    update(left,b,mid,i,j,val);
    update(right,mid+1,e,i,j,val);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
//    tree[node].po=0;
}

ll query(ll node, ll b, ll e, ll i, ll j)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return 0;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;

        return tree[node].sum.v[0][1];
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    ll aa=query(left,b,mid,i,j);
    ll bb=query(right,mid+1,e,i,j);
    tree[node].po=0;
//    cout<<aa<<" "<<bb<<endl;
    return (aa%mod+bb%mod)%mod;
}

int main()
{
    ll t,T,n,m,q,i,j,x,y,val,ans;

    while(scanf("%lld %lld",&n,&q)!=EOF)
    {
        m1.row=2;
        m1.col=2;

        m1.v[0][0]=m1.v[0][1]=m1.v[1][0]=1;
        m1.v[1][1]=0;

        identity.row=2;
        identity.col=2;

        identity.v[0][0]=identity.v[1][1]=1;
        identity.v[0][1]=identity.v[1][0]=0;

        for(i=1; i<=4*n; i++)
        {
            tree[i].sum.row=2;
            tree[i].sum.col=2;
            tree[i].sum.v[0][0]=0;
            tree[i].sum.v[0][1]=0;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][1]=0;
        }

        for(i=1; i<=n; i++)
        {
            scanf("%lld",&A[i]);
        }
        init(1,1,n);
        for(i=1; i<=q; i++)
        {
            scanf("%lld",&m);
//            cout<<tree[1].sum.v[0][1]<<endl;
            if(m==1)
            {
                scanf("%lld %lld %lld",&x,&y,&val);
                update(1,1,n,x,y,val);
            }
            if(m==2)
            {
                scanf("%lld %lld",&x,&y);
                ans=query(1,1,n,x,y)%mod;
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007

struct matrix
{
    ll v[2][2];
    ll row,col;
};
struct data
{
    matrix mul,sum;
};

matrix m1,m2,identity;
data tree[4*100005];
ll A[100005];

matrix add(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            ret.v[i][j]=(a.v[i][j]%mod+b.v[i][j]%mod)%mod;
        }
    }
    return ret;
}

matrix multiply(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            sum=0;
            for(k=0; k<a.col; k++)
            {
                sum=(sum+(a.v[i][k]%mod*b.v[k][j]%mod)%mod)%mod;
            }
            ret.v[i][j]=sum%mod;
        }
    }
    return ret;
}

matrix power(matrix mat, ll p)
{
    matrix ret;
    ret=identity;

    while(p>0)
    {
        if(p%2==1)
            ret = multiply(ret,mat);

        mat=multiply(mat,mat);
        p=p/2;
    }
    return ret;
}

void pushdown(ll node)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;

    tree[left].mul=multiply(tree[left].mul,tree[node].mul);
    tree[right].mul=multiply(tree[right].mul,tree[node].mul);

    tree[left].sum=multiply(tree[left].sum,tree[node].mul);
    tree[right].sum=multiply(tree[right].sum,tree[node].mul);

    tree[node].mul=identity;
}

void init(ll node,ll b,ll e)
{
    if(e==b)
    {
        tree[node].sum=power(m1,A[b]);
        tree[node].mul=identity;
        return;
    }

    ll left=0,right=0,mid=0;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    init(left,b,mid);
    init(right,mid+1,e);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].mul=identity;
}

void update(ll node, ll b, ll e, ll i, ll j, ll val)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return;
    if(b>=i && e<=j)
    {
        tree[node].sum=multiply(tree[node].sum,m2);
        tree[node].mul=multiply(tree[node].mul,m2);
        return;
    }

    pushdown(node);

    update(left,b,mid,i,j,val);
    update(right,mid+1,e,i,j,val);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
}

ll query(ll node, ll b, ll e, ll i, ll j)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return 0;
    if(b>=i && e<=j)
    {
        return tree[node].sum.v[0][1];
    }

    pushdown(node);

    ll aa=query(left,b,mid,i,j);
    ll bb=query(right,mid+1,e,i,j);
    tree[node].sum=add(tree[left].sum,tree[right].sum);
//    cout<<aa<<" "<<bb<<endl;
    return (aa%mod+bb%mod)%mod;
}

int main()
{
    ll t,T,n,m,q,i,j,x,y,val,ans;

    while(scanf("%lld %lld",&n,&q)!=EOF)
    {
        m1.row=2;
        m1.col=2;

        m1.v[0][0]=m1.v[0][1]=m1.v[1][0]=1;
        m1.v[1][1]=0;

        identity.row=2;
        identity.col=2;

        identity.v[0][0]=identity.v[1][1]=1;
        identity.v[0][1]=identity.v[1][0]=0;

        for(i=1; i<=n; i++)
        {
            scanf("%lld",&A[i]);
        }

        init(1,1,n);

        for(i=1; i<=q; i++)
        {
            scanf("%lld",&m);
//            cout<<tree[1].sum.v[0][1]<<endl;
            if(m==1)
            {
                scanf("%lld %lld %lld",&x,&y,&val);
                m2=power(m1,val);
                update(1,1,n,x,y,val);
            }
            if(m==2)
            {
                scanf("%lld %lld",&x,&y);
                ans=query(1,1,n,x,y)%mod;
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define mod 1000000007

struct matrix
{
    ll v[5][5];
    ll row,col;
};
struct data
{
    ll po;
    matrix mul,sum;
};

matrix m1,identity;
data tree[4*100005];
ll A[100005];

matrix add(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            ret.v[i][j]=(a.v[i][j]%mod+b.v[i][j]%mod)%mod;
        }
    }
    return ret;
}

matrix multiply(matrix a, matrix b)
{
    matrix ret;
    ll i,j,k,sum;
    ret.row=a.row;
    ret.col=b.col;
    for(i=0; i<ret.row; i++)
    {
        for(j=0; j<ret.col; j++)
        {
            sum=0;
            for(k=0; k<a.col; k++)
            {
                sum=(sum+(a.v[i][k]%mod*b.v[k][j]%mod)%mod)%mod;
            }
            ret.v[i][j]=sum%mod;
        }
    }
    return ret;
}

matrix power(matrix mat, ll p)
{
    matrix ret;
    ret=identity;

    while(p>0)
    {
        if(p%2==1)
            ret = multiply(ret,mat);

        mat=multiply(mat,mat);
        p=p/2;
    }
    return ret;
}

void init(ll node,ll b,ll e)
{
    if(e==b)
    {
        tree[node].sum=power(m1,A[b]);
        tree[node].po=0;
        return;
    }

    ll left=0,right=0,mid=0;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    init(left,b,mid);
    init(right,mid+1,e);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    tree[node].po=0;
}

void update(ll node, ll b, ll e, ll i, ll j, ll val)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].po+=val;
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;
        return;
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    update(left,b,mid,i,j,val);
    update(right,mid+1,e,i,j,val);

    tree[node].sum=add(tree[left].sum,tree[right].sum);
    if(tree[left].po==0 && tree[right].po==0)
    tree[node].po=0;
}

ll query(ll node, ll b, ll e, ll i, ll j)
{
    ll left,right,mid;
    left=2*node;
    right=2*node+1;
    mid=(b+e)/2;

    if(b>j || e<i)
        return 0;
    if(b>=i && e<=j && tree[node].po!=-1)
    {
        tree[node].sum=multiply(tree[node].sum,power(m1,tree[node].po));

        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=0;

        return tree[node].sum.v[0][1];
    }

    if(tree[node].po!=-1)
    {
        tree[left].po+=tree[node].po;
        tree[right].po+=tree[node].po;
        tree[node].po=-1;
    }

    ll aa=query(left,b,mid,i,j);
    ll bb=query(right,mid+1,e,i,j);
//    if(tree[left].po==0 && tree[right].po==0)
    tree[node].po=0;
//    cout<<aa<<" "<<bb<<endl;
    return (aa%mod+bb%mod)%mod;
}

int main()
{
    ll t,T,n,m,q,i,j,x,y,val,ans;

    while(scanf("%lld %lld",&n,&q)!=EOF)
    {
        m1.row=2;
        m1.col=2;

        m1.v[0][0]=m1.v[0][1]=m1.v[1][0]=1;
        m1.v[1][1]=0;

        identity.row=2;
        identity.col=2;

        identity.v[0][0]=identity.v[1][1]=1;
        identity.v[0][1]=identity.v[1][0]=0;

        for(i=1; i<=4*n; i++)
        {
            tree[i].sum.row=2;
            tree[i].sum.col=2;
            tree[i].sum.v[0][0]=0;
            tree[i].sum.v[0][1]=0;
            tree[i].sum.v[1][0]=0;
            tree[i].sum.v[1][1]=0;
        }

        for(i=1; i<=n; i++)
        {
            scanf("%lld",&A[i]);
        }
        init(1,1,n);
        for(i=1; i<=q; i++)
        {
            scanf("%lld",&m);
//            cout<<tree[1].sum.v[0][1]<<endl;
            if(m==1)
            {
                scanf("%lld %lld %lld",&x,&y,&val);
                update(1,1,n,x,y,val);
            }
            if(m==2)
            {
                scanf("%lld %lld",&x,&y);
                ans=query(1,1,n,x,y)%mod;
                printf("%lld\n",ans);
            }
        }
    }

    return 0;
}