#include<bits/stdc++.h>
using namespace std;
int read()
{
int s = 0,w = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-') w = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
s = (s << 1) + (s << 3) + (ch ^ 48);
ch = getchar();
}
return s * w;
}
void write(int a)
{
if(a < 0) putchar('-'),a = -a;
if(a > 9) write(a / 10);
putchar(a % 10 + '0');
}
const int N = 3e5 + 10,M = 6e7 + 10,p = 1e9 + 7;
int n,m,c,u,v,w,x,y,z;
int tmp[N],cnt;
int opt,l,r,l1,r1,l2,r2,k,ans;
struct FHQ
{
int tot,root;
int val[M],dat[M],size[M],son[M][2];
int sum[M],cov[M],ad[M];
bool lazy[M];
int New(int x)
{
val[++tot] = sum[tot] = x;
size[tot] = 1,dat[tot] = rand();
son[tot][0] = son[tot][1] = 0;
lazy[tot] = ad[tot] = 0;
cov[tot] = -1;
return tot;
}
int clone(int p)
{
int q = ++tot;
val[q] = val[p],dat[q] = dat[p];
size[q] = size[p],sum[q] = sum[p];
son[q][0] = son[p][0];
son[q][1] = son[p][1];
cov[q] = cov[p],ad[q] = ad[p];
lazy[q] = lazy[p];
return q;
}
void cover(int p,int c)
{
val[p] = c,cov[p] = c % p,ad[p] = 0;
sum[p] = (long long)size[p] * (long long)c % p;
}
void add(int p,int c)
{
val[p] = ((long long)val[p] + c) % p;
sum[p] = ((long long)sum[p] + ((long long)size[p] * (long long)c) % p) % p;
ad[p] = (ad[p] + c) % p;
}
void pushup(int p)
{
size[p] = size[son[p][0]] + size[son[p][1]] + 1;
sum[p] = ((long long)sum[son[p][0]] + (long long)sum[son[p][1]] + (long long)val[p]) % p;
}
void pushdown(int p)
{
if(cov[p] == -1 && lazy[p] == 0 && ad[p] == 0) return;
if(son[p][0]) son[p][0] = clone(son[p][0]);
if(son[p][1]) son[p][1] = clone(son[p][1]);
if(lazy[p])
{
if(son[p][0]) lazy[son[p][0]] ^= 1;
if(son[p][1]) lazy[son[p][1]] ^= 1;
swap(son[p][0],son[p][1]);
lazy[p] = 0;
}
if(cov[p] != -1)
{
if(son[p][0]) cover(son[p][0],cov[p]);
if(son[p][1]) cover(son[p][1],cov[p]);
cov[p] = -1;
}
if(ad[p])
{
if(son[p][0]) add(son[p][0],ad[p]);
if(son[p][1]) add(son[p][1],ad[p]);
ad[p] = 0;
}
}
void split(int p,int k,int &x,int &y)
{
if(p == 0) {x = y = 0;return;}pushdown(p);
if(size[son[p][0]] + 1 <= k)
{
x = clone(p);
split(son[p][1],k - size[son[p][0]] - 1,son[x][1],y);
pushup(x);
}
else
{
y = clone(p);
split(son[p][0],k,x,son[y][0]);
pushup(y);
}
}
int merge(int u,int v)
{
if(u == 0 || v == 0) return u | v;
if(dat[u] < dat[v])
{
u = clone(u);
pushdown(u);
son[u][1] = merge(son[u][1],v);
pushup(u);
return u;
}
else
{
v = clone(v);
pushdown(v);
son[v][0] = merge(u,son[v][0]);
pushup(v);
return v;
}
}
int build(int l,int r)
{
if(l > r) return 0;
int mid = (l + r) >> 1;
int k = New(tmp[mid]);
son[k][0] = build(l,mid - 1);
son[k][1] = build(mid + 1,r);
pushup(k);return k;
}
void dfs(int p)
{
pushdown(p);
if(son[p][0]) dfs(son[p][0]);
tmp[++cnt] = val[p];
if(son[p][1]) dfs(son[p][1]);
}
int Query_sum(int l,int r)
{
int x,y,z;
split(root,r,x,z);
split(x,l - 1,x,y);
int t = sum[y];
root = merge(merge(x,y),z);
return t;
}
void Cover(int l,int r,int k)
{
int x,y,z;
split(root,r,x,z);
split(x,l - 1,x,y);
y = clone(y);
cover(y,k);
root = merge(merge(x,y),z);
}
void Add(int l,int r,int k)
{
int x,y,z;
split(root,r,x,z);
split(x,l - 1,x,y);
y = clone(y);
add(y,k);
root = merge(merge(x,y),z);
}
void Copy(int l1,int r1,int l2,int r2)
{
int x,y,z,v,w;
bool flag = 0;
if(l1 > l2) swap(l1,l2),swap(r1,r2),flag = 1;
split(root,r2,x,v);
split(x,l2 - 1,x,w);
split(x,r1,x,z);
split(x,l1 - 1,x,y);
if(flag) y = clone(w);
else w = clone(y);
root = merge(merge(merge(merge(x,y),z),w),v);
}
void Swap(int l1,int r1,int l2,int r2)
{
int x,y,z,v,w;
if(l1 > l2) swap(l1,l2),swap(r1,r2);
split(root,r2,x,v);
split(x,l2 - 1,x,w);
split(x,r1,x,z);
split(x,l1 - 1,x,y);
y = clone(y),w = clone(w),swap(y,w);
root = merge(merge(merge(merge(x,y),z),w),v);
}
void Reverse(int l,int r)
{
int x,y,z;
split(root,r,x,z);
split(x,l - 1,x,y);
y = clone(y);
lazy[y] ^= 1;
root = merge(merge(x,y),z);
}
void rebuild()
{
cnt = 0,dfs(root);
root = tot = 0;
root = build(1,n);
}
void print(int p)
{
cnt = 0,dfs(root);
for(int i = 1;i <= n;i++) cout << tmp[i] << " ";
cout << endl;
}
}tree;
int main()
{
n = read(),m = read();
for(int i = 1;i <= n;i++) tmp[i] = read();
tree.root = tree.build(1,n);
cnt = 0,tree.dfs(tree.root);
while(m--)
{
opt = read();
if(opt == 1)
{
l = read(),r = read();
l ^= ans,r ^= ans;
ans = tree.Query_sum(l,r);
write(ans),putchar('\n');
}
if(opt == 2)
{
l = read(),r = read(),k = read();
l ^= ans,r ^= ans,k ^= ans;
tree.Cover(l,r,k);
}
if(opt == 3)
{
l = read(),r = read(),k = read();
l ^= ans,r ^= ans,k ^= ans;
tree.Add(l,r,k);
}
if(opt == 4)
{
l1 = read(),r1 = read(),l2 = read(),r2 = read();
l1 ^= ans,l2 ^= ans,r1 ^= ans,r2 ^= ans;
tree.Copy(l1,r1,l2,r2);
}
if(opt == 5)
{
l1 = read(),r1 = read(),l2 = read(),r2 = read();
l1 ^= ans,l2 ^= ans,r1 ^= ans,r2 ^= ans;
tree.Swap(l1,r1,l2,r2);
}
if(opt == 6)
{
l = read(),r = read();
l ^= ans,r ^= ans;
tree.Reverse(l,r);
}
if(tree.tot + 400000 >= M) tree.rebuild();
}
cnt = 0,tree.dfs(tree.root);
for(int i = 1;i <= n;i++) cout << tmp[i] << " ";
return 0;
}