#include <bits/stdc++.h>
#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
using namespace std;
const int mod = 1e9 + 7;
struct matrix {
  int arr[2][2];
};
matrix fib, identity;
inline matrix mult(matrix &a, matrix &b) {
  matrix product;
  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 2; ++j) {
      product.arr[i][j] = 0;
      for (int k = 0; k < 2; ++k) {
        product.arr[i][j] += (1LL * a.arr[i][k] * b.arr[k][j]) % mod;
        product.arr[i][j] %= mod;
      }
    }
  }
  return product;
}
inline matrix add(matrix &x, matrix &y) {
  matrix prod;
  prod.arr[0][0] = (x.arr[0][0] + y.arr[0][0]);
  prod.arr[0][1] = (x.arr[0][1] + y.arr[0][1]);
  prod.arr[1][0] = (x.arr[1][0] + y.arr[1][0]);
  prod.arr[1][1] = (x.arr[1][1] + y.arr[1][1]);
  if (prod.arr[0][0] >= mod) prod.arr[0][0] -= mod;
  if (prod.arr[0][1] >= mod) prod.arr[0][1] -= mod;
  if (prod.arr[1][0] >= mod) prod.arr[1][0] -= mod;
  if (prod.arr[1][1] >= mod) prod.arr[1][1] -= mod;
  return prod;
}
long long fastPow(long long a, long long pw, long long mod) {
  long long res = 1;
  a %= mod;
  while (pw > 0) {
    if (pw & 1) res = (res * a) % mod;
    a = (a * a) % mod;
    pw >>= 1;
  }
  return res;
}
unordered_map<long long, matrix> cache;
inline matrix power(long long b) {
  if (cache.count(b)) return cache[b];
  const long long tempB = b;
  matrix res = identity;
  matrix curr = fib;
  while (b > 0) {
    if (b & 1) res = mult(res, curr);
    curr = mult(curr, curr);
    b >>= 1;
  }
  return cache[tempB] = res;
}
struct SegmentTree {
 private:
  vector<matrix> tree;
  vector<long long> lazy;
  int n, root, size;

 public:
  SegmentTree() {}
  SegmentTree(vector<int> &arr) : n(arr.size()), root(1) {
    int x = (long long)(ceil(log2(n)));
    size = 2 * (int)pow(2, x);
    tree.resize(size);
    lazy.resize(size, 0);
    build(arr, root, 0, n - 1);
  }
  void build(vector<int> &arr, int node, int start, int end) {
    if (start == end)
      tree[node] = power(arr[start]);
    else {
      int mid = (start + end) / 2;
      build(arr, 2 * node, start, mid);
      build(arr, 2 * node + 1, mid + 1, end);
      tree[node] = add(tree[2 * node], tree[2 * node + 1]);
    }
  }
  void pendingUpdate(int node, int start, int end) {
    if (lazy[node]) {
      auto temp = power(lazy[node]);
      tree[node] = mult(tree[node], temp);
      if (start != end) {
        lazy[2 * node] += lazy[node];
        lazy[2 * node + 1] += lazy[node];
      }
      lazy[node] = 0;
    }
  }
  void updateRange(int l, int r, int diff) {
    updateRange(root, 0, n - 1, l, r, diff);
  }
  void updateRange(int node, int start, int end, int l, int r, int diff) {
    pendingUpdate(node, start, end);
    if (start > end || start > r || end < l) return;
    if (start >= l && end <= r) {
      auto temp = power(diff);
      tree[node] = mult(tree[node], temp);
      if (start != end) {
        lazy[2 * node] += (long long)diff;
        lazy[2 * node + 1] += (long long)diff;
      }
      return;
    }
    int mid = (start + end) / 2;
    updateRange(2 * node, start, mid, l, r, diff);
    updateRange(2 * node + 1, mid + 1, end, l, r, diff);
    tree[node] = add(tree[2 * node], tree[2 * node + 1]);
  }
  int query(int l, int r) { return query(root, 0, n - 1, l, r); }
  int query(int node, int start, int end, int l, int r) {
    if (r < start || end < l) return 0;
    pendingUpdate(node, start, end);
    if (l <= start && end <= r) return tree[node].arr[0][0];
    int mid = (start + end) / 2;
    return (query(2 * node, start, mid, l, r) +
            query(2 * node + 1, mid + 1, end, l, r)) %
           mod;
  }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  fib.arr[0][0] = 1;
  fib.arr[0][1] = 1;
  fib.arr[1][0] = 1;
  fib.arr[1][1] = 0;
  identity.arr[0][0] = 1;
  identity.arr[0][1] = 0;
  identity.arr[1][0] = 0;
  identity.arr[1][1] = 1;
  int n, m;
  cin >> n >> m;
  vector<int> arr(n);
  for (int i = 0; i < n; ++i) {
    cin >> arr[i];
    arr[i]--;
  }
  SegmentTree st(arr);
  int type, l, r, diff;
  for (int i = 0; i < m; ++i) {
    cin >> type >> l >> r;
    l--, r--;
    if (type == 1) {
      cin >> diff;
      st.updateRange(l, r, diff);
    } else {
      cout << st.query(l, r) << '\n';
    }
  }
}
