#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;
struct tree {
  int l, r;
  int tl, tr, parent;
  long long sum, nextsum, occupy;
} trees[232222];
long long a[2][2], b[2][2];
int s[111111];
int ids = 0;
long long pre = -1;
void make_matrix(long long tm) {
  if (tm <= 1) {
    a[0][0] = 0;
    a[0][1] = a[1][0] = a[1][1] = 1;
    return;
  }
  make_matrix(tm / 2);
  for (int i = 0; i < 2; ++i)
    for (int j = 0; j < 2; ++j) b[i][j] = a[i][j];
  for (int i = 0; i < 2; ++i)
    for (int j = 0; j < 2; ++j)
      a[i][j] = (b[i][0] * b[0][j] + b[i][1] * b[1][j]) % MOD;
  if (tm % 2) {
    for (int i = 0; i < 2; ++i)
      for (int j = 0; j < 2; ++j) b[i][j] = a[i][j];
    a[0][0] = b[0][1];
    a[0][1] = (b[0][0] + b[0][1]) % MOD;
    a[1][0] = b[1][1];
    a[1][1] = (b[1][0] + b[1][1]) % MOD;
  }
}
void cal(long long tm, long long &sum, long long &nextsum) {
  if (pre != tm) {
    make_matrix(tm);
  }
  pre = tm;
  long long sum_temp = (sum * a[0][0] + nextsum * a[1][0]) % MOD;
  nextsum = (sum * a[0][1] + nextsum * a[1][1]) % MOD;
  sum = sum_temp;
}
int make_tree(int a[], int n, int start) {
  int id = ids;
  ++ids;
  trees[id].l = start;
  trees[id].r = start + n - 1;
  trees[id].parent = 0;
  if (n == 1) {
    trees[id].sum = 0;
    trees[id].nextsum = 1;
    cal(a[0], trees[id].sum, trees[id].nextsum);
    trees[id].occupy = 0;
    trees[id].tl = 0;
    trees[id].tr = 0;
  } else {
    int lid = make_tree(a, n / 2, start);
    int rid = make_tree(a + n / 2, n - n / 2, start + n / 2);
    trees[id].tl = lid;
    trees[id].tr = rid;
    trees[id].sum = (trees[lid].sum + trees[rid].sum) % MOD;
    trees[id].nextsum = (trees[lid].nextsum + trees[rid].nextsum) % MOD;
    trees[lid].parent = id;
    trees[rid].parent = id;
  }
  return id;
}
void add_value(tree &node, long long value) {
  long long psum = node.sum;
  long long pnsum = node.nextsum;
  cal(value, node.sum, node.nextsum);
  node.occupy = node.occupy + value;
  psum = node.sum - psum;
  pnsum = node.nextsum - pnsum;
  int p = node.parent;
  while (p != 0) {
    trees[p].nextsum = (trees[p].nextsum + pnsum + MOD) % MOD;
    trees[p].sum = (trees[p].sum + psum + MOD) % MOD;
    p = trees[p].parent;
  }
}
void refresh_from_above(int l, int r, tree &node) {
  if (node.l > r || node.r < l) return;
  if (l <= node.l && node.r <= r) return;
  if (node.occupy > 0) {
    trees[node.tl].occupy = trees[node.tl].occupy + node.occupy;
    cal(node.occupy, trees[node.tl].sum, trees[node.tl].nextsum);
    trees[node.tr].occupy = trees[node.tr].occupy + node.occupy;
    cal(node.occupy, trees[node.tr].sum, trees[node.tr].nextsum);
    node.occupy = 0;
  }
  refresh_from_above(l, r, trees[node.tl]);
  refresh_from_above(l, r, trees[node.tr]);
}
void add_area(int l, int r, tree &node, long long value) {
  if (node.l > r || node.r < l) return;
  if (l <= node.l && r >= node.r) {
    add_value(node, value);
    return;
  }
  add_area(l, r, trees[node.tl], value);
  add_area(l, r, trees[node.tr], value);
}
long long cal_area(int l, int r, tree &node) {
  if (node.l > r || node.r < l) return 0;
  if (l <= node.l && r >= node.r) {
    return node.sum;
  }
  return (cal_area(l, r, trees[node.tl]) + cal_area(l, r, trees[node.tr])) %
         MOD;
}
int main() {
  int n, m, p, l, r, x;
  ids = 1;
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; ++i) scanf("%d", &s[i]);
  int id = make_tree(s, n, 1);
  for (int i = 0; i < m; ++i) {
    scanf("%d", &p);
    if (p == 1) {
      scanf("%d%d%d", &l, &r, &x);
      refresh_from_above(l, r, trees[id]);
      add_area(l, r, trees[id], x);
    } else {
      scanf("%d%d", &l, &r);
      refresh_from_above(l, r, trees[id]);
      printf("%I64d\n", cal_area(l, r, trees[id]));
    }
  }
}
