#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
inline void M(int &x) {
  if (x >= MOD) x -= MOD;
}
const int N = 1e5 + 7;
struct Mat {
  int a[2][2];
  Mat() { memset(a, 0, sizeof(a)); }
  Mat(int x) {
    if (x == 0) {
      a[0][0] = a[0][1] = a[1][0] = 1;
      a[1][1] = 0;
    } else {
      a[0][0] = a[1][1] = 1;
      a[1][0] = a[0][1] = 0;
    }
  }
  Mat operator*(const Mat &b) const {
    Mat c;
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++)
        for (int k = 0; k < 2; k++)
          c.a[i][j] = (c.a[i][j] + 1LL * a[i][k] * b.a[k][j]) % MOD;
    return c;
  }
  Mat operator+(const Mat &b) const {
    Mat c;
    for (int i = 0; i < 2; i++)
      for (int j = 0; j < 2; j++) M(c.a[i][j] += a[i][j] + b.a[i][j]);
    return c;
  }
  inline bool empty() {
    return a[0][1] == 0 && a[1][0] == 0 && a[0][0] == 1 && a[1][1] == 1;
  }
  inline void clear() {
    a[0][1] = a[1][0] = 0;
    a[1][1] = a[0][0] = 1;
  }
} la;
const Mat base(0);
Mat qp(Mat a, int b) {
  Mat ans(1);
  while (b) {
    if (b & 1) ans = ans * a;
    a = a * a;
    b >>= 1;
  }
  return ans;
}
struct Seg {
  Mat tree[N << 2], lazy[N << 2];
  inline void pushup(int p) { tree[p] = tree[p << 1] + tree[p << 1 | 1]; }
  inline void tag(int p, int pre) {
    lazy[p] = lazy[p] * lazy[pre];
    tree[p] = tree[p] * lazy[pre];
  }
  inline void pushdown(int p) {
    if (!lazy[p].empty()) {
      tag(p << 1, p);
      tag(p << 1 | 1, p);
      lazy[p].clear();
    }
  }
  void build(int p, int l, int r) {
    lazy[p] = Mat(1);
    if (l == r) {
      int x;
      scanf("%d", &x);
      tree[p] = qp(base, x - 1);
      return;
    }
    int mid = l + r >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    pushup(p);
  }
  void update(int p, int l, int r, int x, int y) {
    if (x <= l && y >= r) {
      tree[p] = tree[p] * la;
      lazy[p] = lazy[p] * la;
      return;
    }
    int mid = l + r >> 1;
    pushdown(p);
    if (x <= mid) update(p << 1, l, mid, x, y);
    if (y > mid) update(p << 1 | 1, mid + 1, r, x, y);
    pushup(p);
  }
  int query(int p, int l, int r, int x, int y) {
    if (x <= l && y >= r) return tree[p].a[0][0];
    int mid = l + r >> 1;
    pushdown(p);
    int ans = 0;
    ;
    if (x <= mid) M(ans += query(p << 1, l, mid, x, y));
    if (y > mid) M(ans += query(p << 1 | 1, mid + 1, r, x, y));
    return ans;
  }
} seg;
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  seg.build(1, 1, n);
  while (m--) {
    int opt, l, r;
    scanf("%d%d%d", &opt, &l, &r);
    if (opt == 1) {
      int x;
      scanf("%d", &x);
      la = qp(base, x);
      seg.update(1, 1, n, l, r);
    } else {
      int res = seg.query(1, 1, n, l, r);
      printf("%d\n", res);
    }
  }
  return 0;
}
