#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int x = 0;
  int f = 1;
  char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}
const int MAXN = 400005;
const int MOD = 1000000007;
int a[MAXN], ls[MAXN], rs[MAXN];
int n, m;
struct Matrix {
  int v[4];
  Matrix() { memset(v, 0, sizeof(v)); }
  friend Matrix operator*(Matrix a, Matrix b) {
    Matrix c;
    c.v[0] = (1LL * a.v[0] * b.v[0] + 1LL * a.v[1] * b.v[2]) % MOD;
    c.v[1] = (1LL * a.v[0] * b.v[1] + 1LL * a.v[1] * b.v[3]) % MOD;
    c.v[2] = (1LL * a.v[2] * b.v[0] + 1LL * a.v[3] * b.v[2]) % MOD;
    c.v[3] = (1LL * a.v[2] * b.v[1] + 1LL * a.v[3] * b.v[3]) % MOD;
    return c;
  }
  friend Matrix operator+(Matrix a, Matrix b) {
    for (int i = 0; i < 4; i++) a.v[i] = (a.v[i] + b.v[i]) % MOD;
    return a;
  }
  friend Matrix operator^(Matrix a, int b) {
    Matrix ans;
    ans.v[0] = ans.v[3] = 1;
    for (int i = b; i; i >>= 1, a = a * a)
      if (i & 1) ans = ans * a;
    return ans;
  }
} t, f, mt[MAXN], tag[MAXN];
void build(int k, int l, int r) {
  int mid = (l + r) >> 1;
  ls[k] = l;
  rs[k] = r;
  tag[k] = f;
  mt[k].v[1] = 1;
  if (l == r) {
    mt[k] = mt[k] * (t ^ a[l]);
    return;
  }
  build(k << 1, l, mid);
  build(k << 1 | 1, mid + 1, r);
  mt[k] = mt[k << 1] + mt[k << 1 | 1];
}
inline void pushdown(int k) {
  if (ls[k] == rs[k]) return;
  tag[k << 1] = tag[k << 1] * tag[k];
  tag[k << 1 | 1] = tag[k << 1 | 1] * tag[k];
  mt[k << 1] = mt[k << 1] * tag[k];
  mt[k << 1 | 1] = mt[k << 1 | 1] * tag[k];
  tag[k] = f;
}
void add(int k, int x, int y, Matrix v) {
  pushdown(k);
  int l = ls[k], r = rs[k], mid = (l + r) >> 1;
  if (x == l && y == r) {
    tag[k] = tag[k] * v;
    mt[k] = mt[k] * v;
    return;
  }
  if (x <= mid) add(k << 1, x, min(y, mid), v);
  if (y > mid) add(k << 1 | 1, max(x, mid + 1), y, v);
  mt[k] = mt[k << 1] + mt[k << 1 | 1];
}
int query(int k, int x, int y) {
  pushdown(k);
  int l = ls[k], r = rs[k], mid = (l + r) >> 1, ans = 0;
  if (x == l && y == r) return mt[k].v[0];
  if (x <= mid) ans += query(k << 1, x, min(y, mid));
  if (y > mid) ans += query(k << 1 | 1, max(x, mid + 1), y);
  return ans % MOD;
}
int main(int argc, char const *argv[]) {
  n = read();
  m = read();
  t.v[1] = t.v[2] = t.v[3] = 1;
  f.v[0] = f.v[3] = 1;
  for (int i = 1; i <= n; i++) a[i] = read();
  build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    int opt = read(), l = read(), r = read();
    if (opt == 1) add(1, l, r, t ^ read());
    if (opt == 2) printf("%d\n", query(1, l, r));
  }
  return 0;
}
