#include<bits/stdc++.h>
using namespace std;
namespace input
{
const long long len=1<<21;
char buf[len],*S,*T;
inline char getchar()
{
if(S==T)
{
T=(S=buf)+fread(buf,1,len,stdin);
if(S==T)
{
return '\n';
}
}
return *S++;
}
}
namespace output
{
const int len=1<<21;
char buf[len],*S=buf,*T=buf+len;
inline void flush()
{
fwrite(buf,1,S-buf,stdout);
S=buf;
}
inline void putchar(char c)
{
*S++=c;
if(S==T)
{
flush();
}
}
struct NTR
{
~NTR()
{
flush();
}
}ztr;
}
#ifdef ONLINE_JUDGE
#define getchar input::getchar
#define putchar output::putchar
#endif
namespace FastIO
{
struct Reader
{
template<typename T>
Reader& operator >> (T& x)
{
char c=getchar();
T f=1;
while(c<'0' or c>'9')
{
if(c=='-')
{
f=-1;
}
c=getchar();
}
x=0;
while(c>='0' and c<='9')
{
x=x*10+(c-'0');
c=getchar();
}
x*=f;
return *this;
}
Reader& operator >> (char& c)
{
c=getchar();
while(c==' ' or c=='\n')
{
c=getchar();
}
return *this;
}
Reader& operator >> (char* str)
{
long long len=0;
char c=getchar();
while(c==' ' or c=='\n')
{
c=getchar();
}
while(c!=' ' and c!='\n' and c!='\r')
{
str[len++]=c;
c=getchar();
}
str[len]='\0';
return *this;
}
Reader(){}
}cin;
const char endl='\n';
struct Writer
{
template<typename T>
Writer& operator << (T x)
{
if(!x)
{
putchar('0');
return *this;
}
if(x<0)
{
putchar('-');
x=-x;
}
static long long sta[45];
long long top=0;
while(x)
{
sta[++top]=x%10;
x/=10;
}
while(top)
{
putchar(sta[top]+'0');
--top;
}
return *this;
}
Writer& operator << (char c)
{
putchar(c);
return *this;
}
Writer& operator << (char* str)
{
long long cur=0;
while(str[cur])
{
putchar(str[cur++]);
}
return *this;
}
Writer& operator << (const char* str)
{
long long cur=0;
while(str[cur])
{
putchar(str[cur++]);
}
return *this;
}
Writer(){}
}cout;
}
#define cin FastIO::cin
#define cout FastIO::cout
#define endl FastIO::endl
const long long N=2e5+1;
long long a[N],n,q,m=1e9+7,op,x,y,t;
struct segtree{
struct node{
long long l,r;
long long sum,sum2,b,len;
long long mul;
long long add;
}t[N*4-3];
void pushup(long long p){
if(t[p].b){
return;
}
t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
t[p].sum2=t[p<<1].sum2+t[p<<1|1].sum2;
t[p].sum%=m;
t[p].sum2%=m;
t[p].len=t[p<<1].len+t[p<<1|1].len;
}
void pushdown(long long p){
if(!t[p<<1].b){
t[p<<1].add*=t[p].mul;
t[p<<1].add%=m;
t[p<<1].add+=t[p].add;
t[p<<1].add%=m;
t[p<<1].mul*=t[p].mul;
t[p<<1].mul%=m;
t[p<<1].sum*=t[p].mul;
t[p<<1].sum%=m;
t[p<<1].sum+=t[p<<1].len%m*t[p].add%m;
t[p<<1].sum%=m;
}
if(!t[p<<1|1].b){
t[p<<1|1].add*=t[p].mul;
t[p<<1|1].add%=m;
t[p<<1|1].add+=t[p].add;
t[p<<1|1].add%=m;
t[p<<1|1].mul*=t[p].mul;
t[p<<1|1].mul%=m;
t[p<<1|1].sum*=t[p].mul;
t[p<<1|1].sum%=m;
t[p<<1|1].sum+=t[p<<1|1].len%m*t[p].add%m;
t[p<<1|1].sum%=m;
}
t[p].add=0;
t[p].mul=1;
}
void build(long long p,long long l,long long r,long long 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<<1,l,(l+r)>>1,a);
build(p<<1|1,((l+r)>>1)+1,r,a);
pushup(p);
}
void update(long long p,long long l,long long r,long long 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;
}
long long mid=(t[p].l+t[p].r)>>1;
pushdown(p);
if(l<=mid){
update(p<<1,l,r,c);
}
if(r>mid){
update(p<<1|1,l,r,c);
}
pushup(p);
}
void update2(long long p,long long l,long long r,long long 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;
}
long long mid=(t[p].l+t[p].r)>>1;
pushdown(p);
if(l<=mid){
update2(p<<1,l,r,c);
}
if(r>mid){
update2(p<<1|1,l,r,c);
}
pushup(p);
}
void update3(long long p,long long l,long long r){
if(t[p].l>=l&&t[p].r<=r){
if(t[p].l!=t[p].r){
pushdown(p);
}
if(!t[p].b){
t[p].sum2+=t[p].sum;
t[p].sum2%=m;
t[p].sum=0;
t[p].len=0;
}
t[p].b++;
return;
}
long long mid=(t[p].l+t[p].r)>>1;
pushdown(p);
if(l<=mid){
update3(p<<1,l,r);
}
if(r>mid){
update3(p<<1|1,l,r);
}
pushup(p);
}
void update4(long long p,long long l,long long r){
if(t[p].l>=l&&t[p].r<=r){
t[p].b--;
if(!t[p].b){
if(t[p].l==t[p].r){
swap(t[p].sum,t[p].sum2);
t[p].len=1;
}
else{
pushup(p);
}
}
return;
}
long long mid=(t[p].l+t[p].r)>>1;
pushdown(p);
if(l<=mid){
update4(p<<1,l,r);
}
if(r>mid){
update4(p<<1|1,l,r);
}
pushup(p);
}
long long query(long long p,long long l,long long r){
if(t[p].l>=l&&t[p].r<=r){
return (t[p].sum+t[p].sum2)%m;
}
long long mid=(t[p].l+t[p].r)>>1;
pushdown(p);
long long ret=0;
if(l<=mid){
ret+=query(p<<1,l,r);
ret%=m;
}
if(r>mid){
ret+=query(p<<1|1,l,r);
ret%=m;
}
return ret;
}
}k;
vector<pair<long long,long long> >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;
}