#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+1;
int a[N],n,q,m=1e9+7,op,x,y,t,times;
struct segtree{
struct node{
int l,r;
int sum,sum2,b,len;
int mul;
int add;
}t[N*4-3];
void pushup(int p){
if(t[p].b){
return;
}
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].sum2=t[p*2].sum2+t[p*2+1].sum2;
t[p].sum%=m;
t[p].sum2%=m;
t[p].len=t[p*2].len+t[p*2+1].len;
}
void pushdown(int p){
if(t[p*2].b==0){
t[p*2].add*=t[p].mul;
t[p*2].add%=m;
t[p*2].add+=t[p].add;
t[p*2].add%=m;
t[p*2].mul*=t[p].mul;
t[p*2].mul%=m;
t[p*2].sum*=t[p].mul;
t[p*2].sum%=m;
t[p*2].sum+=t[p*2].len%m*t[p].add%m;
t[p*2].sum%=m;
return;
}
if(t[p*2+1].b==0){
t[p*2+1].add*=t[p].mul;
t[p*2+1].add%=m;
t[p*2+1].add+=t[p].add;
t[p*2+1].add%=m;
t[p*2+1].mul*=t[p].mul;
t[p*2+1].mul%=m;
t[p*2+1].sum*=t[p].mul;
t[p*2+1].sum%=m;
t[p*2+1].sum+=t[p*2+1].len%m*t[p].add%m;
t[p*2+1].sum%=m;
}
t[p].add=0;
t[p].mul=1;
}
void build(int p,int l,int r,int a[]){
t[p].mul=1;
t[p].l=l;
t[p].r=r;
if(l==r){
t[p].sum=a[l]%m;
t[p].len=1;
return;
}
build(p*2,l,(l+r)/2,a);
build(p*2+1,(l+r)/2+1,r,a);
pushup(p);
}
void update(int p,int l,int r,int c){
if(t[p].b){
return;
}
if(t[p].l>=l&&t[p].r<=r){
t[p].add+=c%m;
t[p].add%=m;
t[p].sum+=t[p].len%m*(c%m)%m;
t[p].sum%=m;
return;
}
int mid=(t[p].l+t[p].r)/2;
pushdown(p);
if(l<=mid){
update(p*2,l,r,c);
}
if(r>mid){
update(p*2+1,l,r,c);
}
pushup(p);
}
void update2(int p,int l,int r,int c){
if(t[p].b){
return;
}
if(t[p].l>=l&&t[p].r<=r){
t[p].mul*=c%m;
t[p].mul%=m;
t[p].add*=c%m;
t[p].add%=m;
t[p].sum*=c%m;
t[p].sum%=m;
return;
}
int mid=(t[p].l+t[p].r)/2;
pushdown(p);
if(l<=mid){
update2(p*2,l,r,c);
}
if(r>mid){
update2(p*2+1,l,r,c);
}
pushup(p);
}
void update3(int p,int l,int r){
if(t[p].l>=l&&t[p].r<=r){
if(t[p].l!=t[p].r){
pushdown(p);
}
if(t[p].b==0){
t[p].sum2+=t[p].sum;
t[p].sum2%=m;
t[p].sum=0;
t[p].len=0;
}
t[p].b++;
return;
}
int mid=(t[p].l+t[p].r)/2;
pushdown(p);
if(l<=mid){
update3(p*2,l,r);
}
if(r>mid){
update3(p*2+1,l,r);
}
pushup(p);
}
void update4(int p,int l,int r){
if(t[p].l>=l&&t[p].r<=r){
t[p].b--;
if(t[p].b==0){
if(t[p].l==t[p].r){
swap(t[p].sum,t[p].sum2);
t[p].len=1;
}
else{
pushup(p);
}
}
return;
}
int mid=(t[p].l+t[p].r)/2;
pushdown(p);
if(l<=mid){
update4(p*2,l,r);
}
if(r>mid){
update4(p*2+1,l,r);
}
pushup(p);
}
int query(int p,int l,int r){
if(t[p].l>=l&&t[p].r<=r){
return (t[p].sum+t[p].sum2)%m;
}
int mid=(t[p].l+t[p].r)/2;
pushdown(p);
int ret=0;
if(l<=mid){
ret+=query(p*2,l,r);
ret%=m;
}
if(r>mid){
ret+=query(p*2+1,l,r);
ret%=m;
}
return ret;
}
}k;
vector<pair<int,int>>v[N];
signed main(){
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
}
k.build(1,1,n,a);
for(int i=1;i<=q;i++){
cin>>op>>x>>y;
if(op<=3){
cin>>t;
if(op==1){
k.update(1,x,y,t);
}
else if(op==2){
k.update2(1,x,y,t);
}
else{
k.update3(1,x,y);
v[i+t].push_back({x,y});
}
}
else{
cout<<k.query(1,x,y)<<"\n";
}
for(auto j:v[i]){
k.update4(1,j.first,j.second);
}
}
return 0;
}