//加的时候也要一直MOD,否则longlong也爆了!!
//小数据没错的时候,多想想是不是MOD的问题!
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100005;
const int MOD = (1e9)+7;
typedef long long LL;
int n,m;
LL a[N];//存每个动力装置(原子)
struct SegmentTree
{
int l=0,r=0;
LL sumx=0,sumy=0,sumz=0;//都表示这个结点x,y,z的总和
LL addx=0,addy=0,addz=0;//x,y,z对加操作的懒标记
LL mulx=0,muly=0,mulz=0;
#define l(u) tree[u].l
#define r(u) tree[u].r
#define sumx(u) tree[u].sumx
#define sumy(u) tree[u].sumy
#define sumz(u) tree[u].sumz
#define addx(u) tree[u].addx
#define addy(u) tree[u].addy
#define addz(u) tree[u].addz
#define mulx(u) tree[u].mulx
#define muly(u) tree[u].muly
#define mulz(u) tree[u].mulz
}tree[4*N];
void build(int u,int l,int r)//一开始建树,只需要维护左右端点即可
{
l(u)=l,r(u)=r;
if(l==r)
return;
int mid=l+r>>1;
build(u<<1,l,mid);
build((u<<1)+1,mid+1,r);
}
void pushup1(int u)
{
sumx(u)=(sumx(u<<1)+sumx((u<<1)+1))%MOD;
sumy(u)=(sumy(u<<1)+sumy((u<<1)+1))%MOD;
sumz(u)=(sumz(u<<1)+sumz((u<<1)+1))%MOD;
return;
}
void pushdown1(int u)
{
if(!addx(u)&&!addy(u)&&!addz(u))
return;
sumx(u<<1)=(sumx(u<<1)+addx(u)*(r(u<<1)-l(u<<1)+1))%MOD;
sumy(u<<1)=(sumy(u<<1)+addy(u)*(r(u<<1)-l(u<<1)+1))%MOD;
sumz(u<<1)=(sumz(u<<1)+addz(u)*(r(u<<1)-l(u<<1)+1))%MOD;
sumx((u<<1)+1)=(sumx((u<<1)+1)+addx(u)*(r((u<<1)+1)-l((u<<1)+1)+1))%MOD;
sumy((u<<1)+1)=(sumy((u<<1)+1)+addy(u)*(r((u<<1)+1)-l((u<<1)+1)+1))%MOD;
sumz((u<<1)+1)=(sumz((u<<1)+1)+addz(u)*(r((u<<1)+1)-l((u<<1)+1)+1))%MOD;
addx(u)=0;
addy(u)=0;
addz(u)=0;
return;
}
void modify1(int u,int l,int r,int dx,int dy,int dz)
{
if(l<=l(u)&&r>=r(u))
{
sumx(u)=(sumx(u)+(LL)dx*(r(u)-l(u)+1))%MOD;
sumy(u)=(sumy(u)+(LL)dy*(r(u)-l(u)+1))%MOD;
sumz(u)=(sumz(u)+(LL)dz*(r(u)-l(u)+1))%MOD;//改动这个结点的信息
addx(u)=(addx(u)+dx)%MOD;
addy(u)=(addy(u)+dy)%MOD;
addz(u)=(addz(u)+dz)%MOD;//既然不搜下去,懒标记要更新!
return;
}
pushdown1(u);//要去下层,那就要更新懒标记
int mid=l(u)+r(u)>>1;
if(l<=mid)//左孩子有需要更改的部分
modify1(u<<1,l,r,dx,dy,dz);
if(r>mid)
modify1((u<<1)+1,l,r,dx,dy,dz);
pushup1(u);//修改完下层后一定要pushup!!!
}
SegmentTree query(int u,int l,int r)//返回一个res结点,保存了u中l到r区间内的信息总和!
{
if(l<=l(u)&&r>=r(u))
{
return tree[u];
}
//要往下找,那就扩散这个懒标记
pushdown1(u);
struct SegmentTree res;//构造这个答案结点,将u中l到r区间内的信息总和保存在res!!
res.l=l,res.r=r;
int mid=l(u)+r(u)>>1;
if(l<=mid)
{
SegmentTree v=query(u<<1,l,r);
res.sumx=(v.sumx+res.sumx)%MOD;
res.sumy=(v.sumy+res.sumy)%MOD;
res.sumz=(v.sumz+res.sumz)%MOD;
}
if(r>mid)
{
SegmentTree v=query((u<<1)+1,l,r);
res.sumx=(v.sumx+res.sumx)%MOD;
res.sumy=(v.sumy+res.sumy)%MOD;
res.sumz=(v.sumz+res.sumz)%MOD;
}
return res;
}
int main()
{
cin>>n>>m;
build(1,1,n);
while(m--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int l,r,dx,dy,dz;
scanf("%d%d%d%d%d",&l,&r,&dx,&dy,&dz);
modify1(1,l,r,dx,dy,dz);
}
else if(op==4)
{
int l,r;
scanf("%d%d",&l,&r);
SegmentTree res=query(1,l,r);
LL dist=0;
dist=(res.sumx*res.sumx)%MOD;
dist=(dist+res.sumy*res.sumy)%MOD;
dist=(dist+res.sumz*res.sumz)%MOD;
cout<<dist<<endl;
}
}
return 0;
}