#include <bits/stdc++.h>
using namespace std;
const double E = 1e-9, pi = 2 * acos(0);
const long double PI = 3.1415926535897932384626433832795029L;
const int MOD = 1000000007;
struct Matrix {
  int a00, a01, a10, a11;
  Matrix(bool id) {
    a01 = a10 = 0;
    a00 = a11 = id;
  }
  bool operator==(const Matrix &other) {
    return a00 == other.a00 and a01 == other.a01 and a10 == other.a10 and
           a11 == other.a11;
  }
  Matrix operator+(const Matrix &b) {
    const Matrix &a = *this;
    Matrix ret(false);
    ret.a00 = (a.a00 + b.a00) % MOD;
    ret.a01 = (a.a01 + b.a01) % MOD;
    ret.a10 = (a.a10 + b.a10) % MOD;
    ret.a11 = (a.a11 + b.a11) % MOD;
    return ret;
  }
  Matrix operator*(const Matrix &b) {
    const Matrix &a = *this;
    Matrix ret(false);
    ret.a00 = ((long long)a.a00 * b.a00 + (long long)a.a01 * b.a10) % MOD;
    ret.a01 = ((long long)a.a00 * b.a01 + (long long)a.a01 * b.a11) % MOD;
    ret.a10 = ((long long)a.a10 * b.a00 + (long long)a.a11 * b.a10) % MOD;
    ret.a11 = ((long long)a.a10 * b.a01 + (long long)a.a11 * b.a11) % MOD;
    return ret;
  }
  Matrix pow(int x) {
    Matrix a = *this, ret(true);
    for (; x; x >>= 1) {
      if (x & 1) ret = ret * a;
      a = a * a;
    }
    return ret;
  }
};
vector<Matrix> seg, lazy;
vector<int> vet;
Matrix base(false);
void build(int node, int left, int right) {
  if (left == right)
    seg[node] = base.pow(vet[left]);
  else {
    int mid = (left + right) / 2;
    build(2 * node + 1, left, mid);
    build(2 * node + 2, mid + 1, right);
    seg[node] = seg[2 * node + 1] + seg[2 * node + 2];
  }
}
void refresh(int node) {
  if (lazy[node] == Matrix(true)) return;
  seg[2 * node + 1] = seg[2 * node + 1] * lazy[node];
  seg[2 * node + 2] = seg[2 * node + 2] * lazy[node];
  lazy[2 * node + 1] = lazy[2 * node + 1] * lazy[node];
  lazy[2 * node + 2] = lazy[2 * node + 2] * lazy[node];
  lazy[node] = Matrix(true);
}
void update(int node, int left, int right, int from, int to, Matrix &val) {
  if (left > to or right < from) return;
  if (left >= from and right <= to) {
    lazy[node] = lazy[node] * val;
    seg[node] = seg[node] * val;
    return;
  }
  refresh(node);
  int mid = (left + right) / 2;
  update(2 * node + 1, left, mid, from, to, val);
  update(2 * node + 2, mid + 1, right, from, to, val);
  seg[node] = seg[2 * node + 1] + seg[2 * node + 2];
}
Matrix query(int node, int left, int right, int from, int to) {
  if (left > to or right < from) return Matrix(false);
  if (left >= from and right <= to) return seg[node];
  refresh(node);
  int mid = (left + right) / 2;
  return query(2 * node + 1, left, mid, from, to) +
         query(2 * node + 2, mid + 1, right, from, to);
}
bool solve(int testNumber) {
  int n, m;
  if (scanf("%d %d", &n, &m) == EOF) return false;
  seg.assign(4 * n, Matrix(false));
  lazy.assign(4 * n, Matrix(true));
  vet.resize(n);
  for (int i = 0; i < n; i++) scanf("%d", &vet[i]);
  build(0, 0, n - 1);
  for (int i = 0; i < m; i++) {
    int tp, l, r;
    scanf("%d %d %d", &tp, &l, &r);
    l--, r--;
    if (tp == 1) {
      int x;
      scanf("%d", &x);
      Matrix aux = base.pow(x);
      update(0, 0, n - 1, l, r, aux);
    } else {
      Matrix ans = query(0, 0, n - 1, l, r);
      printf("%d\n", ans.a01);
    }
  }
  fflush(stdout);
  return true;
}
void init() {
  base.a00 = base.a01 = base.a10 = 1;
  base.a11 = 0;
}
int main() {
  init();
  for (int i = 1; solve(i); i++)
    ;
  return 0;
}
