#include <bits/stdc++.h>
using namespace std;
struct Mat {
  Mat() = default;
  Mat(int64_t _a, int64_t _b, int64_t _c, int64_t _d)
      : a(_a), b(_b), c(_c), d(_d) {}
  int64_t a;
  int64_t b;
  int64_t c;
  int64_t d;
  bool isId() const { return a == 1 && b == 0 && c == 0 && d == 1; }
};
const Mat MatFibo(1, 1, 1, 0);
const int64_t MOD = 1000ll * 1000ll * 1000ll + 7ll;
const int MAXN = 1 << 18;
Mat operator*(Mat const& A, Mat const& B) {
  int64_t a = (A.a * B.a) % MOD + (A.b * B.c) % MOD;
  int64_t b = (A.a * B.b) % MOD + (A.b * B.d) % MOD;
  int64_t c = (A.c * B.a) % MOD + (A.d * B.c) % MOD;
  int64_t d = (A.c * B.b) % MOD + (A.d * B.d) % MOD;
  Mat big(a % MOD, b % MOD, c % MOD, d % MOD);
  return big;
}
Mat fastexp(Mat m, int64_t n) {
  Mat ret(1, 0, 0, 1);
  while (n) {
    if (n & 1) ret = ret * m;
    m = m * m;
    n >>= 1;
  }
  return ret;
}
Mat operator+(Mat const& A, Mat const& B) {
  return Mat((A.a + B.a) % MOD, (A.b + B.b) % MOD, (A.c + B.c) % MOD,
             (A.d + B.d) % MOD);
}
struct Node {
  Node() : lazy(1, 0, 0, 1), s(0, 0, 0, 0) {}
  Mat lazy;
  Mat s;
};
inline int left(int i) { return 2 * i; }
inline int right(int i) { return 2 * i + 1; }
struct Tree {
  void init(int n, int64_t* tab) {
    start = 1;
    while (start < n) {
      start <<= 1;
    }
    startover = start + n;
    for (int i = 0; i < n; ++i) {
      tree[i + start].s = fastexp(MatFibo, tab[i] - 1);
    }
    for (int i = start - 1; i >= 1; --i) {
      tree[i].s = tree[right(i)].s + tree[left(i)].s;
    }
  }
  void debug() {
    cout << "==============================\n";
    for (int i = 1; i < startover; ++i) {
      cout << i << " | ";
      cout << tree[i].s.a << ", " << tree[i].s.b << ", ";
      cout << tree[i].s.c << ", " << tree[i].s.c << "}\n";
    }
    cout << "==============================\n\n";
  }
  void push(int node) {
    if (tree[node].lazy.isId()) return;
    tree[node].s = tree[node].s * tree[node].lazy;
    if (node < start) {
      tree[left(node)].lazy = tree[left(node)].lazy * tree[node].lazy;
      tree[right(node)].lazy = tree[right(node)].lazy * tree[node].lazy;
    }
    tree[node].lazy = Mat(1, 0, 0, 1);
  }
  int64_t query(int node, int l, int r, int curl, int curr) {
    push(node);
    if (curl > r || curr < l) return 0;
    if (l <= curl && curr <= r) return tree[node].s.a;
    int mid = (curl + curr) / 2;
    int64_t lv = query(left(node), l, r, curl, mid);
    int64_t lr = query(right(node), l, r, mid + 1, curr);
    return (lv + lr) % MOD;
  }
  int64_t query(int l, int r) { return query(1, l, r, 0, start - 1); }
  void update(int node, int l, int r, int curl, int curr, Mat const& mx) {
    push(node);
    if (curl > r || curr < l) return;
    if (l <= curl && curr <= r) {
      tree[node].lazy = mx;
      push(node);
      return;
    }
    int mid = (curl + curr) / 2;
    update(left(node), l, r, curl, mid, mx);
    update(right(node), l, r, mid + 1, curr, mx);
    tree[node].s = tree[left(node)].s + tree[right(node)].s;
  }
  void update(int l, int r, Mat const& mx) {
    update(1, l, r, 0, start - 1, mx);
  }
  int start;
  int startover;
  Node tree[MAXN];
} segtree;
int64_t a[100 * 1000];
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
  }
  segtree.init(n, a);
  for (int i = 0; i < m; ++i) {
    int code, l, r;
    cin >> code >> l >> r;
    if (code == 1) {
      int64_t x;
      cin >> x;
      Mat mx = fastexp(MatFibo, x);
      segtree.update(l - 1, r - 1, mx);
    } else {
      int64_t m = segtree.query(l - 1, r - 1);
      cout << m << "\n";
    }
  }
}
