#include <bits/stdc++.h>
struct info {
  long long x1, y1, x2, y2;
  info(int x1 = 1, int y1 = 1, int x2 = 1, int y2 = 0)
      : x1(x1), y1(y1), x2(x2), y2(y2) {}
  info operator+(info x) {
    info n;
    n.x1 = (x1 + x.x1) % 1000000007LL;
    n.y1 = (y1 + x.y1) % 1000000007LL;
    n.x2 = (x2 + x.x2) % 1000000007LL;
    n.y2 = (y2 + x.y2) % 1000000007LL;
    return n;
  }
  bool operator!=(info x) {
    if (x1 == x.x1 && y1 == x.y1 && x2 == x.x2 && y2 == x.y2) return false;
    return true;
  }
};
info lazy[131072 * 2 + 1], tree[131072 * 2 + 1], a[131072];
info tmp, check(1, 0, 0, 1);
info query(int node, int start, int end, int i, int j);
info mal(info a1, info a2) {
  info w;
  w.x1 = (a1.x1 * a2.x1 + a1.y1 * a2.x2) % 1000000007LL;
  w.y1 = (a1.x1 * a2.y1 + a1.y1 * a2.y2) % 1000000007LL;
  w.x2 = (a1.x2 * a2.x1 + a1.y2 * a2.x2) % 1000000007LL;
  w.y2 = (a1.x2 * a2.y1 + a1.y2 * a2.y2) % 1000000007LL;
  return w;
}
info func(long long num) {
  if (num == 1) return tmp;
  info s = func(num / 2);
  info w = mal(s, s);
  if (num % 2 == 1) w = mal(w, tmp);
  return w;
}
void init(int node, int start, int end) {
  lazy[node] = check;
  if (start == end)
    tree[node] = a[start];
  else {
    init(node << 1, start, (start + end) >> 1);
    init((node << 1) | 1, ((start + end) >> 1) + 1, end);
    tree[node] = tree[node * 2] + tree[node * 2 + 1];
  }
}
void lazy_propagation(int node, int start, int end) {
  if (lazy[node] != check) {
    tree[node] = mal(tree[node], lazy[node]);
    if (start != end) {
      lazy[node << 1] = mal(lazy[node << 1], lazy[node]);
      lazy[(node << 1) | 1] = mal(lazy[node << 1 | 1], lazy[node]);
    }
    lazy[node] = check;
  }
}
void update(int node, int start, int end, int i, int j, info val) {
  lazy_propagation(node, start, end);
  if (i > end || j < start) return;
  if (i <= start && end <= j) {
    tree[node] = mal(tree[node], val);
    if (start != end) {
      lazy[node << 1] = mal(lazy[node << 1], val);
      lazy[(node << 1) | 1] = mal(lazy[(node << 1) | 1], val);
    }
    return;
  } else {
    update(node << 1, start, (start + end) / 2, i, j, val);
    update((node << 1) | 1, (start + end) / 2 + 1, end, i, j, val);
    tree[node] = tree[node << 1] + tree[(node << 1) | 1];
  }
}
info query(int node, int start, int end, int i, int j) {
  lazy_propagation(node, start, end);
  if (i > end || j < start) {
    info w(0, 0, 0, 0);
    return w;
  }
  if (i <= start && end <= j) return tree[node];
  return query(node * 2, start, (start + end) / 2, i, j) +
         query(node * 2 + 1, (start + end) / 2 + 1, end, i, j);
}
int main(void) {
  int n, m;
  scanf("%d %d", &n, &m);
  for (int i = 0; i < n; i++) {
    long long u;
    scanf("%lld", &u);
    a[i] = func(u);
  }
  init(1, 0, n - 1);
  for (int i = 1; i <= m; i++) {
    int type;
    long long s, e;
    scanf("%d %lld %lld", &type, &s, &e);
    if (type == 2)
      printf("%lld\n", query(1, 0, n - 1, s - 1, e - 1).y1);
    else {
      long long x;
      scanf("%lld", &x);
      info w = func(x);
      update(1, 0, n - 1, s - 1, e - 1, w);
    }
  }
}
