#ifndef LOCAL
#include <bits/stdc++.h>
#define debug(...)
#endif
using namespace std;
#define int long long
#define cinv(v) for (auto &it:v) cin>>it;
#define coutv(v) for (auto &it:v) cout<< it<<' '; cout<<'\n';
const int bit = 22, N = 1e6 + 5, MOD = 1e9 + 7;
template<class T> struct BIT { //1-indexed
int n;
vector<T> t;
BIT() {
}
BIT(int _n) {
n = _n;
t.assign(n + 1, 0);
}
T query(int i) {
T ans = 0;
for (; i >= 1; i -= (i & -i)) ans += t[i];
return ans;
}
void upd(int i, T val) {
if (i <= 0) return;
for (; i <= n; i += (i & -i)) t[i] += val;
}
void upd(int l, int r, T val) {
upd(l, val);
upd(r + 1, -val);
}
T query(int l, int r) {
return query(r) - query(l - 1);
}
};
BIT<int> tree[bit];
int arr[N], pw[N];
void shelby() {
int n, q;
cin >> n >> q;
for (auto &it: tree) it = BIT<int>(n);
for (int i = 1; i <= n; ++i) {
cin >> arr[i];
for (int j = 0; j < bit; ++j) {
if ((arr[i] >> j) & 1) tree[j].upd(i, 1);
}
}
while (q--) {
int t;
cin >> t;
if (t == 1) {
int i, x;
cin >> i >> x;
arr[i] ^= x;
for (int j = 0; j < bit; ++j) {
if ((arr[i] >> j & 1) == tree[j].query(i, i)) continue;
if (arr[i] >> j & 1) tree[j].upd(i, 1);
else tree[j].upd(i, -1);
}
}
else {
int l, r;
cin >> l >> r;
int ans = 0;
for (int i = 0; i < bit; ++i) {
int on = tree[i].query(l, r);
int tot = pw[on - 1] * (1 << i) % MOD * pw[(r - l + 1) - on] % MOD;
ans = (ans + tot) % MOD;
}
cout << ans << '\n';
}
}
}
signed main() {
cin.tie(0)->sync_with_stdio(0);
pw[0] = 1;
for (int i = 1; i < N; ++i) pw[i] = pw[i - 1] * 2 % MOD;
int t = 1;
// cin >> t;
for (int _ = 1; _ <= t; ++_) {
// cout << "Case " << _ << ": ";
shelby();
}
}