#include <bits/stdc++.h>
using namespace std;
const int MOD = int(1e9) + 7;
long long pom[2][2] = {{0, 1}, {1, 1}};
void mulMat(long long *A, long long *B, int n) {
  long long res[2][2] = {{0}};
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      for (int k = 0; k < n; k++) {
        res[i][j] += (*(A + i * n + k)) * (*(B + k * n + j));
        if (res[i][j] >= MOD) res[i][j] %= MOD;
      }
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++) *(A + i * n + j) = res[i][j];
}
void fastExp(long long pot, long long *T) {
  while (pot) {
    if (pot & 1) {
      mulMat(T, pom[0], 2);
    }
    mulMat(pom[0], pom[0], 2);
    pot >>= 1;
  }
  pom[0][0] = 0;
  pom[0][1] = 1;
  pom[1][0] = 1;
  pom[1][1] = 1;
}
struct Node {
  long long mat[2][2];
  Node() {
    mat[0][0] = 1;
    mat[0][1] = 0;
    mat[1][0] = 0;
    mat[1][1] = 1;
  }
  Node(int pot) {
    mat[0][0] = 1;
    mat[0][1] = 0;
    mat[1][0] = 0;
    mat[1][1] = 1;
    fastExp(pot, mat[0]);
  }
};
void zbrojiMat(long long *resMat, long long *op1, long long *op2) {
  for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++) {
      *(resMat + i * 2 + j) = (*(op1 + i * 2 + j) + *(op2 + i * 2 + j));
      if (*(resMat + i * 2 + j) >= MOD) *(resMat + i * 2 + j) -= MOD;
    }
}
int n, m;
struct Node zeroe;
struct segTree {
  struct Node arr[1 << 18];
  struct Node lazy[1 << 18];
  int offset;
  struct Node neutralElem;
  void normalInit(int n) {
    for (offset = 1; offset < n; offset *= 2)
      ;
    for (int i = 0; i < 2 * offset; i++) {
      arr[i] = zeroe;
      lazy[i] = neutralElem;
    }
  }
  struct Node mergeValues(struct Node l, struct Node r) {
    struct Node n;
    zbrojiMat(n.mat[0], l.mat[0], r.mat[0]);
    return n;
  }
  segTree(int n) { normalInit(n); }
  segTree(int n, int *data) {
    normalInit(n);
    for (int i = offset; i < offset + n; i++)
      arr[i] = Node(*(data + i - offset));
    for (int i = offset - 1; i >= 1; i--)
      arr[i] = mergeValues(arr[i * 2], arr[i * 2 + 1]);
  }
  void updateRange(int lo, int hi, long long *x) {
    update(1, 0, offset, lo, hi + 1, x);
  }
  struct Node query(int lo, int hi) {
    return q(1, 0, offset, lo, hi + 1);
  }

 private:
  void prop(int node) {
    mulMat(arr[node * 2].mat[0], lazy[node].mat[0], 2);
    mulMat(arr[node * 2 + 1].mat[0], lazy[node].mat[0], 2);
    mulMat(lazy[node * 2].mat[0], lazy[node].mat[0], 2);
    mulMat(lazy[node * 2 + 1].mat[0], lazy[node].mat[0], 2);
    lazy[node] = neutralElem;
  }
  void update(int node, int lo, int hi, int qlo, int qhi, long long *T) {
    if (lo >= qhi or hi <= qlo) return;
    if (lo >= qlo && hi <= qhi) {
      mulMat(arr[node].mat[0], T, 2);
      mulMat(lazy[node].mat[0], T, 2);
      return;
    }
    prop(node);
    int mid = (lo + hi) / 2;
    if (node < offset) {
      update(node * 2, lo, mid, qlo, qhi, T);
      update(node * 2 + 1, mid, hi, qlo, qhi, T);
      arr[node] = mergeValues(arr[node * 2], arr[node * 2 + 1]);
    }
  }
  struct Node q(int node, int lo, int hi, int qlo, int qhi) {
    if (lo >= qhi || hi <= qlo) return zeroe;
    if (lo >= qlo && hi <= qhi) return arr[node];
    prop(node);
    int mid = (lo + hi) / 2;
    return mergeValues(q(node * 2, lo, mid, qlo, qhi),
                       q(node * 2 + 1, mid, hi, qlo, qhi));
  }
};
const int MAX = 100005;
int data[MAX];
int main() {
  double start = clock();
  zeroe.mat[0][0] = 0;
  zeroe.mat[1][1] = 0;
  cin >> n >> m;
  for (int i = 0; i < n; i++) scanf("%d", &data[i]);
  segTree *T = new segTree(n, data);
  if (n == 99395)
    ;
  for (int i = 0; i < m; i++) {
    int id;
    scanf("%d", &id);
    int l, r;
    scanf("%d%d", &l, &r);
    l--;
    r--;
    if (id == 1) {
      int x;
      scanf("%d", &x);
      long long Ti[2][2] = {{1, 0}, {0, 1}};
      fastExp(x, Ti[0]);
      T->updateRange(l, r, Ti[0]);
    } else {
      printf("%d\n", T->query(l, r).mat[0][1]);
    }
  }
  return 0;
}
