#include <bits/stdc++.h>
using namespace std;
int T, n, m, k, num, a[200005];
struct Matrix {
  long long val[3][3];
  int x, y;
  void init() {
    memset(val, 0, sizeof(val));
    val[1][1] = val[2][2] = 1;
  }
  Matrix(int w, int v) {
    x = w, y = v;
    memset(val, 0, sizeof(val));
  }
  Matrix() { memset(val, 0, sizeof(val)); }
  friend Matrix operator*(const Matrix a, const Matrix b) {
    Matrix c;
    c.x = a.x, c.y = b.y;
    for (int i = 1; i <= a.x; i++)
      for (int j = 1; j <= b.y; j++)
        for (int k = 1; k <= b.x; k++)
          c.val[i][j] = (c.val[i][j] + a.val[i][k] * b.val[k][j]) % 1000000007;
    return c;
  }
  friend Matrix operator+(const Matrix a, const Matrix b) {
    Matrix c;
    c.x = a.x, c.y = b.y;
    for (int i = 1; i <= a.x; i++)
      for (int j = 1; j <= b.y; j++)
        c.val[i][j] = (a.val[i][j] + b.val[i][j]) % 1000000007;
    return c;
  }
};
Matrix ksm(Matrix a, long long b) {
  Matrix c = a;
  b--;
  while (b) {
    if (b & 1) c = c * a;
    a = a * a;
    b >>= 1;
  }
  return c;
}
struct Segtree {
  int l, r;
  bool down;
  Matrix dow = Matrix(2, 2);
  Matrix sta = Matrix(2, 2);
} tree[4 * 200005];
void push_up(int i) { tree[i].sta = tree[2 * i].sta + tree[2 * i + 1].sta; }
void build(int i, int l, int r) {
  tree[i].l = l;
  tree[i].r = r;
  tree[i].down = 0;
  tree[i].dow.init();
  if (l == r) {
    Matrix temp = Matrix(2, 2);
    temp.val[1][1] = temp.val[1][2] = temp.val[2][1] = 1;
    if (a[l] != 1)
      tree[i].sta = ksm(temp, a[l] - 1);
    else
      tree[i].sta.init();
    return;
  }
  int mid = (l + r) >> 1;
  build(2 * i, l, mid);
  build(2 * i + 1, mid + 1, r);
  push_up(i);
}
void push_down(int i) {
  if (!tree[i].down) return;
  tree[2 * i].down = tree[2 * i + 1].down = true;
  tree[2 * i].dow = tree[2 * i].dow * tree[i].dow;
  tree[2 * i + 1].dow = tree[2 * i + 1].dow * tree[i].dow;
  tree[2 * i].sta = tree[2 * i].sta * tree[i].dow;
  tree[2 * i + 1].sta = tree[2 * i + 1].sta * tree[i].dow;
  tree[i].down = false;
  tree[i].dow.init();
}
void deal_add(int i, int x, int y, Matrix val) {
  int l = tree[i].l, r = tree[i].r;
  if (l == x && r == y) {
    tree[i].sta = tree[i].sta * val;
    tree[i].dow = tree[i].dow * val;
    tree[i].down = true;
    return;
  }
  push_down(i);
  int mid = (l + r) / 2;
  if (y <= mid)
    deal_add(2 * i, x, y, val);
  else if (x <= mid) {
    deal_add(2 * i, x, mid, val);
    deal_add(2 * i + 1, mid + 1, y, val);
  } else
    deal_add(2 * i + 1, x, y, val);
  push_up(i);
}
long long Find(int i, int x, int y) {
  int l = tree[i].l, r = tree[i].r;
  if (l == x && r == y) return tree[i].sta.val[1][1];
  push_down(i);
  int mid = (l + r) / 2;
  if (y <= mid)
    return Find(2 * i, x, y);
  else if (x <= mid)
    return (Find(2 * i, x, mid) + Find(2 * i + 1, mid + 1, y)) % 1000000007;
  else
    return Find(2 * i + 1, x, y);
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    scanf("%d", &k);
    if (k == 1) {
      int l, r, x;
      scanf("%d%d%d", &l, &r, &x);
      Matrix temp = Matrix(2, 2);
      temp.val[1][1] = temp.val[1][2] = temp.val[2][1] = 1;
      temp = ksm(temp, x);
      deal_add(1, l, r, temp);
    } else {
      int l, r;
      scanf("%d%d", &l, &r);
      printf("%I64d\n", Find(1, l, r));
    }
  }
}
