#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 202020;
const int MOD = 1000000007;
const int REV2 = (MOD + 1) / 2;
const int REV6 = (MOD + 1) / 6;
inline int get_polynomial_sum(int a0, int a1, int a2, int x)
{
return (((long long)a2 * (2 * x + 1) % MOD * REV6 + (long long)a1 * REV2) % MOD * (x + 1) + a0) % MOD * x % MOD;
}
int n, m, a[MAXN];
class Segment_tree
{
public:
int st, ed;
Segment_tree *l, *r;
int sum;
int a[3];//lazy tags
//a[0]: add 1, 1, 1, 1, ...
//a[1]: add 1, 2, 3, 4, ...
//a[2]: add 1, 4, 9, 16, ...
Segment_tree(int st, int ed): st(st), ed(ed), l(0), r(0), sum(0)
{
a[0] = a[1] = a[2] = 0;
}
Segment_tree(int st, int ed, Segment_tree *l, Segment_tree *r): st(st), ed(ed), l(l), r(r)
{
a[0] = a[1] = a[2] = 0;
update();
}
int len() const
{
return ed - st + 1;
}
void add(int b0, int b1, int b2)
{
a[0] = (a[0] + b0) % MOD;
a[1] = (a[1] + b1) % MOD;
a[2] = (a[2] + b2) % MOD;
sum = (sum + get_polynomial_sum(b0, b1, b2, len())) % MOD;
}
void down()
{
if(!a[0] && !a[1] && !a[2])
return;
l->add(a[0], a[1], a[2]);
int llen = l->len();
r->add((((long long)a[2] * llen + a[1]) % MOD * llen + a[0]) % MOD, ((long long)a[2] * llen * 2 + a[1]) % MOD, a[2]);
a[0] = a[1] = a[2] = 0;
}
void update()
{
sum = (l->sum + r->sum) % MOD;
}
};
Segment_tree *root;
Segment_tree *build(int st, int ed)
{
return st == ed ? new Segment_tree(st, ed) : new Segment_tree(st, ed, build(st, (st + ed) >> 1), build(((st + ed) >> 1) + 1, ed));
}
long long query(Segment_tree *p, int st, int ed)
{
if(p->st >= st && p->ed <= ed)
return p->sum;
p->down();
if(ed <= p->l->ed)
return query(p->l, st, ed);
if(st >= p->r->st)
return query(p->r, st, ed);
return query(p->l, st, ed) + query(p->r, st, ed);
}
void add(Segment_tree *p, int st, int ed, int b0, int b1, int b2)
{
// if(p == root)
// printf("add: [%d, %d] %d + %dx + %dx^2\n", st, ed, b0, b1, b2);
if(p->st >= st && p->ed <= ed)
{
p->add(b0, b1, b2);
return;
}
p->down();
if(ed <= p->l->ed)
add(p->l, st, ed, b0, b1, b2);
else if(st >= p->r->st)
add(p->r, st, ed, b0, b1, b2);
else
{
add(p->l, st, p->l->ed, b0, b1, b2);
int llen = p->l->ed - st + 1;
add(p->r, p->r->st, ed, (((long long)b2 * llen + b1) % MOD * llen + b0) % MOD, ((long long)b2 * llen * 2 + b1) % MOD, b2);
}
p->update();
}
void change(int u, int v, int d)
{
if(u > v)
swap(u, v);
int len = v - u + 1;
v = n - v + 1;
add(root, 1, n, 0, (long long)len * d % MOD, 0);
if(u + 1 <= n)
add(root, u + 1, n, 0, (long long)(MOD - d) * REV2 % MOD, (long long)(MOD - d) * REV2 % MOD);
if(u + len + 1 <= n)
add(root, u + len + 1, n, 0, (long long)d * REV2 % MOD, (long long)d * REV2 % MOD);
if(v + 1 <= n)
add(root, v + 1, n, 0, (long long)(MOD - d) * REV2 % MOD, (long long)(MOD - d) * REV2 % MOD);
if(v + len + 1 <= n)
add(root, v + len + 1, n, 0, (long long)d * REV2 % MOD, (long long)d * REV2 % MOD);
}
int main()
{
// freopen("sum.in", "r", stdin);
// freopen("sum.out", "w", stdout);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
root = build(1, n);
for(int i = 1; i <= n; i++)
if(a[i])
change(i, i, a[i]);
for(int i = 1; i <= m; i++)
{
int tp, u, v, d;
scanf("%d%d%d", &tp, &u, &v);
if(tp == 1)
{
scanf("%d", &d);
change(u, v, d);
}
else
{
printf("%d\n", (int)(query(root, u, v) % MOD));
}
}
return 0;
}