#include <bits/stdc++.h>
#define int long long
using namespace std;
template<int Mod>
struct matrix
{
public:
int n, m;
int z[3][3];
matrix()
{
n = m = 0;
memset(z, 0, sizeof z);
}
void init(int x, int y)
{
n = x, m = y;
for (int i = 1; i <= x; i++)
for (int j = 1; j <= y; j++)
z[i][j] = 0;
}
void init(int x, int y, int a[3][3])
{
n = x, m = y;
for (int i = 1; i <= x; i++)
for (int j = 1; j <= y; j++)
z[i][j] = a[i][j];
}
void O()
{
n = m = 2;
z[0][0] = z[1][1] = z[0][1] = z[1][0] = 0;
}
void I()
{
n = m = 2;
z[0][0] = z[1][1] = 1;
z[0][1] = z[1][0] = 0;
}
bool CICN()
{
return z[0][0] == 1 && z[1][1] == 1 && z[0][1] == 0 && z[1][0] == 0;
}
};
template<int Mod>
istream &operator>>(istream &in, matrix<Mod> &x)
{
in >> x.n >> x.m;
for (int i = 1; i <= x.n; i++)
for (int j = 1; j <= x.m; j++)
in >> x.z[i][j];
return in;
}
template<int Mod>
ostream &operator<<(ostream &out, matrix<Mod> &x)
{
for (int i = 1; i <= x.n; i++, cout << '\n')
for (int j = 1; j <= x.m; j++)
out << x.z[i][j] << ' ';
return out;
}
template<int Mod>
matrix<Mod> operator+(const matrix<Mod> &a, const matrix<Mod> &b)
{
assert(a.n == b.n && a.m == b.m);
matrix<Mod> c;
c.n = a.n, c.m = a.m;
for (int i = 1; i <= c.n; i++)
for (int j = 1; j <= c.m; j++)
c.z[i][j] = a.z[i][j] + b.z[i][j];
return c;
}
template<int Mod>
matrix<Mod> operator*(const matrix<Mod> &a, const matrix<Mod> &b)
{
assert(a.m == b.n);
matrix<Mod> c;
c.n = a.n, c.m = b.m;
for (int i = 1; i <= c.n; i++)
for (int k = 1; k <= a.m; k++)
for (int j = 1; j <= c.m; j++)
(c.z[i][j] += a.z[i][k] * b.z[k][j] % Mod) %= Mod;
return c;
}
template<int Mod>
matrix<Mod> operator^(matrix<Mod> &a, int k)
{
matrix<Mod> b; b.I();
while (k)
{
if (k & 1)
b = b * a;
a = a * a;
k /= 2;
}
return b;
}
const int N = 2e5 + 10;
int a[N];
struct Node
{
int l, r;
matrix<1000000007> sum, tag;
Node ()
{
l = r = 0;
sum.init(0, 0), tag.init(0, 0);
}
void init(int p)
{
l = r = p;
if (a[p] == 1)
sum.z[0][0] = 1;
else
{
sum.z[0][0] = sum.z[0][1] = 1;
sum = sum ^ (a[p] - 2);
}
}
void color(matrix<1000000007> p)
{
sum = sum * p;
tag = tag * p;
}
} z[N << 2];
Node operator+(const Node &lhs, const Node &rhs)
{
Node res;
res.l = lhs.l, res.r = rhs.r;
res.sum = lhs.sum + rhs.sum;
res.tag.I();
return res;
}
void build(int l, int r, int rt)
{
if (l == r)
z[rt].init(l);
else
{
int mid = l + r >> 1;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
}
void push_down(int rt)
{
if (z[rt].tag.CICN())
{
z[rt << 1].color(z[rt].tag);
z[rt << 1 | 1].color(z[rt].tag);
z[rt].tag.I();
}
}
void modify(int l, int r, int rt, int nowl, int nowr, matrix<1000000007> val)
{
if (nowl <= l && r <= nowr)
z[rt].color(val);
else
{
int mid = l + r >> 1;
push_down(rt);
if (nowl <= mid)
modify(l, mid, rt << 1, nowl, nowr, val);
if (mid < nowr)
modify(mid + 1, r, rt << 1 | 1, nowl, nowr, val);
z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
}
int query(int l, int r, int rt, int nowl, int nowr)
{
if (nowl <= l && r <= nowr)
return z[rt].sum.z[0][0];
int mid = l + r >> 1, sum = 0;
push_down(rt);
if (nowl <= mid)
sum = query(l, mid, rt << 1, nowl, nowr);
if (mid < nowr)
sum += query(mid + 1, r, rt << 1 | 1, nowl, nowr);
return sum;
}
signed main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
build(1, n, 1);
while (m--)
{
int o;
cin >> o;
if (o == 1)
{
int l, r, x;
cin >> l >> r >> x;
matrix<1000000007> t; t.I();
modify(1, n, 1, l, r, t ^ x);
}
else
{
int l, r;
cin >> l >> r;
cout << query(1, n, 1, l, r) << '\n';
}
}
return 0;
}


