#include <bits/stdc++.h>
const int M = 1e9 + 7, N = 100100;
struct matrix {
  int a[2][2];
  void init(int v) {
    if (v == 1)
      this->a[0][0] = this->a[1][1] = 1, this->a[1][0] = this->a[0][1] = 0;
    else if (v == 0)
      this->a[0][0] = this->a[0][1] = this->a[1][0] = this->a[1][1] = 0;
  }
  void cpy(matrix x) {
    for (int i = 0; i <= 1; i++)
      for (int j = 0; j <= 1; j++) this->a[i][j] = x.a[i][j];
  }
  void times(matrix b) {
    matrix c;
    c.init(0);
    for (int i = 0; i <= 1; i++)
      for (int j = 0; j <= 1; j++)
        for (int k = 0; k <= 1; k++)
          c.a[i][j] = (c.a[i][j] +
                       (long long)this->a[i][k] * (long long)b.a[k][j] % M) %
                      M;
    this->cpy(c);
  }
  void pow(int v) {
    matrix b;
    b.init(1);
    while (v) {
      if (v & 1) b.times(*this);
      this->times(*this);
      v >>= 1;
    }
    this->cpy(b);
  }
};
const matrix fb = {{{1, 1}, {1, 0}}};
int n, m, tp, l, r, x;
struct segt {
  int l, r;
  matrix x, tag;
} tr[8 * N];
segt pushup(segt a, segt b) {
  segt c;
  c.l = a.l, c.r = b.r, c.tag.init(1);
  a.x.times(a.tag), b.x.times(b.tag);
  for (int i = 0; i <= 1; i++)
    for (int j = 0; j <= 1; j++) c.x.a[i][j] = (a.x.a[i][j] + b.x.a[i][j]) % M;
  return c;
}
void pushdown(int v) {
  tr[v].x.times(tr[v].tag);
  tr[v << 1].tag.times(tr[v].tag);
  tr[v << 1 | 1].tag.times(tr[v].tag);
  tr[v].tag.init(1);
}
void build(int v, int l, int r) {
  tr[v].l = l, tr[v].r = r, tr[v].tag.init(1);
  if (l == r) {
    int a;
    scanf("%d", &a);
    tr[v].x.cpy(fb), tr[v].x.pow(a), tr[v].tag.init(1);
    return;
  }
  build(v << 1, l, (l + r) >> 1);
  build(v << 1 | 1, ((l + r) >> 1) + 1, r);
  tr[v] = pushup(tr[v << 1], tr[v << 1 | 1]);
}
segt getans(int v, int l, int r) {
  pushdown(v);
  int mid = (tr[v].l + tr[v].r) >> 1;
  if (tr[v].l == l && tr[v].r == r)
    return tr[v];
  else if (r <= mid)
    return getans(v << 1, l, r);
  else if (l > mid)
    return getans(v << 1 | 1, l, r);
  else
    return pushup(getans(v << 1, l, mid), getans(v << 1 | 1, mid + 1, r));
}
void add(int v, int l, int r, matrix c) {
  int mid = (tr[v].l + tr[v].r) >> 1;
  if (tr[v].l == l && tr[v].r == r)
    tr[v].tag.times(c);
  else {
    pushdown(v);
    if (r <= mid)
      add(v << 1, l, r, c);
    else if (l > mid)
      add(v << 1 | 1, l, r, c);
    else
      add(v << 1, l, mid, c), add(v << 1 | 1, mid + 1, r, c);
    tr[v] = pushup(tr[v << 1], tr[v << 1 | 1]);
  }
}
int main(void) {
  scanf("%d%d", &n, &m);
  build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    scanf("%d%d%d", &tp, &l, &r);
    if (tp == 2)
      printf("%d\n", getans(1, l, r).x.a[0][1]);
    else {
      scanf("%d", &x);
      matrix c;
      c.cpy(fb);
      c.pow(x);
      add(1, l, r, c);
    }
  }
  return 0;
}
