#include <bits/stdc++.h>
using namespace std;
inline void fastRead(int *a) {
  register char c = 0;
  while (c < 33) c = getchar();
  *a = 0;
  while (c > 33) {
    *a = *a * 10 + c - '0';
    c = getchar();
  }
}
inline void fastWrite(int a) {
  char snum[20];
  int i = 0;
  do {
    snum[i++] = a % 10 + 48;
    a = a / 10;
  } while (a != 0);
  i = i - 1;
  while (i >= 0) putchar(snum[i--]);
  putchar('\n');
}
struct matrix {
  int mat[2][2];
};
matrix base;
matrix iden;
matrix setvalue(int a, int b, int c, int d) {
  matrix r;
  r.mat[0][0] = a;
  r.mat[0][1] = b;
  r.mat[1][0] = c;
  r.mat[1][1] = d;
  return r;
}
void print(matrix a) {
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) cout << a.mat[i][j] << " ";
    cout << '\n';
  }
}
matrix multiply(matrix a, matrix b) {
  matrix r;
  for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++) {
      long long int sum = 0;
      for (int k = 0; k < 2; k++) {
        sum += (long long int)a.mat[i][k] * (long long int)b.mat[k][j];
        if (sum > LLONG_MAX / 3) sum %= 1000000007;
      }
      if (sum > 1000000007) sum %= 1000000007;
      r.mat[i][j] = sum;
    }
  return r;
}
matrix add(matrix &a, matrix &b) {
  matrix r;
  for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++) {
      r.mat[i][j] = a.mat[i][j] + b.mat[i][j];
      if (r.mat[i][j] > 1000000007) r.mat[i][j] %= 1000000007;
    }
  return r;
}
matrix power(matrix a, long long int p) {
  if (!p) return iden;
  if (p == 1) return a;
  if (p % 2 == 1) return multiply(a, power(a, p - 1));
  matrix r = power(a, p / 2);
  r = multiply(r, r);
  return r;
}
matrix nfib(long long int n) { return power(base, n - 1); }
vector<int> v;
matrix tree[4 * 100005];
matrix lazy[4 * 100005];
bool lazyflag[4 * 100005];
void build(int n, int st, int en) {
  if (st == en) {
    tree[n] = nfib(v[st]);
    return;
  }
  int mid = (st + en) / 2, lc = 2 * n, rc = lc + 1;
  build(lc, st, mid);
  build(rc, mid + 1, en);
  tree[n] = add(tree[lc], tree[rc]);
}
void process(int n, int st, int en, matrix val) {
  tree[n] = multiply(tree[n], val);
  lazyflag[n] = 0;
  int lc = 2 * n, rc = lc + 1;
  if (st != en) {
    if (!lazyflag[lc])
      lazy[lc] = val;
    else
      lazy[lc] = multiply(lazy[lc], val);
    if (!lazyflag[rc])
      lazy[rc] = val;
    else
      lazy[rc] = multiply(lazy[rc], val);
    lazyflag[lc] = 1;
    lazyflag[rc] = 1;
  }
}
void update(int n, int st, int en, int l, int r, long long int val) {
  if (lazyflag[n]) process(n, st, en, lazy[n]);
  if (en < l || r < st) return;
  if (l <= st && en <= r) {
    process(n, st, en, power(base, val));
    return;
  }
  int mid = (st + en) / 2, lc = 2 * n, rc = lc + 1;
  update(lc, st, mid, l, r, val);
  update(rc, mid + 1, en, l, r, val);
  tree[n] = add(tree[lc], tree[rc]);
}
int query(int n, int st, int en, int l, int r) {
  if (lazyflag[n]) process(n, st, en, lazy[n]);
  if (en < l || r < st) return 0;
  if (l <= st && en <= r) return tree[n].mat[0][0];
  int mid = (st + en) / 2, lc = 2 * n, rc = lc + 1;
  int q1 = query(lc, st, mid, l, r);
  int q2 = query(rc, mid + 1, en, l, r);
  int ret = q1 + q2;
  if (ret > 1000000007) ret %= 1000000007;
  return ret;
}
int main() {
  int n, q, inp, l, r, op;
  base = setvalue(1, 1, 1, 0);
  iden = setvalue(1, 0, 0, 1);
  scanf("%d %d", &n, &q);
  v.push_back(1);
  for (int i = 0; i < n; i++) {
    fastRead(&inp);
    v.push_back(inp);
  }
  build(1, 1, n);
  for (int j = 0; j < q; j++) {
    fastRead(&op);
    fastRead(&l);
    fastRead(&r);
    if (op == 1) {
      fastRead(&inp);
      update(1, 1, n, l, r, inp);
    } else
      fastWrite(query(1, 1, n, l, r));
  }
  return 0;
}
