#include <bits/stdc++.h>
using namespace std;
const int MAX = 1e5 + 5;
const int LIM = 3e5 + 5;
const int SZ = 2;
const int LN = 64;
const int MOD = 1e9 + 7;
template <typename T>
void inPos(T &x) {
  x = 0;
  register T c = getchar();
  while ((c < 48) || (c > 57)) c = getchar();
  for (; c < 48 || c > 57; c = getchar())
    ;
  for (; c > 47 && c < 58; c = getchar()) x = (x << 3) + (x << 1) + (c & 15);
}
template <typename T>
void outPos(T n) {
  char snum[65];
  int i = 0;
  do {
    snum[i++] = n % 10 + '0';
    n /= 10;
  } while (n);
  i = i - 1;
  while (i >= 0) putchar(snum[i--]);
  putchar('\n');
}
template <typename T>
T mod(T a, T b) {
  return (a < b ? a : a % b);
}
template <typename T>
T add(T a, T b, T c) {
  T x = a + b;
  return (x >= c ? x - c : x);
}
template <typename T>
T mod_neg(T a, T b) {
  a = mod(a, b);
  if (a < 0) {
    a += b;
  }
  return a;
}
template <typename T>
struct Matrix {
  T data[SZ][SZ];
  Matrix<T>() { init_identity(); }
  Matrix<T>(T base[SZ][SZ]) {
    for (int i = 0; i < SZ; ++i) {
      for (int j = 0; j < SZ; ++j) {
        data[i][j] = base[i][j];
      }
    }
  }
  Matrix<T> operator=(const Matrix<T> &other) {
    for (int i = 0; i < SZ; ++i) {
      for (int j = 0; j < SZ; ++j) {
        this->data[i][j] = other.data[i][j];
      }
    }
    return *this;
  }
  Matrix<T> operator+(const Matrix<T> &other) const {
    Matrix res;
    for (int i = 0; i < SZ; ++i) {
      for (int j = 0; j < SZ; ++j) {
        res[i][j] = add(data[i][j], other[i][j], MOD);
      }
    }
    return res;
  }
  Matrix<T> operator-(const Matrix<T> &other) const {
    Matrix res;
    for (int i = 0; i < SZ; ++i) {
      for (int j = 0; j < SZ; ++j) {
        res[i][j] = mod_neg(data[i][j] - other[i][j], MOD);
      }
    }
    return res;
  }
  Matrix<T> operator*(const Matrix<T> &other) const {
    Matrix res;
    for (int i = 0; i < SZ; ++i) {
      for (int j = 0; j < SZ; ++j) {
        res[i][j] = 0;
        for (int k = 0; k < SZ; ++k) {
          res[i][j] = mod(res[i][j] + (long long)data[i][k] * other[k][j],
                          (long long)MOD);
        }
      }
    }
    return res;
  }
  const T *operator[](int i) const { return data[i]; }
  T *operator[](int i) { return data[i]; }
  void init_zero() {
    for (int i = 0; i < SZ; ++i) {
      for (int j = 0; j < SZ; ++j) {
        data[i][j] = 0;
      }
    }
  }
  void init_identity() {
    for (int i = 0; i < SZ; ++i) {
      for (int j = 0; j < SZ; ++j) {
        data[i][j] = (i == j);
      }
    }
  }
  void print() {
    for (int i = 0; i < SZ; ++i) {
      for (int j = 0; j < SZ; ++j) {
        cout << data[i][j] << " ";
      }
      cout << "\n";
    }
  }
};
Matrix<int> base;
Matrix<int> pre[LN];
void init(Matrix<int> mat) {
  pre[0].init_identity();
  pre[1] = mat;
  for (int i = 2; i < LN; ++i) {
    pre[i] = pre[i - 1] * pre[i - 1];
  }
}
Matrix<int> power(Matrix<int> a, long long n) {
  Matrix<int> res;
  int cnt = 1;
  while (n) {
    if (n & 1) {
      res = res * pre[cnt];
    }
    cnt += 1;
    n >>= 1;
  }
  return res;
}
int a[MAX];
Matrix<int> value;
Matrix<int> seg[LIM];
Matrix<int> lazy[LIM];
bool push[LIM];
void combine(int t) { seg[t] = seg[t * 2] + seg[t * 2 + 1]; }
void propagate(int t, int i, int j) {
  if (push[t]) {
    seg[t] = seg[t] * lazy[t];
    if (i != j) {
      push[t * 2] = true;
      push[t * 2 + 1] = true;
      lazy[t * 2] = lazy[t * 2] * lazy[t];
      lazy[t * 2 + 1] = lazy[t * 2 + 1] * lazy[t];
    }
    push[t] = false;
    lazy[t].init_identity();
  }
}
void build(int t, int i, int j) {
  push[t] = false;
  lazy[t].init_identity();
  if (i == j) {
    seg[t] = power(base, a[i]);
    return;
  }
  int mid = (i + j) / 2;
  build(t * 2, i, mid);
  build(t * 2 + 1, mid + 1, j);
  combine(t);
}
void update(int t, int i, int j, int l, int r) {
  propagate(t, i, j);
  if (i > r || j < l) {
    return;
  }
  if (l <= i && j <= r) {
    lazy[t] = lazy[t] * value;
    push[t] = true;
    propagate(t, i, j);
    return;
  }
  int mid = (i + j) / 2;
  update(t * 2, i, mid, l, r);
  update(t * 2 + 1, mid + 1, j, l, r);
  combine(t);
}
int query(int t, int i, int j, int l, int r) {
  propagate(t, i, j);
  if (i > r || j < l) {
    return 0;
  }
  if (l <= i && j <= r) {
    return seg[t].data[0][1];
  }
  int mid = (i + j) / 2;
  int a = query(t * 2, i, mid, l, r);
  int b = query(t * 2 + 1, mid + 1, j, l, r);
  return add(a, b, MOD);
}
int main() {
  int fib[SZ][SZ] = {{1, 1}, {1, 0}};
  base = fib;
  init(base);
  int n, m;
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= n; ++i) {
    scanf("%d", &a[i]);
  }
  build(1, 1, n);
  int type, l, r, x;
  while (m--) {
    scanf("%d %d %d", &type, &l, &r);
    if (type == 1) {
      scanf("%d", &x);
      value = power(base, x);
      update(1, 1, n, l, r);
    } else {
      int ans = query(1, 1, n, l, r);
      outPos(ans);
    }
  }
  return 0;
}
