#include <bits/stdc++.h>
using namespace std;
#define ios_close ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
#define yes puts("Yes")
#define no puts("No")
#define lowbit(x) (x) & (-x)
#define inf 0x3f3f3f3f
#define endl "\n"
#define PII pair<int, int>
typedef long long LL;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;
int n, m;
LL a[N];
struct MatrixLazy
{
LL M[4][4];
MatrixLazy()
{
memset(M, 0, sizeof M);
}
void Mul(int d)
{
M[1][1] = 1; M[1][2] = 0; M[1][3] = d % MOD;
M[2][1] = 2 * d % MOD; M[2][2] = 1; M[2][3] = d % MOD * d % MOD;
M[3][1] = 0; M[3][2] = 0; M[3][3] = 1;
}
void Unit()
{
M[1][1] = 1; M[1][2] = 0; M[1][3] = 0;
M[2][1] = 0; M[2][2] = 1; M[2][3] = 0;
M[3][1] = 0; M[3][2] = 0; M[3][3] = 1;
}
friend MatrixLazy operator * (const MatrixLazy& a, const MatrixLazy& b)
{
MatrixLazy c;
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
for (int k = 1; k <= 3; k++)
(c.M[i][j] += (a.M[i][k] % MOD * b.M[k][j] % MOD) % MOD) %= MOD;
return c;
}
};
struct MatrixValu
{
LL M[4][2];
MatrixValu()
{
memset(M, 0, sizeof M);
}
friend MatrixValu operator + (const MatrixValu& a, const MatrixValu& b)
{
MatrixValu c;
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 1; j++)
c.M[i][j] = (a.M[i][j] % MOD + b.M[i][j] % MOD) % MOD;
return c;
}
friend MatrixValu operator * (const MatrixLazy& a, const MatrixValu& b)
{
MatrixValu c;
for (int i = 1; i <= 3; i++)
{
for (int j = 1; j <= 1; j++)
{
for (int k = 1; k <= 3; k++)
{
(c.M[i][j] += (a.M[i][k] % MOD * b.M[k][j] % MOD) % MOD) %= MOD;
}
}
}
return c;
}
};
struct Tree
{
int l, r;
MatrixValu valu;
MatrixLazy lazy;
void Maintain(MatrixLazy _lazy)
{
valu = _lazy * valu;
lazy = _lazy * lazy;
}
} tree[N << 2];
int ls(int p) { return p << 1; }
int rs(int p) { return p << 1 | 1; }
void PushUp(int p)
{
tree[p].valu = tree[ls(p)].valu + tree[rs(p)].valu;
}
void PushDown(int p)
{
tree[ls(p)].Maintain(tree[p].lazy);
tree[rs(p)].Maintain(tree[p].lazy);
tree[p].lazy.Unit();
}
void Build(int p, int l, int r)
{
tree[p].l = l; tree[p].r = r;
tree[p].lazy.Unit();
if (tree[p].l == tree[p].r)
{
tree[p].valu.M[1][1] = a[l] % MOD;
tree[p].valu.M[2][1] = a[l] % MOD * a[l] % MOD;
tree[p].valu.M[3][1] = 1;
}
else
{
int mid = (tree[p].l + tree[p].r) >> 1;
Build(ls(p), l, mid + 0);
Build(rs(p), mid + 1, r);
PushUp(p);
}
}
void Change(int p, int x, MatrixLazy& k)
{
if (tree[p].l == tree[p].r)
{
tree[p].Maintain(k);
}
else
{
PushDown(p);
int mid = (tree[p].l + tree[p].r) >> 1;
if (x <= mid)Change(ls(p), x, k);
if (x > mid) Change(rs(p), x, k);
PushUp(p);
}
}
LL Ask(int p, int l, int r, bool f)
{
if (l <= tree[p].l && tree[p].r <= r)
{
return f ? tree[p].valu.M[1][1] % MOD : tree[p].valu.M[2][1] % MOD;
}
else
{
PushDown(p);
LL res = 0;
int mid = (tree[p].l + tree[p].r) >> 1;
if (l <= mid)(res += Ask(ls(p), l, r, f) % MOD) %= MOD;
if (r > mid) (res += Ask(rs(p), l, r, f) % MOD) %= MOD;
return res % MOD;
}
}
LL qpow(int a, int b, int p)
{
if (!b) return 1;
if (b % 2 == 0)
{
LL t = qpow(a, b / 2, p) % p;
return t % p * t % p;
}
LL t = qpow(a, b - 1, p) % p;
return t % p * a % p;
}
void Solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i]; a[i] %= MOD;
}
Build(1, 1, n);
while (m--)
{
int op, x, y;
cin >> op >> x >> y;
if (op == 1)
{
MatrixLazy k; k.Mul(y);
Change(1, x, k);
}
else
{
LL inv = qpow(y - x + 1, MOD - 2, MOD) % MOD;
LL res1 = Ask(1, x, y, 0) % MOD;
LL res2 = Ask(1, x, y, 1) % MOD;
LL ave = inv % MOD * res2 % MOD;
LL ans = ((inv % MOD * res1 % MOD) % MOD - (ave % MOD * ave % MOD) % MOD + MOD) % MOD;
cout << (ans % MOD + MOD) % MOD << endl;
}
}
return;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("IN.txt", "r+", stdin);
#endif
ios_close;
int _ = 1;
while (_--)
Solve();
return 0;
}