#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<string.h>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<map>
#include<set>
#include<iostream>
#include<sstream>
#include<cctype>
#define fi first
#define se second
#define rep(i,n) for(int i = 0; i < n; i++)
#define rrep(i,n) for(int i = 1; i <= n; i++)
#define drep(i,n) for(int i = n-1; i >= 0; i--)
#define gep(i,g,j) for(int i = g.head[j]; i != -1; i = g.e[i].next)
#define each(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
#define rng(a) a.begin(),a.end()
#define maxs(x,y) x = max(x,y)
#define mins(x,y) x = min(x,y)
#define pb push_back
#define sz(x) (int)(x).size()
#define pcnt __builtin_popcount
#define snuke srand((unsigned)clock()+(unsigned)time(NULL))
using namespace std;
typedef long long int ll;
typedef pair<int,int> P;
typedef vector<int> vi;

const int MX = 300005, INF = 1000010000;
const ll LINF = 1000000000000000000ll;
const double eps = 1e-10;
const int dx[] = {-1,0,1,0}, dy[] = {0,-1,0,1}; //<^>v
const int mod = 1000000009;

int f[MX*2], g[MX*2];

// Segment tree (RMQ type)
struct seg{
	vector<ll> d, e1, e2; int sz, sz2;
	seg(){}
	seg(int mx){
		sz = 1; while(sz < mx) sz <<= 1;
		sz2 = sz<<1; d.resize(sz2,0); e1.resize(sz2,0); e2.resize(sz2,0);
	}
	void fil(){ drep(i,sz) d[i] = d[i<<1]+d[i<<1|1];}
	void addr(int a, int b, int x, int y, int i=1, int l=0, int r=INF){
		if(r == INF) r = sz;
		if(a <= l && r <= b){
			e1[i] += x;
			e2[i] += y;
			return;
		}
		int c = l+r>>1;
		if(a < c) addr(a,b,x,y,i<<1,l,c);
		if(c < b) {
			int nx = 0, ny = 0, nc = c-l;
			(nx += x*f[nc+1])%=mod;
			(ny += x*f[nc])%=mod;
			(nx += y*f[nc])%=mod;
			if(c) (ny += y*f[nc-1])%=mod;
		  addr(a,b,nx,ny,i<<1|1,c,r);
		}
	}
	int qu(int a, int b, int i=1, int l=0, int r=INF){
		if(r == INF) r = sz;
		(d[i] += e1[i]*g[r-l])%=mod;
		(d[i] += e2[i]*g[r-l-1])%=mod;
		if (l+1 != r) {
			(e1[i<<1] += e1[i])%=mod;
			(e2[i<<1] += e2[i])%=mod;
			int c = (r-l)>>1;
			(e1[i<<1|1] += e1[i]*f[c+1])%=mod;
			(e2[i<<1|1] += e1[i]*f[c])%=mod;
			(e1[i<<1|1] += e2[i]*f[c])%=mod;
			if(c) (e2[i<<1|1] += e2[i]*f[c-1])%=mod;
		}
		e1[i] = e2[i] = 0;
		if(a <= l && r <= b) return d[i];
		int c = l+r>>1; int res = 0;
		if(a < c) (res += qu(a,b,i<<1,l,c)) %= mod;
		res %= mod;
		if(c < b) (res += qu(a,b,i<<1|1,c,r)) %= mod;
		res %= mod;
		return res;
	}
};
//

int main(){
	int n, m;
	scanf("%d%d",&n,&m);
	f[1] = f[2] = 1;
	rrep(i,n*2+5) f[i+2] = (f[i]+f[i+1])%mod;
	rep(i,n*2+5) g[i] = f[i];
	rrep(i,n*2+5) (g[i] += g[i-1]) %= mod;
	seg t(n+5);
	rep(i,n) scanf("%I64d",&t.d[t.sz+i]);
	t.fil();
	rep(j,m){
		int tp, l, r;
		scanf("%d%d%d",&tp,&l,&r);
		--l;
		if(tp == 1) {
			t.addr(l, r, 1, 0);
		} else {
			printf("%d\n",t.qu(l, r));
		}
	}

	return 0;
}


#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<string.h>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<map>
#include<set>
#include<iostream>
#include<sstream>
#include<cctype>
#define fi first
#define se second
#define rep(i,n) for(int i = 0; i < n; i++)
#define rrep(i,n) for(int i = 1; i <= n; i++)
#define drep(i,n) for(int i = n-1; i >= 0; i--)
#define gep(i,g,j) for(int i = g.head[j]; i != -1; i = g.e[i].next)
#define each(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
#define rng(a) a.begin(),a.end()
#define maxs(x,y) x = max(x,y)
#define mins(x,y) x = min(x,y)
#define pb push_back
#define sz(x) (int)(x).size()
#define pcnt __builtin_popcount
#define snuke srand((unsigned)clock()+(unsigned)time(NULL))
using namespace std;
typedef long long int ll;
typedef pair<int,int> P;
typedef vector<int> vi;

const int MX = 300005, INF = 1000010000;
const ll LINF = 1000000000000000000ll;
const double eps = 1e-10;
const int dx[] = {-1,0,1,0}, dy[] = {0,-1,0,1}; //<^>v
const int mod = 1000000009;

int f[MX*2], g[MX*2];

// Segment tree (RMQ type)
struct seg{
	vector<ll> d, e1, e2; int sz, sz2;
	seg(){}
	seg(int mx){
		sz = 1; while(sz < mx) sz <<= 1;
		sz2 = sz<<1; d.resize(sz2,0); e1.resize(sz2,0); e2.resize(sz2,0);
	}
	void fil(){ drep(i,sz) d[i] = d[i<<1]+d[i<<1|1];}
	void addr(int a, int b, ll x, ll y, int i=1, int l=0, int r=INF){
		if(r == INF) r = sz;
		if(a <= l && r <= b){
			e1[i] += x;
			e2[i] += y;
			return;
		}
		int nr = min(r,b);
		int nl = max(l,a);
		(d[i] += x*g[nr-nl])%=mod;
		(d[i] += y*g[nr-nl-1])%=mod;
		int c = l+r>>1;
		if(a < c) addr(a,b,x,y,i<<1,l,c);
		if(c < b) {
			ll nx = 0, ny = 0; int nc = max(0,c-max(a,l));
			(nx += x*f[nc+1])%=mod;
			(ny += x*f[nc])%=mod;
			(nx += y*f[nc])%=mod;
			if(c) (ny += y*f[nc-1])%=mod;
		  addr(a,b,nx,ny,i<<1|1,c,r);
		}
	}
	int qu(int a, int b, int i=1, int l=0, int r=INF){
		if(r == INF) r = sz;
		(d[i] += e1[i]*g[r-l])%=mod;
		(d[i] += e2[i]*g[r-l-1])%=mod;
		if (l+1 != r) {
			(e1[i<<1] += e1[i])%=mod;
			(e2[i<<1] += e2[i])%=mod;
			int c = (r-l)>>1;
			(e1[i<<1|1] += e1[i]*f[c+1])%=mod;
			(e2[i<<1|1] += e1[i]*f[c])%=mod;
			(e1[i<<1|1] += e2[i]*f[c])%=mod;
			if(c) (e2[i<<1|1] += e2[i]*f[c-1])%=mod;
		}
		e1[i] = e2[i] = 0;
		if(a <= l && r <= b) return d[i];
		int c = l+r>>1; int res = 0;
		if(a < c) (res += qu(a,b,i<<1,l,c)) %= mod;
		res %= mod;
		if(c < b) (res += qu(a,b,i<<1|1,c,r)) %= mod;
		res %= mod;
		return res;
	}
};
//

int main(){
	int n, m;
	scanf("%d%d",&n,&m);
	f[1] = f[2] = 1;
	rrep(i,n*2+5) f[i+2] = (f[i]+f[i+1])%mod;
	rep(i,n*2+5) g[i] = f[i];
	rrep(i,n*2+5) (g[i] += g[i-1]) %= mod;
	seg t(n+5);
	rep(i,n) scanf("%I64d",&t.d[t.sz+i]);
	t.fil();
	rep(j,m){
		int tp, l, r;
		scanf("%d%d%d",&tp,&l,&r);
		--l;
		if(tp == 1) {
			t.addr(l, r, 1, 0);
		} else {
			printf("%d\n",t.qu(l, r));
		}
	}

	return 0;
}


#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<string.h>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<map>
#include<set>
#include<iostream>
#include<sstream>
#include<cctype>
#define fi first
#define se second
#define rep(i,n) for(int i = 0; i < n; i++)
#define rrep(i,n) for(int i = 1; i <= n; i++)
#define drep(i,n) for(int i = n-1; i >= 0; i--)
#define gep(i,g,j) for(int i = g.head[j]; i != -1; i = g.e[i].next)
#define each(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
#define rng(a) a.begin(),a.end()
#define maxs(x,y) x = max(x,y)
#define mins(x,y) x = min(x,y)
#define pb push_back
#define sz(x) (int)(x).size()
#define pcnt __builtin_popcount
#define snuke srand((unsigned)clock()+(unsigned)time(NULL))
using namespace std;
typedef long long int ll;
typedef pair<int,int> P;
typedef vector<int> vi;

const int MX = 300005, INF = 1000010000;
const ll LINF = 1000000000000000000ll;
const double eps = 1e-10;
const int dx[] = {-1,0,1,0}, dy[] = {0,-1,0,1}; //<^>v
const int mod = 1000000009;

int f[MX*2], g[MX*2];

// Segment tree (RMQ type)
struct seg{
	vector<ll> d, e1, e2; int sz, sz2;
	seg(){}
	seg(int mx){
		sz = 1; while(sz < mx) sz <<= 1;
		sz2 = sz<<1; d.resize(sz2,0); e1.resize(sz2,0); e2.resize(sz2,0);
	}
	void fil(){ drep(i,sz) d[i] = d[i<<1]+d[i<<1|1];}
	void addr(int a, int b, int x, int y, int i=1, int l=0, int r=INF){
		if(r == INF) r = sz;
		if(a <= l && r <= b){
			e1[i] += x;
			e2[i] += y;
			return;
		}
		int nr = min(r,b);
		int nl = max(l,a);
		(d[i] += x*g[nr-nl])%=mod;
		(d[i] += y*g[nr-nl-1])%=mod;
		int c = l+r>>1;
		if(a < c) addr(a,b,x,y,i<<1,l,c);
		if(c < b) {
			int nx = 0, ny = 0, nc = max(0,c-max(a,l));
			(nx += x*f[nc+1])%=mod;
			(ny += x*f[nc])%=mod;
			(nx += y*f[nc])%=mod;
			if(c) (ny += y*f[nc-1])%=mod;
		  addr(a,b,nx,ny,i<<1|1,c,r);
		}
	}
	int qu(int a, int b, int i=1, int l=0, int r=INF){
		if(r == INF) r = sz;
		(d[i] += e1[i]*g[r-l])%=mod;
		(d[i] += e2[i]*g[r-l-1])%=mod;
		if (l+1 != r) {
			(e1[i<<1] += e1[i])%=mod;
			(e2[i<<1] += e2[i])%=mod;
			int c = (r-l)>>1;
			(e1[i<<1|1] += e1[i]*f[c+1])%=mod;
			(e2[i<<1|1] += e1[i]*f[c])%=mod;
			(e1[i<<1|1] += e2[i]*f[c])%=mod;
			if(c) (e2[i<<1|1] += e2[i]*f[c-1])%=mod;
		}
		e1[i] = e2[i] = 0;
		if(a <= l && r <= b) return d[i];
		int c = l+r>>1; int res = 0;
		if(a < c) (res += qu(a,b,i<<1,l,c)) %= mod;
		res %= mod;
		if(c < b) (res += qu(a,b,i<<1|1,c,r)) %= mod;
		res %= mod;
		return res;
	}
};
//

int main(){
	int n, m;
	scanf("%d%d",&n,&m);
	f[1] = f[2] = 1;
	rrep(i,n*2+5) f[i+2] = (f[i]+f[i+1])%mod;
	rep(i,n*2+5) g[i] = f[i];
	rrep(i,n*2+5) (g[i] += g[i-1]) %= mod;
	seg t(n+5);
	rep(i,n) scanf("%I64d",&t.d[t.sz+i]);
	t.fil();
	rep(j,m){
		int tp, l, r;
		scanf("%d%d%d",&tp,&l,&r);
		--l;
		if(tp == 1) {
			t.addr(l, r, 1, 0);
		} else {
			printf("%d\n",t.qu(l, r));
		}
	}

	return 0;
}


#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<string.h>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<map>
#include<set>
#include<iostream>
#include<sstream>
#include<cctype>
#define fi first
#define se second
#define rep(i,n) for(int i = 0; i < n; i++)
#define rrep(i,n) for(int i = 1; i <= n; i++)
#define drep(i,n) for(int i = n-1; i >= 0; i--)
#define gep(i,g,j) for(int i = g.head[j]; i != -1; i = g.e[i].next)
#define each(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
#define rng(a) a.begin(),a.end()
#define maxs(x,y) x = max(x,y)
#define mins(x,y) x = min(x,y)
#define pb push_back
#define sz(x) (int)(x).size()
#define pcnt __builtin_popcount
#define snuke srand((unsigned)clock()+(unsigned)time(NULL))
using namespace std;
typedef long long int ll;
typedef pair<int,int> P;
typedef vector<int> vi;

const int MX = 100005, INF = 1000010000;
const ll LINF = 1000000000000000000ll;
const double eps = 1e-10;
const int dx[] = {-1,0,1,0}, dy[] = {0,-1,0,1}; //<^>v
const int mod = 1000000009;

int f[MX], g[MX];

// Segment tree (RMQ type)
struct seg{
	vector<ll> d, e1, e2; int sz, sz2;
	seg(){}
	seg(int mx){
		sz = 1; while(sz < mx) sz <<= 1;
		sz2 = sz<<1; d.resize(sz2,0); e1.resize(sz2,0); e2.resize(sz2,0);
	}
	void fil(){ drep(i,sz) d[i] = d[i<<1]+d[i<<1|1];}
	void addr(int a, int b, int x, int y, int i=1, int l=0, int r=INF){
		if(r == INF) r = sz;
		if(a <= l && r <= b){
			e1[i] += x;
			e2[i] += y;
			return;
		}
		int c = l+r>>1;
		if(a < c) addr(a,b,x,y,i<<1,l,c);
		if(c < b) {
			int nx = 0, ny = 0, nc = c-l;
			(nx += x*f[nc+1])%=mod;
			(ny += x*f[nc])%=mod;
			(nx += y*f[nc])%=mod;
			if(c) (ny += y*f[nc-1])%=mod;
		  addr(a,b,nx,ny,i<<1|1,c,r);
		}
	}
	int qu(int a, int b, int i=1, int l=0, int r=INF){
		if(r == INF) r = sz;
		(d[i] += e1[i]*g[r-l])%=mod;
		(d[i] += e2[i]*g[r-l-1])%=mod;
		if (l+1 != r) {
			(e1[i<<1] += e1[i])%=mod;
			(e2[i<<1] += e2[i])%=mod;
			int c = (r-l)>>1;
			(e1[i<<1|1] += e1[i]*f[c+1])%=mod;
			(e2[i<<1|1] += e1[i]*f[c])%=mod;
			(e1[i<<1|1] += e2[i]*f[c])%=mod;
			if(c) (e2[i<<1|1] += e2[i]*f[c-1])%=mod;
		}
		e1[i] = e2[i] = 0;
		if(a <= l && r <= b) return d[i];
		int c = l+r>>1; int res = 0;
		if(a < c) (res += qu(a,b,i<<1,l,c)) %= mod;
		res %= mod;
		if(c < b) (res += qu(a,b,i<<1|1,c,r)) %= mod;
		res %= mod;
		return res;
	}
};
//

int main(){
	int n, m;
	scanf("%d%d",&n,&m);
	f[1] = f[2] = 1;
	rrep(i,n) f[i+2] = f[i]+f[i+1];
	rep(i,n+3) g[i] = f[i];
	rrep(i,n+3) g[i] += g[i-1];
	seg t(n+5);
	rep(i,n) scanf("%I64d",&t.d[t.sz+i]);
	t.fil();
	rep(j,m){
		int tp, l, r;
		scanf("%d%d%d",&tp,&l,&r);
		--l;
		if(tp == 1) {
			t.addr(l, r, 1, 0);
		} else {
			printf("%d\n",t.qu(l, r));
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#ifdef SG
	#include <debug.h>
#else
	#define show(...)
	#define debug(...)
	#define deepen(...)
	#define timer(...)
#endif

#define forn(i,n) for (int i = 0; i < int(n); ++i)
#define ford(i,n) for (int i = int(n) - 1; i >= 0; --i)
#define forv(i,v) for (auto i = v.begin(); i != v.end(); ++i)
#define forr(i,v) for (auto i = v.end(); i != v.begin() && (--i, 1); )
#define ve vector
#define pa pair
#define tu tuple
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define fs first
#define sc second
#define all(a) (a).begin(), (a).end()
#define sz(a) ((int)(a).size())

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pa<int, int> pii;
typedef pa<int, ll> pil;
typedef pa<ll, int> pli;
typedef pa<ll, ll> pll;
typedef ve<int> vi;

const ld pi = 3.1415926535897932384626433832795l;

template<typename T> inline auto sqr (T x) -> decltype(x * x) {return x * x;}
template<typename T> inline T abs (T x) {return x > T() ? x : -x;}
template<typename T1, typename T2> inline bool umx (T1& a, T2 b) {if (a < b) {a = b; return 1;} return 0;}
template<typename T1, typename T2> inline bool umn (T1& a, T2 b) {if (b < a) {a = b; return 1;} return 0;}

const int N = 300000;
const int M = 300000;

const ll mod = 1000000009;

struct Input {
	int n, m;
	int a[N];
	int t[M], l[M], r[M];

	void init (const Input &input) {
		*this = input;
	}
};

struct Data: Input {
	bool read () {
		if (!(cin >> n >> m)) {
			return 0;
		}
		forn (i, n) {
			scanf("%d", &a[i]);
		}
		forn (i, m) {
			scanf("%d%d%d", &t[i], &l[i], &r[i]);
			--t[i];
			--l[i];
		}
		return 1;
	}

	ve<ll> ans;

	void write () {
		forn (i, sz(ans)) {
			cout << ans[i] << endl;
		}
	}

	virtual void solve () {}

	virtual void clear () {
		*this = Data();
	}
};

struct Solution: Data {
	ll v1[N], v2[N];
	ll s[4 * N], u1[4 * N], u2[4 * N];
	int lb[4 * N], rb[4 * N];
	int ts;

	void push (int v) {
		(s[v] += (v1[rb[v] + 1] + mod - v1[lb[v] + 1]) * u1[v]) %= mod;
		(s[v] += (v2[rb[v] + 1] + mod - v2[lb[v] + 1]) * u2[v]) %= mod;
		if (lb[v] + 1 < rb[v]) {
			(u1[2 * v + 1] += u1[v]) %= mod;
			(u2[2 * v + 1] += u2[v]) %= mod;
			(u1[2 * v + 2] += u1[v]) %= mod;
			(u2[2 * v + 2] += u2[v]) %= mod;
		}
		u1[v] = 0;
		u2[v] = 0;
	}

	void upd (int l, int r, ll q1, ll q2, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return;
		}
		if (lb[v] >= l && rb[v] <= r) {
			(u1[v] += q1) %= mod;
			(u2[v] += q2) %= mod;
			push(v);
			return;
		}
		upd(l, r, q1, q2, 2 * v + 1);
		upd(l, r, q1, q2, 2 * v + 2);
		s[v] = (s[2 * v + 1] + s[2 * v + 2]) % mod;
	}

	ull fnd (int l, int r, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return 0;
		}
		if (lb[v] >= l && rb[v] <= r) {
			return s[v];
		}
		return (fnd(l, r, 2 * v + 1) + fnd(l, r, 2 * v + 2)) % mod;
	}

	ll F[N + 10];
	ll q[N];

	void solve () {
		F[0] = 0;
		F[1] = 1;
		forn (i, N + 8) {
			F[i + 2] = (F[i] + F[i + 1]) % mod;
		}
		forn (i, N) {
			v1[i] = F[i + 1];
			v2[i] = F[i + 2];
			q[i] = F[i];
			if (!(i & 1)) {
				q[i] = (mod - q[i]) % mod;
			}
		}
		debug(q, q + 5);
		ts = 1;
		while (ts < n) {
			ts *= 2;
		}
		memset(u1, 0, sizeof u1);
		memset(u2, 0, sizeof u2);
		forn (i, ts) {
			lb[ts - 1 + i] = i;
			rb[ts - 1 + i] = i + 1;
			s[ts - 1 + i] = a[i];
		}
		ford (i, ts - 1) {
			lb[i] = lb[2 * i + 1];
			rb[i] = rb[2 * i + 2];
			s[i] = (s[2 * i + 1] + s[2 * i + 2]) % mod;
		}
		debug(s, s + 2 * ts - 1);
		debug(u1, u1 + 2 * ts - 1);
		debug(u2, u2 + 2 * ts - 1);
		forn (i, m) {
			if (t[i] == 0) {
				debug(mp(q[l[i] + 1], q[l[i]]));
				upd(l[i], r[i], q[l[i] + 1], q[l[i]], 0);
			} else {
				ans.pb(fnd(l[i], r[i], 0));
			}
			debug(s, s + 2 * ts - 1);
			debug(u1, u1 + 2 * ts - 1);
			debug(u2, u2 + 2 * ts - 1);
		}
	}

	void clear () {
		*this = Solution();
	}
};

Solution sol;

int main () {
	cout.setf(ios::showpoint | ios::fixed);
	cout.precision(20);
#ifdef SG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	while (sol.read()) {
		sol.solve();
		sol.write();
		sol.clear();
	}
#else
	sol.read();
	sol.solve();
	sol.write();
#endif
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#ifdef SG
	#include <debug.h>
#else
	#define show(...)
	#define debug(...)
	#define deepen(...)
	#define timer(...)
#endif

#define forn(i,n) for (int i = 0; i < int(n); ++i)
#define ford(i,n) for (int i = int(n) - 1; i >= 0; --i)
#define forv(i,v) for (auto i = v.begin(); i != v.end(); ++i)
#define forr(i,v) for (auto i = v.end(); i != v.begin() && (--i, 1); )
#define ve vector
#define pa pair
#define tu tuple
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define fs first
#define sc second
#define all(a) (a).begin(), (a).end()
#define sz(a) ((int)(a).size())

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pa<int, int> pii;
typedef pa<int, ll> pil;
typedef pa<ll, int> pli;
typedef pa<ll, ll> pll;
typedef ve<int> vi;

const ld pi = 3.1415926535897932384626433832795l;

template<typename T> inline auto sqr (T x) -> decltype(x * x) {return x * x;}
template<typename T> inline T abs (T x) {return x > T() ? x : -x;}
template<typename T1, typename T2> inline bool umx (T1& a, T2 b) {if (a < b) {a = b; return 1;} return 0;}
template<typename T1, typename T2> inline bool umn (T1& a, T2 b) {if (b < a) {a = b; return 1;} return 0;}

const int N = 300000;
const int M = 300000;

const ll mod = 1000000009;

struct Input {
	int n, m;
	int a[N];
	int t[M], l[M], r[M];

	void init (const Input &input) {
		*this = input;
	}
};

struct Data: Input {
	bool read () {
		if (!(cin >> n >> m)) {
			return 0;
		}
		forn (i, n) {
			scanf("%d", &a[i]);
		}
		forn (i, m) {
			scanf("%d%d%d", &t[i], &l[i], &r[i]);
			--t[i];
			--l[i];
		}
		return 1;
	}

	ve<ll> ans;

	void write () {
		forn (i, sz(ans)) {
			cout << ans[i] << endl;
		}
	}

	virtual void solve () {}

	virtual void clear () {
		*this = Data();
	}
};

struct Solution: Data {
	ll v1[2 * N], v2[2 * N];
	ll s[2 * N], u1[2 * N], u2[2 * N];
	int lb[2 * N], rb[2 * N];
	int ts;

	void push (int v) {
		(s[v] += (v1[rb[v] + 1] + mod - v1[lb[v] + 1]) * u1[v]) %= mod;
		(s[v] += (v2[rb[v] + 1] + mod - v2[lb[v] + 1]) * u2[v]) %= mod;
		if (lb[v] + 1 < rb[v]) {
			(u1[2 * v + 1] += u1[v]) %= mod;
			(u2[2 * v + 1] += u2[v]) %= mod;
			(u1[2 * v + 2] += u1[v]) %= mod;
			(u2[2 * v + 2] += u2[v]) %= mod;
		}
		u1[v] = 0;
		u2[v] = 0;
	}

	void upd (int l, int r, ll q1, ll q2, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return;
		}
		if (lb[v] >= l && rb[v] <= r) {
			(u1[v] += q1) %= mod;
			(u2[v] += q2) %= mod;
			push(v);
			return;
		}
		upd(l, r, q1, q2, 2 * v + 1);
		upd(l, r, q1, q2, 2 * v + 2);
		s[v] = (s[2 * v + 1] + s[2 * v + 2]) % mod;
	}

	ull fnd (int l, int r, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return 0;
		}
		if (lb[v] >= l && rb[v] <= r) {
			return s[v];
		}
		return (fnd(l, r, 2 * v + 1) + fnd(l, r, 2 * v + 2)) % mod;
	}

	ll F[N + 10];
	ll q[N];

	void solve () {
		F[0] = 0;
		F[1] = 1;
		forn (i, N + 8) {
			F[i + 2] = (F[i] + F[i + 1]) % mod;
		}
		forn (i, N) {
			v1[i] = F[i + 1];
			v2[i] = F[i + 2];
			q[i] = F[i];
			if (!(i & 1)) {
				q[i] = (mod - q[i]) % mod;
			}
		}
		debug(q, q + 5);
		ts = 1;
		while (ts < n) {
			ts *= 2;
		}
		memset(u1, 0, sizeof u1);
		memset(u2, 0, sizeof u2);
		forn (i, ts) {
			lb[ts - 1 + i] = i;
			rb[ts - 1 + i] = i + 1;
			s[ts - 1 + i] = a[i];
		}
		ford (i, ts - 1) {
			lb[i] = lb[2 * i + 1];
			rb[i] = rb[2 * i + 2];
			s[i] = (s[2 * i + 1] + s[2 * i + 2]) % mod;
		}
		debug(s, s + 2 * ts - 1);
		debug(u1, u1 + 2 * ts - 1);
		debug(u2, u2 + 2 * ts - 1);
		forn (i, m) {
			if (t[i] == 0) {
				debug(mp(q[l[i] + 1], q[l[i]]));
				upd(l[i], r[i], q[l[i] + 1], q[l[i]], 0);
			} else {
				ans.pb(fnd(l[i], r[i], 0));
			}
			debug(s, s + 2 * ts - 1);
			debug(u1, u1 + 2 * ts - 1);
			debug(u2, u2 + 2 * ts - 1);
		}
	}

	void clear () {
		*this = Solution();
	}
};

Solution sol;

int main () {
	cout.setf(ios::showpoint | ios::fixed);
	cout.precision(20);
#ifdef SG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	while (sol.read()) {
		sol.solve();
		sol.write();
		sol.clear();
	}
#else
	sol.read();
	sol.solve();
	sol.write();
#endif
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#ifdef SG
	#include <debug.h>
#else
	#define show(...)
	#define debug(...)
	#define deepen(...)
	#define timer(...)
#endif

#define forn(i,n) for (int i = 0; i < int(n); ++i)
#define ford(i,n) for (int i = int(n) - 1; i >= 0; --i)
#define forv(i,v) for (auto i = v.begin(); i != v.end(); ++i)
#define forr(i,v) for (auto i = v.end(); i != v.begin() && (--i, 1); )
#define ve vector
#define pa pair
#define tu tuple
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define fs first
#define sc second
#define all(a) (a).begin(), (a).end()
#define sz(a) ((int)(a).size())

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pa<int, int> pii;
typedef pa<int, ll> pil;
typedef pa<ll, int> pli;
typedef pa<ll, ll> pll;
typedef ve<int> vi;

const ld pi = 3.1415926535897932384626433832795l;

template<typename T> inline auto sqr (T x) -> decltype(x * x) {return x * x;}
template<typename T> inline T abs (T x) {return x > T() ? x : -x;}
template<typename T1, typename T2> inline bool umx (T1& a, T2 b) {if (a < b) {a = b; return 1;} return 0;}
template<typename T1, typename T2> inline bool umn (T1& a, T2 b) {if (b < a) {a = b; return 1;} return 0;}

const int N = 300000;
const int M = 300000;

const ll mod = 1000000009;

struct Input {
	int n, m;
	int a[N];
	int t[M], l[M], r[M];

	void init (const Input &input) {
		*this = input;
	}
};

struct Data: Input {
	bool read () {
		if (!(cin >> n >> m)) {
			return 0;
		}
		forn (i, n) {
			scanf("%d", &a[i]);
		}
		forn (i, m) {
			scanf("%d%d%d", &t[i], &l[i], &r[i]);
			--t[i];
			--l[i];
		}
		return 1;
	}

	ve<ll> ans;

	void write () {
		forn (i, sz(ans)) {
			printf("%d\n", int(ans[i]));
		}
	}

	virtual void solve () {}

	virtual void clear () {
		*this = Data();
	}
};

struct Solution: Data {
	ll v1[N + 5], v2[N + 5];
	ll s[4 * N], u1[4 * N], u2[4 * N];
	int lb[4 * N], rb[4 * N];
	int ts;

	void push (int v) {
		(s[v] += (v1[rb[v] + 1] + mod - v1[lb[v] + 1]) * u1[v]) %= mod;
		(s[v] += (v2[rb[v] + 1] + mod - v2[lb[v] + 1]) * u2[v]) %= mod;
		if (lb[v] + 1 < rb[v]) {
			(u1[2 * v + 1] += u1[v]) %= mod;
			(u2[2 * v + 1] += u2[v]) %= mod;
			(u1[2 * v + 2] += u1[v]) %= mod;
			(u2[2 * v + 2] += u2[v]) %= mod;
		}
		u1[v] = 0;
		u2[v] = 0;
	}

	void upd (int l, int r, ll q1, ll q2, int v) {
		if (lb[v] >= r || rb[v] <= l) {
			push(v);
			return;
		}
		if (lb[v] >= l && rb[v] <= r) {
			(u1[v] += q1) %= mod;
			(u2[v] += q2) %= mod;
			push(v);
			return;
		}
		push(v);
		upd(l, r, q1, q2, 2 * v + 1);
		upd(l, r, q1, q2, 2 * v + 2);
		s[v] = (s[2 * v + 1] + s[2 * v + 2]) % mod;
	}

	ull fnd (int l, int r, int v) {
		if (lb[v] >= r || rb[v] <= l) {
			return 0;
		}
		push(v);
		if (lb[v] >= l && rb[v] <= r) {
			return s[v];
		}
		return (fnd(l, r, 2 * v + 1) + fnd(l, r, 2 * v + 2)) % mod;
	}

	ll F[N + 10];
	ll q[N + 5];

	void solve () {
		F[0] = 0;
		F[1] = 1;
		forn (i, N + 8) {
			F[i + 2] = (F[i] + F[i + 1]) % mod;
		}
		forn (i, N + 5) {
			v1[i] = F[i + 1];
			v2[i] = F[i + 2];
			q[i] = F[i];
			if (!(i & 1)) {
				q[i] = (mod - q[i]) % mod;
			}
		}
		debug(q, q + 5);
		ts = 1;
		while (ts < n) {
			ts *= 2;
		}
		memset(u1, 0, sizeof u1);
		memset(u2, 0, sizeof u2);
		forn (i, ts) {
			lb[ts - 1 + i] = i;
			rb[ts - 1 + i] = i + 1;
			s[ts - 1 + i] = a[i];
		}
		ford (i, ts - 1) {
			lb[i] = lb[2 * i + 1];
			rb[i] = rb[2 * i + 2];
			s[i] = (s[2 * i + 1] + s[2 * i + 2]) % mod;
		}
		debug(s, s + 2 * ts - 1);
		debug(u1, u1 + 2 * ts - 1);
		debug(u2, u2 + 2 * ts - 1);
		forn (i, m) {
			if (t[i] == 0) {
				debug(mp(q[l[i] + 1], q[l[i]]));
				upd(l[i], r[i], q[l[i] + 1], q[l[i]], 0);
			} else {
				ans.pb(fnd(l[i], r[i], 0));
			}
			debug(s, s + 2 * ts - 1);
			debug(u1, u1 + 2 * ts - 1);
			debug(u2, u2 + 2 * ts - 1);
		}
	}

	void clear () {
		*this = Solution();
	}
};

Solution sol;

int main () {
	cout.setf(ios::showpoint | ios::fixed);
	cout.precision(20);
#ifdef SG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	while (sol.read()) {
		sol.solve();
		sol.write();
		sol.clear();
	}
#else
	sol.read();
	sol.solve();
	sol.write();
#endif
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#ifdef SG
	#include <debug.h>
#else
	#define show(...)
	#define debug(...)
	#define deepen(...)
	#define timer(...)
#endif

#define forn(i,n) for (int i = 0; i < int(n); ++i)
#define ford(i,n) for (int i = int(n) - 1; i >= 0; --i)
#define forv(i,v) for (auto i = v.begin(); i != v.end(); ++i)
#define forr(i,v) for (auto i = v.end(); i != v.begin() && (--i, 1); )
#define ve vector
#define pa pair
#define tu tuple
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define fs first
#define sc second
#define all(a) (a).begin(), (a).end()
#define sz(a) ((int)(a).size())

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pa<int, int> pii;
typedef pa<int, ll> pil;
typedef pa<ll, int> pli;
typedef pa<ll, ll> pll;
typedef ve<int> vi;

const ld pi = 3.1415926535897932384626433832795l;

template<typename T> inline auto sqr (T x) -> decltype(x * x) {return x * x;}
template<typename T> inline T abs (T x) {return x > T() ? x : -x;}
template<typename T1, typename T2> inline bool umx (T1& a, T2 b) {if (a < b) {a = b; return 1;} return 0;}
template<typename T1, typename T2> inline bool umn (T1& a, T2 b) {if (b < a) {a = b; return 1;} return 0;}

const int N = 300000;
const int M = 300000;

const ll mod = 1000000009;

struct Input {
	int n, m;
	int a[N];
	int t[M], l[M], r[M];

	void init (const Input &input) {
		*this = input;
	}
};

struct Data: Input {
	bool read () {
		if (!(cin >> n >> m)) {
			return 0;
		}
		forn (i, n) {
			scanf("%d", &a[i]);
		}
		forn (i, m) {
			scanf("%d%d%d", &t[i], &l[i], &r[i]);
			--t[i];
			--l[i];
		}
		return 1;
	}

	ve<ll> ans;

	void write () {
		forn (i, sz(ans)) {
			cout << ans[i] << endl;
		}
	}

	virtual void solve () {}

	virtual void clear () {
		*this = Data();
	}
};

struct Solution: Data {
	ll v1[N + 2], v2[N + 2];
	ll s[4 * N], u1[4 * N], u2[4 * N];
	int lb[4 * N], rb[4 * N];
	int ts;

	void push (int v) {
		(s[v] += (v1[rb[v] + 1] + mod - v1[lb[v] + 1]) * u1[v]) %= mod;
		(s[v] += (v2[rb[v] + 1] + mod - v2[lb[v] + 1]) * u2[v]) %= mod;
		if (lb[v] + 1 < rb[v]) {
			(u1[2 * v + 1] += u1[v]) %= mod;
			(u2[2 * v + 1] += u2[v]) %= mod;
			(u1[2 * v + 2] += u1[v]) %= mod;
			(u2[2 * v + 2] += u2[v]) %= mod;
		}
		u1[v] = 0;
		u2[v] = 0;
	}

	void upd (int l, int r, ll q1, ll q2, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return;
		}
		if (lb[v] >= l && rb[v] <= r) {
			(u1[v] += q1) %= mod;
			(u2[v] += q2) %= mod;
			push(v);
			return;
		}
		upd(l, r, q1, q2, 2 * v + 1);
		upd(l, r, q1, q2, 2 * v + 2);
		s[v] = (s[2 * v + 1] + s[2 * v + 2]) % mod;
	}

	ull fnd (int l, int r, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return 0;
		}
		if (lb[v] >= l && rb[v] <= r) {
			return s[v];
		}
		return (fnd(l, r, 2 * v + 1) + fnd(l, r, 2 * v + 2)) % mod;
	}

	ll F[N + 10];
	ll q[N + 2];

	void solve () {
		F[0] = 0;
		F[1] = 1;
		forn (i, N + 8) {
			F[i + 2] = (F[i] + F[i + 1]) % mod;
		}
		forn (i, N + 2) {
			v1[i] = F[i + 1];
			v2[i] = F[i + 2];
			q[i] = F[i];
			if (!(i & 1)) {
				q[i] = (mod - q[i]) % mod;
			}
		}
		debug(q, q + 5);
		ts = 1;
		while (ts < n) {
			ts *= 2;
		}
		memset(u1, 0, sizeof u1);
		memset(u2, 0, sizeof u2);
		forn (i, ts) {
			lb[ts - 1 + i] = i;
			rb[ts - 1 + i] = i + 1;
			s[ts - 1 + i] = a[i];
		}
		ford (i, ts - 1) {
			lb[i] = lb[2 * i + 1];
			rb[i] = rb[2 * i + 2];
			s[i] = (s[2 * i + 1] + s[2 * i + 2]) % mod;
		}
		debug(s, s + 2 * ts - 1);
		debug(u1, u1 + 2 * ts - 1);
		debug(u2, u2 + 2 * ts - 1);
		forn (i, m) {
			if (t[i] == 0) {
				debug(mp(q[l[i] + 1], q[l[i]]));
				upd(l[i], r[i], q[l[i] + 1], q[l[i]], 0);
			} else {
				ans.pb(fnd(l[i], r[i], 0));
			}
			debug(s, s + 2 * ts - 1);
			debug(u1, u1 + 2 * ts - 1);
			debug(u2, u2 + 2 * ts - 1);
		}
	}

	void clear () {
		*this = Solution();
	}
};

Solution sol;

int main () {
	cout.setf(ios::showpoint | ios::fixed);
	cout.precision(20);
#ifdef SG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	while (sol.read()) {
		sol.solve();
		sol.write();
		sol.clear();
	}
#else
	sol.read();
	sol.solve();
	sol.write();
#endif
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#ifdef SG
	#include <debug.h>
#else
	#define show(...)
	#define debug(...)
	#define deepen(...)
	#define timer(...)
#endif

#define forn(i,n) for (int i = 0; i < int(n); ++i)
#define ford(i,n) for (int i = int(n) - 1; i >= 0; --i)
#define forv(i,v) for (auto i = v.begin(); i != v.end(); ++i)
#define forr(i,v) for (auto i = v.end(); i != v.begin() && (--i, 1); )
#define ve vector
#define pa pair
#define tu tuple
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define fs first
#define sc second
#define all(a) (a).begin(), (a).end()
#define sz(a) ((int)(a).size())

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pa<int, int> pii;
typedef pa<int, ll> pil;
typedef pa<ll, int> pli;
typedef pa<ll, ll> pll;
typedef ve<int> vi;

const ld pi = 3.1415926535897932384626433832795l;

template<typename T> inline auto sqr (T x) -> decltype(x * x) {return x * x;}
template<typename T> inline T abs (T x) {return x > T() ? x : -x;}
template<typename T1, typename T2> inline bool umx (T1& a, T2 b) {if (a < b) {a = b; return 1;} return 0;}
template<typename T1, typename T2> inline bool umn (T1& a, T2 b) {if (b < a) {a = b; return 1;} return 0;}

const int N = 300000;
const int M = 300000;

const ll mod = 1000000009;

struct Input {
	int n, m;
	int a[N];
	int t[M], l[M], r[M];

	void init (const Input &input) {
		*this = input;
	}
};

struct Data: Input {
	bool read () {
		if (!(cin >> n >> m)) {
			return 0;
		}
		forn (i, n) {
			scanf("%d", &a[i]);
		}
		forn (i, m) {
			scanf("%d%d%d", &t[i], &l[i], &r[i]);
			--t[i];
			--l[i];
		}
		return 1;
	}

	ve<ll> ans;

	void write () {
		forn (i, sz(ans)) {
			cout << ans[i] << endl;
		}
	}

	virtual void solve () {}

	virtual void clear () {
		*this = Data();
	}
};

struct Solution: Data {
	ll v1[N + 5], v2[N + 5];
	ll s[4 * N], u1[4 * N], u2[4 * N];
	int lb[4 * N], rb[4 * N];
	int ts;

	void push (int v) {
		(s[v] += (v1[rb[v] + 1] + mod - v1[lb[v] + 1]) * u1[v]) %= mod;
		(s[v] += (v2[rb[v] + 1] + mod - v2[lb[v] + 1]) * u2[v]) %= mod;
		if (lb[v] + 1 < rb[v]) {
			(u1[2 * v + 1] += u1[v]) %= mod;
			(u2[2 * v + 1] += u2[v]) %= mod;
			(u1[2 * v + 2] += u1[v]) %= mod;
			(u2[2 * v + 2] += u2[v]) %= mod;
		}
		u1[v] = 0;
		u2[v] = 0;
	}

	void upd (int l, int r, ll q1, ll q2, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return;
		}
		if (lb[v] >= l && rb[v] <= r) {
			(u1[v] += q1) %= mod;
			(u2[v] += q2) %= mod;
			push(v);
			return;
		}
		upd(l, r, q1, q2, 2 * v + 1);
		upd(l, r, q1, q2, 2 * v + 2);
		s[v] = (s[2 * v + 1] + s[2 * v + 2]) % mod;
	}

	ull fnd (int l, int r, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return 0;
		}
		if (lb[v] >= l && rb[v] <= r) {
			return s[v];
		}
		return (fnd(l, r, 2 * v + 1) + fnd(l, r, 2 * v + 2)) % mod;
	}

	ll F[N + 10];
	ll q[N + 5];

	void solve () {
		F[0] = 0;
		F[1] = 1;
		forn (i, N + 8) {
			F[i + 2] = (F[i] + F[i + 1]) % mod;
		}
		forn (i, N + 5) {
			v1[i] = F[i + 1];
			v2[i] = F[i + 2];
			q[i] = F[i];
			if (!(i & 1)) {
				q[i] = (mod - q[i]) % mod;
			}
		}
		debug(q, q + 5);
		ts = 1;
		while (ts < n) {
			ts *= 2;
		}
		memset(u1, 0, sizeof u1);
		memset(u2, 0, sizeof u2);
		forn (i, ts) {
			lb[ts - 1 + i] = i;
			rb[ts - 1 + i] = i + 1;
			s[ts - 1 + i] = a[i];
		}
		ford (i, ts - 1) {
			lb[i] = lb[2 * i + 1];
			rb[i] = rb[2 * i + 2];
			s[i] = (s[2 * i + 1] + s[2 * i + 2]) % mod;
		}
		debug(s, s + 2 * ts - 1);
		debug(u1, u1 + 2 * ts - 1);
		debug(u2, u2 + 2 * ts - 1);
		forn (i, m) {
			if (t[i] == 0) {
				debug(mp(q[l[i] + 1], q[l[i]]));
				upd(l[i], r[i], q[l[i] + 1], q[l[i]], 0);
			} else {
				ans.pb(fnd(l[i], r[i], 0));
			}
			debug(s, s + 2 * ts - 1);
			debug(u1, u1 + 2 * ts - 1);
			debug(u2, u2 + 2 * ts - 1);
		}
	}

	void clear () {
		*this = Solution();
	}
};

Solution sol;

int main () {
	cout.setf(ios::showpoint | ios::fixed);
	cout.precision(20);
#ifdef SG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	while (sol.read()) {
		sol.solve();
		sol.write();
		sol.clear();
	}
#else
	sol.read();
	sol.solve();
	sol.write();
#endif
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#ifdef SG
	#include <debug.h>
#else
	#define show(...)
	#define debug(...)
	#define deepen(...)
	#define timer(...)
#endif

#define forn(i,n) for (int i = 0; i < int(n); ++i)
#define ford(i,n) for (int i = int(n) - 1; i >= 0; --i)
#define forv(i,v) for (auto i = v.begin(); i != v.end(); ++i)
#define forr(i,v) for (auto i = v.end(); i != v.begin() && (--i, 1); )
#define ve vector
#define pa pair
#define tu tuple
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define fs first
#define sc second
#define all(a) (a).begin(), (a).end()
#define sz(a) ((int)(a).size())

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pa<int, int> pii;
typedef pa<int, ll> pil;
typedef pa<ll, int> pli;
typedef pa<ll, ll> pll;
typedef ve<int> vi;

const ld pi = 3.1415926535897932384626433832795l;

template<typename T> inline auto sqr (T x) -> decltype(x * x) {return x * x;}
template<typename T> inline T abs (T x) {return x > T() ? x : -x;}
template<typename T1, typename T2> inline bool umx (T1& a, T2 b) {if (a < b) {a = b; return 1;} return 0;}
template<typename T1, typename T2> inline bool umn (T1& a, T2 b) {if (b < a) {a = b; return 1;} return 0;}

const int N = 300000;
const int M = 300000;

const ll mod = 1000000009;

struct Input {
	int n, m;
	int a[N];
	int t[M], l[M], r[M];

	void init (const Input &input) {
		*this = input;
	}
};

struct Data: Input {
	bool read () {
		if (!(cin >> n >> m)) {
			return 0;
		}
		forn (i, n) {
			scanf("%d", &a[i]);
		}
		forn (i, m) {
			scanf("%d%d%d", &t[i], &l[i], &r[i]);
			--t[i];
			--l[i];
		}
		return 1;
	}

	ve<ll> ans;

	void write () {
		forn (i, sz(ans)) {
			cout << ans[i] << endl;
		}
	}

	virtual void solve () {}

	virtual void clear () {
		*this = Data();
	}
};

struct Solution: Data {
	ll v1[2 * N], v2[2 * N];
	ll s[2 * N], u1[2 * N], u2[2 * N];
	int lb[2 * N], rb[2 * N];
	int ts;

	void push (int v) {
		(s[v] += (v1[rb[v] + 1] + mod - v1[lb[v] + 1]) * u1[v]) %= mod;
		(s[v] += (v2[rb[v] + 1] + mod - v2[lb[v] + 1]) * u2[v]) %= mod;
		if (lb[v] + 1 < rb[v]) {
			(u1[2 * v + 1] += u1[v]) %= mod;
			(u2[2 * v + 1] += u2[v]) %= mod;
			(u1[2 * v + 2] += u1[v]) %= mod;
			(u2[2 * v + 2] += u2[v]) %= mod;
		}
		u1[v] = 0;
		u2[v] = 0;
	}

	void upd (int l, int r, ll q1, ll q2, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return;
		}
		if (lb[v] >= l && rb[v] <= r) {
			(u1[v] += q1) %= mod;
			(u2[v] += q2) %= mod;
			push(v);
			return;
		}
		upd(l, r, q1, q2, 2 * v + 1);
		upd(l, r, q1, q2, 2 * v + 2);
		s[v] = (s[2 * v + 1] + s[2 * v + 2]) % mod;
	}

	ull fnd (int l, int r, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return 0;
		}
		if (lb[v] >= l && rb[v] <= r) {
			return s[v];
		}
		return (fnd(l, r, 2 * v + 1) + fnd(l, r, 2 * v + 2)) % mod;
	}

	ll F[2 * N + 10];
	ll q[2 * N];

	void solve () {
		F[0] = 0;
		F[1] = 1;
		forn (i, 2 * N + 8) {
			F[i + 2] = (F[i] + F[i + 1]) % mod;
		}
		forn (i, 2 * N) {
			v1[i] = F[i + 1];
			v2[i] = F[i + 2];
			q[i] = F[i];
			if (!(i & 1)) {
				q[i] = (mod - q[i]) % mod;
			}
		}
		debug(q, q + 5);
		ts = 1;
		while (ts < n) {
			ts *= 2;
		}
		memset(u1, 0, sizeof u1);
		memset(u2, 0, sizeof u2);
		forn (i, ts) {
			lb[ts - 1 + i] = i;
			rb[ts - 1 + i] = i + 1;
			s[ts - 1 + i] = a[i];
		}
		ford (i, ts - 1) {
			lb[i] = lb[2 * i + 1];
			rb[i] = rb[2 * i + 2];
			s[i] = (s[2 * i + 1] + s[2 * i + 2]) % mod;
		}
		debug(s, s + 2 * ts - 1);
		debug(u1, u1 + 2 * ts - 1);
		debug(u2, u2 + 2 * ts - 1);
		forn (i, m) {
			if (t[i] == 0) {
				debug(mp(q[l[i] + 1], q[l[i]]));
				upd(l[i], r[i], q[l[i] + 1], q[l[i]], 0);
			} else {
				ans.pb(fnd(l[i], r[i], 0));
			}
			debug(s, s + 2 * ts - 1);
			debug(u1, u1 + 2 * ts - 1);
			debug(u2, u2 + 2 * ts - 1);
		}
	}

	void clear () {
		*this = Solution();
	}
};

Solution sol;

int main () {
	cout.setf(ios::showpoint | ios::fixed);
	cout.precision(20);
#ifdef SG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	while (sol.read()) {
		sol.solve();
		sol.write();
		sol.clear();
	}
#else
	sol.read();
	sol.solve();
	sol.write();
#endif
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#ifdef SG
	#include <debug.h>
#else
	#define show(...)
	#define debug(...)
	#define deepen(...)
	#define timer(...)
#endif

#define forn(i,n) for (int i = 0; i < int(n); ++i)
#define ford(i,n) for (int i = int(n) - 1; i >= 0; --i)
#define forv(i,v) for (auto i = v.begin(); i != v.end(); ++i)
#define forr(i,v) for (auto i = v.end(); i != v.begin() && (--i, 1); )
#define ve vector
#define pa pair
#define tu tuple
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define fs first
#define sc second
#define all(a) (a).begin(), (a).end()
#define sz(a) ((int)(a).size())

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pa<int, int> pii;
typedef pa<int, ll> pil;
typedef pa<ll, int> pli;
typedef pa<ll, ll> pll;
typedef ve<int> vi;

const ld pi = 3.1415926535897932384626433832795l;

template<typename T> inline auto sqr (T x) -> decltype(x * x) {return x * x;}
template<typename T> inline T abs (T x) {return x > T() ? x : -x;}
template<typename T1, typename T2> inline bool umx (T1& a, T2 b) {if (a < b) {a = b; return 1;} return 0;}
template<typename T1, typename T2> inline bool umn (T1& a, T2 b) {if (b < a) {a = b; return 1;} return 0;}

const int N = 300000;
const int M = 300000;

const ll mod = 1000000009;

struct Input {
	int n, m;
	int a[N];
	int t[M], l[M], r[M];

	void init (const Input &input) {
		*this = input;
	}
};

struct Data: Input {
	bool read () {
		if (!(cin >> n >> m)) {
			return 0;
		}
		forn (i, n) {
			scanf("%d", &a[i]);
		}
		forn (i, m) {
			scanf("%d%d%d", &t[i], &l[i], &r[i]);
			--t[i];
			--l[i];
		}
		return 1;
	}

	ve<ll> ans;

	void write () {
		forn (i, sz(ans)) {
			cout << ans[i] << endl;
		}
	}

	virtual void solve () {}

	virtual void clear () {
		*this = Data();
	}
};

struct Solution: Data {
	ll v1[N + 1], v2[N + 1];
	ll s[4 * N], u1[4 * N], u2[4 * N];
	int lb[4 * N], rb[4 * N];
	int ts;

	void push (int v) {
		(s[v] += (v1[rb[v] + 1] + mod - v1[lb[v] + 1]) * u1[v]) %= mod;
		(s[v] += (v2[rb[v] + 1] + mod - v2[lb[v] + 1]) * u2[v]) %= mod;
		if (lb[v] + 1 < rb[v]) {
			(u1[2 * v + 1] += u1[v]) %= mod;
			(u2[2 * v + 1] += u2[v]) %= mod;
			(u1[2 * v + 2] += u1[v]) %= mod;
			(u2[2 * v + 2] += u2[v]) %= mod;
		}
		u1[v] = 0;
		u2[v] = 0;
	}

	void upd (int l, int r, ll q1, ll q2, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return;
		}
		if (lb[v] >= l && rb[v] <= r) {
			(u1[v] += q1) %= mod;
			(u2[v] += q2) %= mod;
			push(v);
			return;
		}
		upd(l, r, q1, q2, 2 * v + 1);
		upd(l, r, q1, q2, 2 * v + 2);
		s[v] = (s[2 * v + 1] + s[2 * v + 2]) % mod;
	}

	ull fnd (int l, int r, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return 0;
		}
		if (lb[v] >= l && rb[v] <= r) {
			return s[v];
		}
		return (fnd(l, r, 2 * v + 1) + fnd(l, r, 2 * v + 2)) % mod;
	}

	ll F[N + 10];
	ll q[N + 1];

	void solve () {
		F[0] = 0;
		F[1] = 1;
		forn (i, N + 8) {
			F[i + 2] = (F[i] + F[i + 1]) % mod;
		}
		forn (i, N + 1) {
			v1[i] = F[i + 1];
			v2[i] = F[i + 2];
			q[i] = F[i];
			if (!(i & 1)) {
				q[i] = (mod - q[i]) % mod;
			}
		}
		debug(q, q + 5);
		ts = 1;
		while (ts < n) {
			ts *= 2;
		}
		memset(u1, 0, sizeof u1);
		memset(u2, 0, sizeof u2);
		forn (i, ts) {
			lb[ts - 1 + i] = i;
			rb[ts - 1 + i] = i + 1;
			s[ts - 1 + i] = a[i];
		}
		ford (i, ts - 1) {
			lb[i] = lb[2 * i + 1];
			rb[i] = rb[2 * i + 2];
			s[i] = (s[2 * i + 1] + s[2 * i + 2]) % mod;
		}
		debug(s, s + 2 * ts - 1);
		debug(u1, u1 + 2 * ts - 1);
		debug(u2, u2 + 2 * ts - 1);
		forn (i, m) {
			if (t[i] == 0) {
				debug(mp(q[l[i] + 1], q[l[i]]));
				upd(l[i], r[i], q[l[i] + 1], q[l[i]], 0);
			} else {
				ans.pb(fnd(l[i], r[i], 0));
			}
			debug(s, s + 2 * ts - 1);
			debug(u1, u1 + 2 * ts - 1);
			debug(u2, u2 + 2 * ts - 1);
		}
	}

	void clear () {
		*this = Solution();
	}
};

Solution sol;

int main () {
	cout.setf(ios::showpoint | ios::fixed);
	cout.precision(20);
#ifdef SG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	while (sol.read()) {
		sol.solve();
		sol.write();
		sol.clear();
	}
#else
	sol.read();
	sol.solve();
	sol.write();
#endif
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#ifdef SG
	#include <debug.h>
#else
	#define show(...)
	#define debug(...)
	#define deepen(...)
	#define timer(...)
#endif

#define forn(i,n) for (int i = 0; i < int(n); ++i)
#define ford(i,n) for (int i = int(n) - 1; i >= 0; --i)
#define forv(i,v) for (auto i = v.begin(); i != v.end(); ++i)
#define forr(i,v) for (auto i = v.end(); i != v.begin() && (--i, 1); )
#define ve vector
#define pa pair
#define tu tuple
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define fs first
#define sc second
#define all(a) (a).begin(), (a).end()
#define sz(a) ((int)(a).size())

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pa<int, int> pii;
typedef pa<int, ll> pil;
typedef pa<ll, int> pli;
typedef pa<ll, ll> pll;
typedef ve<int> vi;

const ld pi = 3.1415926535897932384626433832795l;

template<typename T> inline auto sqr (T x) -> decltype(x * x) {return x * x;}
template<typename T> inline T abs (T x) {return x > T() ? x : -x;}
template<typename T1, typename T2> inline bool umx (T1& a, T2 b) {if (a < b) {a = b; return 1;} return 0;}
template<typename T1, typename T2> inline bool umn (T1& a, T2 b) {if (b < a) {a = b; return 1;} return 0;}

const int N = 300000;
const int M = 300000;

const ll mod = 1000000009;

struct Input {
	int n, m;
	int a[N];
	int t[M], l[M], r[M];

	void init (const Input &input) {
		*this = input;
	}
};

struct Data: Input {
	bool read () {
		if (!(cin >> n >> m)) {
			return 0;
		}
		forn (i, n) {
			scanf("%d", &a[i]);
		}
		forn (i, m) {
			scanf("%d%d%d", &t[i], &l[i], &r[i]);
			--t[i];
			--l[i];
		}
		return 1;
	}

	ve<ll> ans;

	void write () {
		forn (i, sz(ans)) {
			cout << ans[i] << endl;
		}
	}

	virtual void solve () {}

	virtual void clear () {
		*this = Data();
	}
};

struct Solution: Data {
	ll v1[N + 1], v2[N + 1];
	ll s[4 * N], u1[4 * N], u2[4 * N];
	int lb[4 * N], rb[4 * N];
	int ts;

	void push (int v) {
		(s[v] += (v1[rb[v] + 1] + mod - v1[lb[v] + 1]) * u1[v]) %= mod;
		(s[v] += (v2[rb[v] + 1] + mod - v2[lb[v] + 1]) * u2[v]) %= mod;
		if (lb[v] + 1 < rb[v]) {
			(u1[2 * v + 1] += u1[v]) %= mod;
			(u2[2 * v + 1] += u2[v]) %= mod;
			(u1[2 * v + 2] += u1[v]) %= mod;
			(u2[2 * v + 2] += u2[v]) %= mod;
		}
		u1[v] = 0;
		u2[v] = 0;
	}

	void upd (int l, int r, ll q1, ll q2, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return;
		}
		if (lb[v] >= l && rb[v] <= r) {
			(u1[v] += q1) %= mod;
			(u2[v] += q2) %= mod;
			push(v);
			return;
		}
		upd(l, r, q1, q2, 2 * v + 1);
		upd(l, r, q1, q2, 2 * v + 2);
		s[v] = (s[2 * v + 1] + s[2 * v + 2]) % mod;
	}

	ull fnd (int l, int r, int v) {
		push(v);
		if (lb[v] >= r || rb[v] <= l) {
			return 0;
		}
		if (lb[v] >= l && rb[v] <= r) {
			return s[v];
		}
		return (fnd(l, r, 2 * v + 1) + fnd(l, r, 2 * v + 2)) % mod;
	}

	ll F[N + 10];
	ll q[N];

	void solve () {
		F[0] = 0;
		F[1] = 1;
		forn (i, N + 8) {
			F[i + 2] = (F[i] + F[i + 1]) % mod;
		}
		forn (i, N) {
			v1[i] = F[i + 1];
			v2[i] = F[i + 2];
			q[i] = F[i];
			if (!(i & 1)) {
				q[i] = (mod - q[i]) % mod;
			}
		}
		debug(q, q + 5);
		ts = 1;
		while (ts < n) {
			ts *= 2;
		}
		memset(u1, 0, sizeof u1);
		memset(u2, 0, sizeof u2);
		forn (i, ts) {
			lb[ts - 1 + i] = i;
			rb[ts - 1 + i] = i + 1;
			s[ts - 1 + i] = a[i];
		}
		ford (i, ts - 1) {
			lb[i] = lb[2 * i + 1];
			rb[i] = rb[2 * i + 2];
			s[i] = (s[2 * i + 1] + s[2 * i + 2]) % mod;
		}
		debug(s, s + 2 * ts - 1);
		debug(u1, u1 + 2 * ts - 1);
		debug(u2, u2 + 2 * ts - 1);
		forn (i, m) {
			if (t[i] == 0) {
				debug(mp(q[l[i] + 1], q[l[i]]));
				upd(l[i], r[i], q[l[i] + 1], q[l[i]], 0);
			} else {
				ans.pb(fnd(l[i], r[i], 0));
			}
			debug(s, s + 2 * ts - 1);
			debug(u1, u1 + 2 * ts - 1);
			debug(u2, u2 + 2 * ts - 1);
		}
	}

	void clear () {
		*this = Solution();
	}
};

Solution sol;

int main () {
	cout.setf(ios::showpoint | ios::fixed);
	cout.precision(20);
#ifdef SG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	while (sol.read()) {
		sol.solve();
		sol.write();
		sol.clear();
	}
#else
	sol.read();
	sol.solve();
	sol.write();
#endif
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#ifdef SG
	#include <debug.h>
#else
	#define show(...)
	#define debug(...)
	#define deepen(...)
	#define timer(...)
#endif

#define forn(i,n) for (int i = 0; i < int(n); ++i)
#define ford(i,n) for (int i = int(n) - 1; i >= 0; --i)
#define forv(i,v) for (auto i = v.begin(); i != v.end(); ++i)
#define forr(i,v) for (auto i = v.end(); i != v.begin() && (--i, 1); )
#define ve vector
#define pa pair
#define tu tuple
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define fs first
#define sc second
#define all(a) (a).begin(), (a).end()
#define sz(a) ((int)(a).size())

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pa<int, int> pii;
typedef pa<int, ll> pil;
typedef pa<ll, int> pli;
typedef pa<ll, ll> pll;
typedef ve<int> vi;

const ld pi = 3.1415926535897932384626433832795l;

template<typename T> inline auto sqr (T x) -> decltype(x * x) {return x * x;}
template<typename T> inline T abs (T x) {return x > T() ? x : -x;}
template<typename T1, typename T2> inline bool umx (T1& a, T2 b) {if (a < b) {a = b; return 1;} return 0;}
template<typename T1, typename T2> inline bool umn (T1& a, T2 b) {if (b < a) {a = b; return 1;} return 0;}

const int N = 300000;
const int M = 300000;

const ll mod = 1000000009;

struct Input {
	int n, m;
	int a[N];
	int t[M], l[M], r[M];

	void init (const Input &input) {
		*this = input;
	}
};

struct Data: Input {
	bool read () {
		if (!(cin >> n >> m)) {
			return 0;
		}
		forn (i, n) {
			scanf("%d", &a[i]);
		}
		forn (i, m) {
			scanf("%d%d%d", &t[i], &l[i], &r[i]);
			--t[i];
			--l[i];
		}
		return 1;
	}

	ve<ll> ans;

	void write () {
		forn (i, sz(ans)) {
			printf("%d\n", int(ans[i]));
		}
	}

	virtual void solve () {}

	virtual void clear () {
		*this = Data();
	}
};

struct Solution: Data {
	ll v1[N + 5], v2[N + 5];
	ll s[4 * N], u1[4 * N], u2[4 * N];
	int lb[4 * N], rb[4 * N];
	int ts;

	void push (int v) {
		(s[v] += (v1[rb[v] + 1] + mod - v1[lb[v] + 1]) * u1[v]) %= mod;
		(s[v] += (v2[rb[v] + 1] + mod - v2[lb[v] + 1]) * u2[v]) %= mod;
		if (lb[v] + 1 < rb[v]) {
			(u1[2 * v + 1] += u1[v]) %= mod;
			(u2[2 * v + 1] += u2[v]) %= mod;
			(u1[2 * v + 2] += u1[v]) %= mod;
			(u2[2 * v + 2] += u2[v]) %= mod;
		}
		u1[v] = 0;
		u2[v] = 0;
	}

	void upd (int l, int r, ll q1, ll q2, int v) {
		if (lb[v] >= r || rb[v] <= l) {
			push(v);
			return;
		}
		if (lb[v] >= l && rb[v] <= r) {
			(u1[v] += q1) %= mod;
			(u2[v] += q2) %= mod;
			push(v);
			return;
		}
		upd(l, r, q1, q2, 2 * v + 1);
		upd(l, r, q1, q2, 2 * v + 2);
		s[v] = (s[2 * v + 1] + s[2 * v + 2]) % mod;
	}

	ull fnd (int l, int r, int v) {
		if (lb[v] >= r || rb[v] <= l) {
			return 0;
		}
		push(v);
		if (lb[v] >= l && rb[v] <= r) {
			return s[v];
		}
		return (fnd(l, r, 2 * v + 1) + fnd(l, r, 2 * v + 2)) % mod;
	}

	ll F[N + 10];
	ll q[N + 5];

	void solve () {
		F[0] = 0;
		F[1] = 1;
		forn (i, N + 8) {
			F[i + 2] = (F[i] + F[i + 1]) % mod;
		}
		forn (i, N + 5) {
			v1[i] = F[i + 1];
			v2[i] = F[i + 2];
			q[i] = F[i];
			if (!(i & 1)) {
				q[i] = (mod - q[i]) % mod;
			}
		}
		debug(q, q + 5);
		ts = 1;
		while (ts < n) {
			ts *= 2;
		}
		memset(u1, 0, sizeof u1);
		memset(u2, 0, sizeof u2);
		forn (i, ts) {
			lb[ts - 1 + i] = i;
			rb[ts - 1 + i] = i + 1;
			s[ts - 1 + i] = a[i];
		}
		ford (i, ts - 1) {
			lb[i] = lb[2 * i + 1];
			rb[i] = rb[2 * i + 2];
			s[i] = (s[2 * i + 1] + s[2 * i + 2]) % mod;
		}
		debug(s, s + 2 * ts - 1);
		debug(u1, u1 + 2 * ts - 1);
		debug(u2, u2 + 2 * ts - 1);
		forn (i, m) {
			if (t[i] == 0) {
				debug(mp(q[l[i] + 1], q[l[i]]));
				upd(l[i], r[i], q[l[i] + 1], q[l[i]], 0);
			} else {
				ans.pb(fnd(l[i], r[i], 0));
			}
			debug(s, s + 2 * ts - 1);
			debug(u1, u1 + 2 * ts - 1);
			debug(u2, u2 + 2 * ts - 1);
		}
	}

	void clear () {
		*this = Solution();
	}
};

Solution sol;

int main () {
	cout.setf(ios::showpoint | ios::fixed);
	cout.precision(20);
#ifdef SG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
	while (sol.read()) {
		sol.solve();
		sol.write();
		sol.clear();
	}
#else
	sol.read();
	sol.solve();
	sol.write();
#endif
	return 0;
}


#include <cstdio>
#include <numeric>
using namespace std;

constexpr int module = 1000000009;

int fibo[300000];
int fibosum[300000];

int get_fibo(int a, int b, int k) {
    if(k == 0) return a;
    // if(k == 1) return b;
    return ((long long) a * fibo[k] + (long long) (b - a) * fibo[k - 1]) % module;
}

int get_fibosum(int a, int b, int k) {
    if(k == 0) return 0;
    if(k == 1) return a;
    // if(k == 2) return (a + b) % module;
    return ((long long) a * fibosum[k - 1] + (long long) (b - a) * fibosum[k - 2]) % module;
}

int get_fibosum(int a, int b, int k1, int k2) {
    int ans = (get_fibosum(a, b, k2) - get_fibosum(a, b, k1)) % module;
    if(ans < 0) ans += module;
    return ans;
}

struct Node {
    int sum;
    int first, second;
} seg[(1 << 20) - 1];

void pull(int nl, int nr, int k) {
    if(nl + 1 < nr)
        seg[k].sum = (seg[2 * k + 1].sum + seg[2 * k + 2].sum) % module;
    else
        seg[k].sum = 0;
    seg[k].sum = (seg[k].sum + get_fibosum(seg[k].first, seg[k].second, nr - nl)) % module;
}

void insert(int l, int r, int first, int second, int nl, int nr, int k);

void push(int nl, int nr, int k) {
    if(seg[k].first || seg[k].second) {
        insert(nl, (nl + nr) / 2, seg[k].first, seg[k].second, nl, (nl + nr) / 2, 2 * k + 1);
        insert((nl + nr) / 2, nr, get_fibo(seg[k].first, seg[k].second, (nr - nl) / 2),
                                  get_fibo(seg[k].first, seg[k].second, (nr - nl) / 2 + 1),
                                  (nl + nr) / 2, nr, 2 * k + 2);
        seg[k].first = seg[k].second = 0;
    }
}

void build(int n, int nl = 0, int nr = 1 << 19, int k = 0) {
    if(nl + 1 == nr) {
        if(nl < n)
            scanf("%d", &seg[k].first);
        seg[k].sum = seg[k].first;
    } else {
        build(n, nl, (nl + nr) / 2, 2 * k + 1);
        build(n, (nl + nr) / 2, nr, 2 * k + 2);
        pull(nl, nr, k);
    }
}

void insert(int l, int r, int first = 1, int second = 1, int nl = 0, int nr = 1 << 19, int k = 0) {
    if(l <= nl && nr <= r) {
        seg[k].first  = (seg[k].first  + get_fibo(first, second, nl - l    )) % module;
        seg[k].second = (seg[k].second + get_fibo(first, second, nl - l + 1)) % module;
        pull(nl, nr, k);
    } else if(!(r <= nl || nr <= l)) {
        insert(l, r, first, second, nl, (nl + nr) / 2, 2 * k + 1);
        insert(l, r, first, second, (nl + nr) / 2, nr, 2 * k + 2);
        pull(nl, nr, k);
    }
}

int query(int l, int r, int nl = 0, int nr = 1 << 19, int k = 0) {
    if(l <= nl && nr <= r) {
        return seg[k].sum;
    } else if(!(r <= nl || nr <= l)) {
        push(nl, nr, k);
        return (query(l, r, nl, (nl + nr) / 2, 2 * k + 1) +
                query(l, r, (nl + nr) / 2, nr, 2 * k + 2)) % module;
    } else {
        return 0;
    }
}

int main(){
    int n, m;
    scanf("%d %d", &n, &m);
    fibo[0] = fibo[1] = 1;
    fibosum[0] = 1; fibosum[1] = 2;
    for(int i = 2; i < n; i++) {
        fibo[i] = (fibo[i - 1] + fibo[i - 2]) % module;
        fibosum[i] = (fibosum[i - 1] + fibo[i]) % module;
    }
    build(n);
    while(m--) {
        int q, l, r;
        scanf("%d %d %d", &q, &l, &r);
        l--;
        if(q == 1) {
            insert(l, r);
        } else {
            printf("%d\n", query(l, r));
        }
    }
}


#include <cstdio>
#include <numeric>
using namespace std;

constexpr int module = 1000000009;

int fibo[300001];
int fibosum[300001];

int get_fibo(int a, int b, int k) {
    if(k == 0) return a;
    // if(k == 1) return b;
    int ans = ((long long) a * fibo[k] + (long long) (b - a) * fibo[k - 1]) % module;
    if(ans < 0) ans += module;
    return ans;
}

int get_fibosum(int a, int b, int k) {
    if(k == 0) return 0;
    if(k == 1) return a;
    // if(k == 2) return (a + b) % module;
    int ans = ((long long) a * fibosum[k - 1] + (long long) (b - a) * fibosum[k - 2]) % module;
    if(ans < 0) ans += module;
    return ans;
}

struct Node {
    int sum;
    int first, second;
} seg[(1 << 20) - 1];

void pull(int nl, int nr, int k) {
    if(nl + 1 < nr)
        seg[k].sum = (seg[2 * k + 1].sum + seg[2 * k + 2].sum) % module;
    else
        seg[k].sum = 0;
    seg[k].sum = (seg[k].sum + get_fibosum(seg[k].first, seg[k].second, nr - nl)) % module;
}

void insert(int l, int r, int first, int second, int nl, int nr, int k);

void push(int nl, int nr, int k) {
    if(seg[k].first || seg[k].second) {
        insert(nl, nr, seg[k].first, seg[k].second, nl, (nl + nr) / 2, 2 * k + 1);
        insert(nl, nr, seg[k].first, seg[k].second, (nl + nr) / 2, nr, 2 * k + 2);
        seg[k].first = seg[k].second = 0;
    }
}

void build(int n, int nl = 0, int nr = 1 << 19, int k = 0) {
    if(nl + 1 == nr) {
        if(nl < n)
            scanf("%d", &seg[k].first);
        seg[k].sum = seg[k].first;
    } else {
        build(n, nl, (nl + nr) / 2, 2 * k + 1);
        build(n, (nl + nr) / 2, nr, 2 * k + 2);
        pull(nl, nr, k);
    }
}

void insert(int l, int r, int first = 1, int second = 1, int nl = 0, int nr = 1 << 19, int k = 0) {
    if(l <= nl && nr <= r) {
        seg[k].first  = (seg[k].first  + get_fibo(first, second, nl - l    )) % module;
        seg[k].second = (seg[k].second + get_fibo(first, second, nl - l + 1)) % module;
        pull(nl, nr, k);
    } else if(!(r <= nl || nr <= l)) {
        insert(l, r, first, second, nl, (nl + nr) / 2, 2 * k + 1);
        insert(l, r, first, second, (nl + nr) / 2, nr, 2 * k + 2);
        pull(nl, nr, k);
    }
}

int query(int l, int r, int nl = 0, int nr = 1 << 19, int k = 0) {
    if(l <= nl && nr <= r) {
        return seg[k].sum;
    } else if(!(r <= nl || nr <= l)) {
        push(nl, nr, k);
        return (query(l, r, nl, (nl + nr) / 2, 2 * k + 1) +
                query(l, r, (nl + nr) / 2, nr, 2 * k + 2)) % module;
    } else {
        return 0;
    }
}

int main(){
    int n, m;
    scanf("%d %d", &n, &m);
    fibo[0] = fibo[1] = 1;
    fibosum[0] = 1; fibosum[1] = 2;
    for(int i = 2; i <= n; i++) {
        fibo[i] = (fibo[i - 1] + fibo[i - 2]) % module;
        fibosum[i] = (fibosum[i - 1] + fibo[i]) % module;
    }
    build(n);
    while(m--) {
        int q, l, r;
        scanf("%d %d %d", &q, &l, &r);
        l--;
        if(q == 1) {
            insert(l, r);
        } else {
            printf("%d\n", query(l, r));
        }
    }
}


#include <bits/stdc++.h>
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
typedef pair<unsigned, unsigned> PUU;
typedef long long LL;
typedef long double K;

const int mod = 1000000009;
const LL INF = 2000000000LL * 2000000000LL;

struct matrix{ int T[3][3]; };

matrix operator*(matrix a, matrix b){
	matrix c;
	FWD(i,0,3) FWD(j,0,3) c.T[i][j] = 0;
	FWD(i,0,3) FWD(k,0,3) FWD(j,0,3)
		c.T[i][k] = (c.T[i][k] + (LL)a.T[i][j] * b.T[j][k]) % mod;
	return c;
}

matrix POW[300010];

typedef int val_t;

struct mod_t {
	int s, a, b;
};

mod_t advance(mod_t m, int k){
	if(k == 0) return m;
	matrix r = POW[k];
	return mod_t({
		m.s + k,
		(int)(((LL)m.a * r.T[0][0] + (LL)m.b * r.T[1][0]) % mod),
		(int)(((LL)m.a * r.T[0][1] + (LL)m.b * r.T[1][1]) % mod)
	});
}

int get_sum(mod_t m, int a, int b){
	m = advance(m, a-m.s);
	matrix r = POW[b-a];
	return ((LL)m.a * r.T[0][2] + (LL)m.b * r.T[1][2]) % mod;
}

val_t apply(val_t v, mod_t m, int x, int y){
	return (v + get_sum(m, x, y)) % mod;
}

mod_t bind(mod_t a, mod_t b){
	if(b.s < a.s) swap(a, b);
	a = advance(a, b.s-a.s);
	return mod_t({b.s, (a.a+b.a) % mod, (a.b+b.b) % mod});
}

val_t sum(val_t a, val_t b){
	return (a+b) % mod;
}

const val_t VAL_INIT = 0;
const mod_t MOD_ZERO = mod_t({0, 0, 0});		// neutral modifier
const int MAXD = 1024*1024;

struct segment_tree {
	int d; val_t V[MAXD]; mod_t M[MAXD];
	void init(int n, val_t* initial = NULL){
		d = 1; while(d < n) d *= 2;
		if(initial) FWD(i,0,n) V[d+i] = initial[i]; else n = 0;
		FWD(i,n,d) V[d+i] = VAL_INIT;
		BCK(i,d-1,0) V[i] = sum(V[2*i], V[2*i+1]);
		FWD(i,1,2*d) M[i] = MOD_ZERO;
	}
	void modify(int x, int y, mod_t m){ _modify(1,0,d,x,y,m); }	// applies m on [x, y)
	val_t query(int x, int y){ return _query(1,0,d,x,y); }		// gets val_t of [x, y)
	void _bind(int u, mod_t m){ M[u] = bind(M[u], m); }
	void _push(int u, int a, int b){
		if(M[u].a == 0 && M[u].b == 0) return;
		V[u] = apply(V[u], M[u], a, b);
		if(u<d) _bind(2*u, M[u]), _bind(2*u+1, M[u]);
		M[u] = MOD_ZERO;
	}
	void _modify(int u, int a, int b, int x, int y, mod_t m){
		_push(u, a, b);
		if(x <= a && b <= y){
			_bind(u, m); _push(u, a, b);
			return;
		}
		if(x<(a+b)/2) _modify(2*u, a, (a+b)/2, x, y, m); else _push(2*u, a, (a+b)/2);
		if((a+b)/2<y) _modify(2*u+1, (a+b)/2, b, x, y, m); else _push(2*u+1, (a+b)/2, b);
		V[u] = sum(V[2*u], V[2*u+1]);
	}
	val_t _query(int u, int a, int b, int x, int y){
		_push(u, a, b);
		if(x <= a && b <= y) return V[u];
		if(y <= (a+b)/2) return _query(2*u, a, (a+b)/2, x, y);
		if((a+b)/2 <= x) return _query(2*u+1, (a+b)/2, b, x, y);
		return sum(_query(2*u, a, (a+b)/2, x, y), _query(2*u+1, (a+b)/2, b, x, y));
	}
} S;

int n, m;
int A[300010];

int main(){
	matrix a;
	FWD(i,0,3) FWD(j,0,3) POW[0].T[i][j] = (i==j?1:0), a.T[i][j] = 0;
	a.T[0][1] = a.T[0][2] = a.T[1][0] = a.T[1][1] = a.T[2][2] = 1;
	FWD(i,1,300010) POW[i] = POW[i-1] * a;
	scanf("%d %d", &n, &m);
	FWD(i,0,n) scanf("%d", &A[i]);
	S.init(n, A);
	FWD(i,0,m){
		int t, a, b;
		scanf("%d %d %d", &t, &a, &b);
		--a;
		if(t == 1){
			S.modify(a, b, {a, 1, 1});
		}else{
			printf("%d\n", S.query(a, b));
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
typedef pair<unsigned, unsigned> PUU;
typedef long long LL;
typedef long double K;

const int mod = 1000000009;
const LL INF = 2000000000LL * 2000000000LL;

struct matrix{ int T[3][3]; };

matrix operator*(matrix a, matrix b){
	matrix c;
	FWD(i,0,3) FWD(j,0,3) c.T[i][j] = 0;
	FWD(i,0,3) FWD(k,0,3) FWD(j,0,3)
		c.T[i][k] = (c.T[i][k] + (LL)a.T[i][j] * b.T[j][k]) % mod;
	return c;
}

void print(matrix a){
	FWD(i,0,3){
		printf("\t");
		FWD(j,0,3) printf("%d ", a.T[i][j]);
		printf("\n");
	}
}

matrix POW[300010];

matrix pow(int w){
	return POW[w];
}

typedef int val_t;

struct mod_t {
	int s, a, b;
};

mod_t advance(mod_t m, int k){
	if(k == 0) return m;
	matrix r = pow(k);
	return mod_t({
		m.s + k,
		(int)(((LL)m.a * r.T[0][0] + (LL)m.b * r.T[1][0]) % mod),
		(int)(((LL)m.a * r.T[0][1] + (LL)m.b * r.T[1][1]) % mod)
	});
}

int get_sum(mod_t m, int a, int b){
	//printf("get sum %d %d %d on %d %d\n", m.s, m.a, m.b, a, b);
	m = advance(m, a-m.s);
	//printf("get sum %d %d %d on %d %d\n", m.s, m.a, m.b, a, b);
	matrix r = pow(b-a);
	//printf("res %lld\n", ((LL)m.a * r.T[0][2] + (LL)m.b * r.T[1][2]) % mod);
	return ((LL)m.a * r.T[0][2] + (LL)m.b * r.T[1][2]) % mod;
}

val_t apply(val_t v, mod_t m, int x, int y){
	return (v + get_sum(m, x, y)) % mod;
}

mod_t bind(mod_t a, mod_t b){
	if(b.s < a.s) swap(a, b);
	a = advance(a, b.s-a.s);
	return mod_t({b.s, (a.a+b.a) % mod, (a.b+b.b) % mod});
}

val_t sum(val_t a, val_t b){
	return (a+b) % mod;
}

const val_t VAL_INIT = 0;
const mod_t MOD_ZERO = mod_t({0, 0, 0});		// neutral modifier
const int MAXD = 1024*1024;

struct segment_tree {
	int d; val_t V[MAXD]; mod_t M[MAXD];
	void init(int n, val_t* initial = NULL){
		d = 1; while(d < n) d *= 2;
		if(initial) FWD(i,0,n) V[d+i] = initial[i]; else n = 0;
		FWD(i,n,d) V[d+i] = VAL_INIT;
		BCK(i,d-1,0) V[i] = sum(V[2*i], V[2*i+1]);
		FWD(i,1,2*d) M[i] = MOD_ZERO;
	}
	void modify(int x, int y, mod_t m){ _modify(1,0,d,x,y,m); }	// applies m on [x, y)
	val_t query(int x, int y){ return _query(1,0,d,x,y); }		// gets val_t of [x, y)
	void _bind(int u, mod_t m){ M[u] = bind(M[u], m); }
	void _push(int u, int a, int b){
		V[u] = apply(V[u], M[u], a, b);
		if(u<d) _bind(2*u, M[u]), _bind(2*u+1, M[u]);
		M[u] = MOD_ZERO;
	}
	void _modify(int u, int a, int b, int x, int y, mod_t m){
		_push(u, a, b);
		if(x <= a && b <= y){
			_bind(u, m); _push(u, a, b);
			return;
		}
		if(x<(a+b)/2) _modify(2*u, a, (a+b)/2, x, y, m); else _push(2*u, a, (a+b)/2);
		if((a+b)/2<y) _modify(2*u+1, (a+b)/2, b, x, y, m); else _push(2*u+1, (a+b)/2, b);
		V[u] = sum(V[2*u], V[2*u+1]);
	}
	val_t _query(int u, int a, int b, int x, int y){
		_push(u, a, b);
		if(x <= a && b <= y) return V[u];
		if(y <= (a+b)/2) return _query(2*u, a, (a+b)/2, x, y);
		if((a+b)/2 <= x) return _query(2*u+1, (a+b)/2, b, x, y);
		return sum(_query(2*u, a, (a+b)/2, x, y), _query(2*u+1, (a+b)/2, b, x, y));
	}
} S;

int n, m;
int A[300010];

int main(){
	matrix a;
	FWD(i,0,3) FWD(j,0,3) POW[0].T[i][j] = (i==j?1:0), a.T[i][j] = 0;
	a.T[0][1] = a.T[0][2] = a.T[1][0] = a.T[1][1] = a.T[2][2] = 1;
	FWD(i,1,300010) POW[i] = POW[i-1] * a;
	scanf("%d %d", &n, &m);
	FWD(i,0,n) scanf("%d", &A[i]);
	S.init(n, A);
	FWD(i,0,m){
		int t, a, b;
		scanf("%d %d %d", &t, &a, &b);
		--a;
		if(t == 1){
			S.modify(a, b, {a, 1, 1});
		}else{
			printf("%d\n", S.query(a, b));
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
typedef pair<unsigned, unsigned> PUU;
typedef long long LL;
typedef long double K;

const int mod = 1000000009;
const LL INF = 2000000000LL * 2000000000LL;

struct matrix{ int T[3][3]; };

matrix operator*(matrix a, matrix b){
	matrix c;
	FWD(i,0,3) FWD(j,0,3) c.T[i][j] = 0;
	FWD(i,0,3) FWD(k,0,3) FWD(j,0,3)
		c.T[i][k] = (c.T[i][k] + (LL)a.T[i][j] * b.T[j][k]) % mod;
	return c;
}

void print(matrix a){
	FWD(i,0,3){
		printf("\t");
		FWD(j,0,3) printf("%d ", a.T[i][j]);
		printf("\n");
	}
}

matrix pow(int w){
	matrix a, r;
	FWD(i,0,3) FWD(j,0,3) r.T[i][j] = (i==j?1:0), a.T[i][j] = 0;
	a.T[0][1] = a.T[0][2] = a.T[1][0] = a.T[1][1] = a.T[2][2] = 1;
	while(w){
		if(w&1) r = r*a;
		a = a*a;
		w /= 2;
	}
	return r;
}

typedef int val_t;

struct mod_t {
	int s, a, b;
};

mod_t advance(mod_t m, int k){
	matrix r = pow(k);
	return mod_t({
		m.s + k,
		(int)(((LL)m.a * r.T[0][0] + (LL)m.b * r.T[1][0]) % mod),
		(int)(((LL)m.a * r.T[0][1] + (LL)m.b * r.T[1][1]) % mod)
	});
}

int get_sum(mod_t m, int a, int b){
	//printf("get sum %d %d %d on %d %d\n", m.s, m.a, m.b, a, b);
	m = advance(m, a-m.s);
	//printf("get sum %d %d %d on %d %d\n", m.s, m.a, m.b, a, b);
	matrix r = pow(b-a);
	//printf("res %lld\n", ((LL)m.a * r.T[0][2] + (LL)m.b * r.T[1][2]) % mod);
	return ((LL)m.a * r.T[0][2] + (LL)m.b * r.T[1][2]) % mod;
}

val_t apply(val_t v, mod_t m, int x, int y){
	return (v + get_sum(m, x, y)) % mod;
}

mod_t bind(mod_t a, mod_t b){
	if(b.s < a.s) swap(a, b);
	a = advance(a, b.s-a.s);
	return mod_t({b.s, (a.a+b.a) % mod, (a.b+b.b) % mod});
}

val_t sum(val_t a, val_t b){
	return (a+b) % mod;
}

const val_t VAL_INIT = 0;
const mod_t MOD_ZERO = mod_t({0, 0, 0});		// neutral modifier
const int MAXD = 1024*1024;

struct segment_tree {
	int d; val_t V[MAXD]; mod_t M[MAXD];
	void init(int n, val_t* initial = NULL){
		d = 1; while(d < n) d *= 2;
		if(initial) FWD(i,0,n) V[d+i] = initial[i]; else n = 0;
		FWD(i,n,d) V[d+i] = VAL_INIT;
		BCK(i,d-1,0) V[i] = sum(V[2*i], V[2*i+1]);
		FWD(i,1,2*d) M[i] = MOD_ZERO;
	}
	void modify(int x, int y, mod_t m){ _modify(1,0,d,x,y,m); }	// applies m on [x, y)
	val_t query(int x, int y){ return _query(1,0,d,x,y); }		// gets val_t of [x, y)
	void _bind(int u, mod_t m){ M[u] = bind(M[u], m); }
	void _push(int u, int a, int b){
		V[u] = apply(V[u], M[u], a, b);
		if(u<d) _bind(2*u, M[u]), _bind(2*u+1, M[u]);
		M[u] = MOD_ZERO;
	}
	void _modify(int u, int a, int b, int x, int y, mod_t m){
		_push(u, a, b);
		if(x <= a && b <= y){
			_bind(u, m); _push(u, a, b);
			return;
		}
		if(x<(a+b)/2) _modify(2*u, a, (a+b)/2, x, y, m); else _push(2*u, a, (a+b)/2);
		if((a+b)/2<y) _modify(2*u+1, (a+b)/2, b, x, y, m); else _push(2*u+1, (a+b)/2, b);
		V[u] = sum(V[2*u], V[2*u+1]);
	}
	val_t _query(int u, int a, int b, int x, int y){
		_push(u, a, b);
		if(x <= a && b <= y) return V[u];
		if(y <= (a+b)/2) return _query(2*u, a, (a+b)/2, x, y);
		if((a+b)/2 <= x) return _query(2*u+1, (a+b)/2, b, x, y);
		return sum(_query(2*u, a, (a+b)/2, x, y), _query(2*u+1, (a+b)/2, b, x, y));
	}
} S;

int n, m;
int A[300010];

int main(){
	scanf("%d %d", &n, &m);
	FWD(i,0,n) scanf("%d", &A[i]);
	S.init(n, A);
	FWD(i,0,m){
		int t, a, b;
		scanf("%d %d %d", &t, &a, &b);
		--a;
		if(t == 1){
			S.modify(a, b, {a, 1, 1});
		}else{
			printf("%d\n", S.query(a, b));
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
typedef pair<unsigned, unsigned> PUU;
typedef long long LL;
typedef long double K;

const int mod = 1000000009;
const LL INF = 2000000000LL * 2000000000LL;

struct matrix{ int T[3][3]; };

matrix operator*(matrix a, matrix b){
	matrix c;
	FWD(i,0,3) FWD(j,0,3) c.T[i][j] = 0;
	FWD(i,0,3) FWD(k,0,3) FWD(j,0,3)
		c.T[i][k] = (c.T[i][k] + (LL)a.T[i][j] * b.T[j][k]) % mod;
	return c;
}

matrix POW[1024*1024+3];

typedef int val_t;

struct mod_t {
	int s, a, b;
};

mod_t advance(mod_t m, int k){
	if(k == 0) return m;
	matrix r = POW[k];
	return mod_t({
		m.s + k,
		(int)(((LL)m.a * r.T[0][0] + (LL)m.b * r.T[1][0]) % mod),
		(int)(((LL)m.a * r.T[0][1] + (LL)m.b * r.T[1][1]) % mod)
	});
}

int get_sum(mod_t m, int a, int b){
	m = advance(m, a-m.s);
	matrix r = POW[b-a];
	return ((LL)m.a * r.T[0][2] + (LL)m.b * r.T[1][2]) % mod;
}

val_t apply(val_t v, mod_t m, int x, int y){
	return (v + get_sum(m, x, y)) % mod;
}

mod_t bind(mod_t a, mod_t b){
	if(b.s < a.s) swap(a, b);
	a = advance(a, b.s-a.s);
	return mod_t({b.s, (a.a+b.a) % mod, (a.b+b.b) % mod});
}

val_t sum(val_t a, val_t b){
	return (a+b) % mod;
}

const val_t VAL_INIT = 0;
const mod_t MOD_ZERO = mod_t({0, 0, 0});		// neutral modifier
const int MAXD = 1024*1024;

struct segment_tree {
	int d; val_t V[MAXD]; mod_t M[MAXD];
	void init(int n, val_t* initial = NULL){
		d = 1; while(d < n) d *= 2;
		if(initial) FWD(i,0,n) V[d+i] = initial[i]; else n = 0;
		FWD(i,n,d) V[d+i] = VAL_INIT;
		BCK(i,d-1,0) V[i] = sum(V[2*i], V[2*i+1]);
		FWD(i,1,2*d) M[i] = MOD_ZERO;
	}
	void modify(int x, int y, mod_t m){ _modify(1,0,d,x,y,m); }	// applies m on [x, y)
	val_t query(int x, int y){ return _query(1,0,d,x,y); }		// gets val_t of [x, y)
	void _bind(int u, mod_t m){ M[u] = bind(M[u], m); }
	void _push(int u, int a, int b){
		V[u] = apply(V[u], M[u], a, b);
		if(u<d) _bind(2*u, M[u]), _bind(2*u+1, M[u]);
		M[u] = MOD_ZERO;
	}
	void _modify(int u, int a, int b, int x, int y, mod_t m){
		_push(u, a, b);
		if(x <= a && b <= y){
			_bind(u, m); _push(u, a, b);
			return;
		}
		if(x<(a+b)/2) _modify(2*u, a, (a+b)/2, x, y, m); else _push(2*u, a, (a+b)/2);
		if((a+b)/2<y) _modify(2*u+1, (a+b)/2, b, x, y, m); else _push(2*u+1, (a+b)/2, b);
		V[u] = sum(V[2*u], V[2*u+1]);
	}
	val_t _query(int u, int a, int b, int x, int y){
		_push(u, a, b);
		if(x <= a && b <= y) return V[u];
		if(y <= (a+b)/2) return _query(2*u, a, (a+b)/2, x, y);
		if((a+b)/2 <= x) return _query(2*u+1, (a+b)/2, b, x, y);
		return sum(_query(2*u, a, (a+b)/2, x, y), _query(2*u+1, (a+b)/2, b, x, y));
	}
} S;

int n, m;
int A[300010];

int main(){
	matrix a;
	FWD(i,0,3) FWD(j,0,3) POW[0].T[i][j] = (i==j?1:0), a.T[i][j] = 0;
	a.T[0][1] = a.T[0][2] = a.T[1][0] = a.T[1][1] = a.T[2][2] = 1;
	FWD(i,1,1024*1024+3) POW[i] = POW[i-1] * a;
	scanf("%d %d", &n, &m);
	FWD(i,0,n) scanf("%d", &A[i]);
	S.init(n, A);
	FWD(i,0,m){
		int t, a, b;
		scanf("%d %d %d", &t, &a, &b);
		--a;
		if(t == 1){
			S.modify(a, b, {a, 1, 1});
		}else{
			printf("%d\n", S.query(a, b));
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
typedef pair<unsigned, unsigned> PUU;
typedef long long LL;
typedef long double K;

const int mod = 1000000009;
const LL INF = 2000000000LL * 2000000000LL;

struct matrix{ int T[3][3]; };

matrix operator*(matrix a, matrix b){
	matrix c;
	FWD(i,0,3) FWD(j,0,3) c.T[i][j] = 0;
	FWD(i,0,3) FWD(k,0,3) FWD(j,0,3)
		c.T[i][k] = (c.T[i][k] + (LL)a.T[i][j] * b.T[j][k]) % mod;
	return c;
}

matrix POW[300010];

typedef int val_t;

struct mod_t {
	int s, a, b;
};

mod_t advance(mod_t m, int k){
	if(k > 300005){
		printf("TROLOLO\n");
		exit(0);
	}
	if(k == 0) return m;
	matrix r = POW[k];
	return mod_t({
		m.s + k,
		(int)(((LL)m.a * r.T[0][0] + (LL)m.b * r.T[1][0]) % mod),
		(int)(((LL)m.a * r.T[0][1] + (LL)m.b * r.T[1][1]) % mod)
	});
}

int get_sum(mod_t m, int a, int b){
	m = advance(m, a-m.s);
	if(b-a > 300005){
		printf("TROLOLO\n");
		exit(0);
	}
	matrix r = POW[b-a];
	return ((LL)m.a * r.T[0][2] + (LL)m.b * r.T[1][2]) % mod;
}

val_t apply(val_t v, mod_t m, int x, int y){
	return (v + get_sum(m, x, y)) % mod;
}

mod_t bind(mod_t a, mod_t b){
	if(b.s < a.s) swap(a, b);
	a = advance(a, b.s-a.s);
	return mod_t({b.s, (a.a+b.a) % mod, (a.b+b.b) % mod});
}

val_t sum(val_t a, val_t b){
	return (a+b) % mod;
}

const val_t VAL_INIT = 0;
const mod_t MOD_ZERO = mod_t({0, 0, 0});		// neutral modifier
const int MAXD = 1024*1024;

struct segment_tree {
	int d; val_t V[MAXD]; mod_t M[MAXD];
	void init(int n, val_t* initial = NULL){
		d = 1; while(d < n) d *= 2;
		if(initial) FWD(i,0,n) V[d+i] = initial[i]; else n = 0;
		FWD(i,n,d) V[d+i] = VAL_INIT;
		BCK(i,d-1,0) V[i] = sum(V[2*i], V[2*i+1]);
		FWD(i,1,2*d) M[i] = MOD_ZERO;
	}
	void modify(int x, int y, mod_t m){ _modify(1,0,d,x,y,m); }	// applies m on [x, y)
	val_t query(int x, int y){ return _query(1,0,d,x,y); }		// gets val_t of [x, y)
	void _bind(int u, mod_t m){ M[u] = bind(M[u], m); }
	void _push(int u, int a, int b){
		V[u] = apply(V[u], M[u], a, b);
		if(u<d) _bind(2*u, M[u]), _bind(2*u+1, M[u]);
		M[u] = MOD_ZERO;
	}
	void _modify(int u, int a, int b, int x, int y, mod_t m){
		_push(u, a, b);
		if(x <= a && b <= y){
			_bind(u, m); _push(u, a, b);
			return;
		}
		if(x<(a+b)/2) _modify(2*u, a, (a+b)/2, x, y, m); else _push(2*u, a, (a+b)/2);
		if((a+b)/2<y) _modify(2*u+1, (a+b)/2, b, x, y, m); else _push(2*u+1, (a+b)/2, b);
		V[u] = sum(V[2*u], V[2*u+1]);
	}
	val_t _query(int u, int a, int b, int x, int y){
		_push(u, a, b);
		if(x <= a && b <= y) return V[u];
		if(y <= (a+b)/2) return _query(2*u, a, (a+b)/2, x, y);
		if((a+b)/2 <= x) return _query(2*u+1, (a+b)/2, b, x, y);
		return sum(_query(2*u, a, (a+b)/2, x, y), _query(2*u+1, (a+b)/2, b, x, y));
	}
} S;

int n, m;
int A[300010];

int main(){
	matrix a;
	FWD(i,0,3) FWD(j,0,3) POW[0].T[i][j] = (i==j?1:0), a.T[i][j] = 0;
	a.T[0][1] = a.T[0][2] = a.T[1][0] = a.T[1][1] = a.T[2][2] = 1;
	FWD(i,1,300010) POW[i] = POW[i-1] * a;
	scanf("%d %d", &n, &m);
	FWD(i,0,n) scanf("%d", &A[i]);
	S.init(n, A);
	FWD(i,0,m){
		int t, a, b;
		scanf("%d %d %d", &t, &a, &b);
		--a;
		if(t == 1){
			S.modify(a, b, {a, 1, 1});
		}else{
			printf("%d\n", S.query(a, b));
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define REP(a,b) for(int a=0; a<(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define x first
#define y second
#define pb push_back
#define re real()
#define im imag()

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef double K;
typedef vector<int> VI;

const int mod = 1000000009;

int n, m, d;
vector<int> I[1024*1024+3];
int S[1024*1024+3];

int F[300010];
int P[300010];

int get(int i, int k){
	return (P[i+k-1] - P[i-1] + mod) % mod;
}

void push(int u, int k){
	for(int i : I[u]){
		S[u] = (S[u] + get(i, k)) % mod;
		if(u < d){
			I[2*u].push_back(i);
			I[2*u+1].push_back(i+k/2);
		}
	}
	I[u].clear();
}

int dadd(int u, int a, int b, int x, int y){
	if(b < x || y < a) return 0;
	if(x <= a && b <= y){
		I[u].push_back(a-x+1);
		return get(a-x+1, b-a+1);
	}
	int wz = (dadd(2*u, a, (a+b)/2, x, y) + dadd(2*u+1, (a+b)/2+1, b, x, y)) % mod;
	S[u] = (S[u] + wz) % mod;
}

int dget(int u, int a, int b, int x, int y){
	if(b < x || y < a) return 0;
	push(u, b-a+1);
	if(x <= a && b <= y){
		return S[u];
	}
	return (dget(2*u, a, (a+b)/2, x, y) + dget(2*u+1, (a+b)/2+1, b, x, y)) % mod;
}

int main(){
	P[0] = F[0] = 0;
	P[1] = F[1] = 1;
	FWD(i,2,300010){
		F[i] = (F[i-1] + F[i-2]) % mod;
		P[i] = (P[i-1] + F[i]) % mod;
	}
	scanf("%d %d", &n, &m);
	d = 1; while(d < n) d *= 2;
	FWD(i,0,n){
		scanf("%d", &S[d+i]);
	}
	BCK(i,d-1,0) S[i] = (S[2*i]+S[2*i+1]) % mod;
	FWD(i,0,m){
		int t, a, b;
		scanf("%d %d %d", &t, &a, &b);
		--a; --b;
		if(t == 1)
			dadd(1, 0, d-1, a, b);
		else
			printf("%d\n", dget(1, 0, d-1, a, b));
	}
	return 0;
}


#include <bits/stdc++.h>
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
typedef pair<unsigned, unsigned> PUU;
typedef long long LL;
typedef long double K;

const int mod = 1000000009;
const LL INF = 2000000000LL * 2000000000LL;

struct matrix{ int T[3][3]; };

matrix operator*(matrix a, matrix b){
	matrix c;
	FWD(i,0,3) FWD(j,0,3) c.T[i][j] = 0;
	FWD(i,0,3) FWD(k,0,3) FWD(j,0,3)
		c.T[i][k] = ((LL)c.T[i][k] + a.T[i][j] * b.T[j][k]) % mod;
	return c;
}

void print(matrix a){
	FWD(i,0,3){
		printf("\t");
		FWD(j,0,3) printf("%d ", a.T[i][j]);
		printf("\n");
	}
}

matrix pow(int w){
	matrix a, r;
	FWD(i,0,3) FWD(j,0,3) r.T[i][j] = (i==j?1:0), a.T[i][j] = 0;
	a.T[0][1] = a.T[0][2] = a.T[1][0] = a.T[1][1] = a.T[2][2] = 1;
	while(w){
		if(w&1) r = r*a;
		a = a*a;
		w /= 2;
	}
	return r;
}

typedef int val_t;

struct mod_t {
	int s, a, b;
};

mod_t advance(mod_t m, int k){
	matrix r = pow(k);
	return mod_t({
		m.s + k,
		(int)(((LL)m.a * r.T[0][0] + (LL)m.b * r.T[1][0]) % mod),
		(int)(((LL)m.a * r.T[0][1] + (LL)m.b * r.T[1][1]) % mod)
	});
}

int get_sum(mod_t m, int a, int b){
	//printf("get sum %d %d %d on %d %d\n", m.s, m.a, m.b, a, b);
	m = advance(m, a-m.s);
	//printf("get sum %d %d %d on %d %d\n", m.s, m.a, m.b, a, b);
	matrix r = pow(b-a);
	//printf("res %lld\n", ((LL)m.a * r.T[0][2] + (LL)m.b * r.T[1][2]) % mod);
	return ((LL)m.a * r.T[0][2] + (LL)m.b * r.T[1][2]) % mod;
}

val_t apply(val_t v, mod_t m, int x, int y){
	return (v + get_sum(m, x, y)) % mod;
}

mod_t bind(mod_t a, mod_t b){
	if(b.s < a.s) swap(a, b);
	a = advance(a, b.s-a.s);
	return mod_t({b.s, a.a+b.a, a.b+b.b});
}

val_t sum(val_t a, val_t b){
	return (a+b) % mod;
}

const val_t VAL_INIT = 0;
const mod_t MOD_ZERO = mod_t({0, 0, 0});		// neutral modifier
const int MAXD = 1024*1024;

struct segment_tree {
	int d; val_t V[MAXD]; mod_t M[MAXD];
	void init(int n, val_t* initial = NULL){
		d = 1; while(d < n) d *= 2;
		if(initial) FWD(i,0,n) V[d+i] = initial[i]; else n = 0;
		FWD(i,n,d) V[d+i] = VAL_INIT;
		BCK(i,d-1,0) V[i] = sum(V[2*i], V[2*i+1]);
		FWD(i,1,2*d) M[i] = MOD_ZERO;
	}
	void modify(int x, int y, mod_t m){ _modify(1,0,d,x,y,m); }	// applies m on [x, y)
	val_t query(int x, int y){ return _query(1,0,d,x,y); }		// gets val_t of [x, y)
	void _bind(int u, mod_t m){ M[u] = bind(M[u], m); }
	void _push(int u, int a, int b){
		V[u] = apply(V[u], M[u], a, b);
		if(u<d) _bind(2*u, M[u]), _bind(2*u+1, M[u]);
		M[u] = MOD_ZERO;
	}
	void _modify(int u, int a, int b, int x, int y, mod_t m){
		_push(u, a, b);
		if(x <= a && b <= y){
			_bind(u, m); _push(u, a, b);
			return;
		}
		if(x<(a+b)/2) _modify(2*u, a, (a+b)/2, x, y, m); else _push(2*u, a, (a+b)/2);
		if((a+b)/2<y) _modify(2*u+1, (a+b)/2, b, x, y, m); else _push(2*u+1, (a+b)/2, b);
		V[u] = sum(V[2*u], V[2*u+1]);
	}
	val_t _query(int u, int a, int b, int x, int y){
		_push(u, a, b);
		if(x <= a && b <= y) return V[u];
		if(y <= (a+b)/2) return _query(2*u, a, (a+b)/2, x, y);
		if((a+b)/2 <= x) return _query(2*u+1, (a+b)/2, b, x, y);
		return sum(_query(2*u, a, (a+b)/2, x, y), _query(2*u+1, (a+b)/2, b, x, y));
	}
} S;

int n, m;
int A[300010];

int main(){
	scanf("%d %d", &n, &m);
	FWD(i,0,n) scanf("%d", &A[i]);
	S.init(n, A);
	FWD(i,0,m){
		int t, a, b;
		scanf("%d %d %d", &t, &a, &b);
		--a;
		if(t == 1){
			S.modify(a, b, {a, 1, 1});
		}else{
			printf("%d\n", S.query(a, b));
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
typedef pair<unsigned, unsigned> PUU;
typedef long long LL;
typedef long double K;

const int mod = 1000000009;
const LL INF = 2000000000LL * 2000000000LL;

struct matrix{ int T[3][3]; };

matrix operator*(matrix a, matrix b){
	matrix c;
	FWD(i,0,3) FWD(j,0,3) c.T[i][j] = 0;
	FWD(i,0,3) FWD(k,0,3) FWD(j,0,3)
		c.T[i][k] = (c.T[i][k] + (LL)a.T[i][j] * b.T[j][k]) % mod;
	return c;
}

matrix POW[300010];

typedef int val_t;

struct mod_t {
	int s, a, b;
};

mod_t advance(mod_t m, int k){
	if(k < 0){
		printf("TROLOLO\n");
		exit(0);
	}
	if(k == 0) return m;
	matrix r = POW[k];
	return mod_t({
		m.s + k,
		(int)(((LL)m.a * r.T[0][0] + (LL)m.b * r.T[1][0]) % mod),
		(int)(((LL)m.a * r.T[0][1] + (LL)m.b * r.T[1][1]) % mod)
	});
}

int get_sum(mod_t m, int a, int b){
	m = advance(m, a-m.s);
	if(b<a){
		printf("ZOMFG\n");
		exit(0);
	}
	matrix r = POW[b-a];
	return ((LL)m.a * r.T[0][2] + (LL)m.b * r.T[1][2]) % mod;
}

val_t apply(val_t v, mod_t m, int x, int y){
	return (v + get_sum(m, x, y)) % mod;
}

mod_t bind(mod_t a, mod_t b){
	if(b.s < a.s) swap(a, b);
	a = advance(a, b.s-a.s);
	return mod_t({b.s, (a.a+b.a) % mod, (a.b+b.b) % mod});
}

val_t sum(val_t a, val_t b){
	return (a+b) % mod;
}

const val_t VAL_INIT = 0;
const mod_t MOD_ZERO = mod_t({0, 0, 0});		// neutral modifier
const int MAXD = 1024*1024;

struct segment_tree {
	int d; val_t V[MAXD]; mod_t M[MAXD];
	void init(int n, val_t* initial = NULL){
		d = 1; while(d < n) d *= 2;
		if(initial) FWD(i,0,n) V[d+i] = initial[i]; else n = 0;
		FWD(i,n,d) V[d+i] = VAL_INIT;
		BCK(i,d-1,0) V[i] = sum(V[2*i], V[2*i+1]);
		FWD(i,1,2*d) M[i] = MOD_ZERO;
	}
	void modify(int x, int y, mod_t m){ _modify(1,0,d,x,y,m); }	// applies m on [x, y)
	val_t query(int x, int y){ return _query(1,0,d,x,y); }		// gets val_t of [x, y)
	void _bind(int u, mod_t m){ M[u] = bind(M[u], m); }
	void _push(int u, int a, int b){
		V[u] = apply(V[u], M[u], a, b);
		if(u<d) _bind(2*u, M[u]), _bind(2*u+1, M[u]);
		M[u] = MOD_ZERO;
	}
	void _modify(int u, int a, int b, int x, int y, mod_t m){
		_push(u, a, b);
		if(x <= a && b <= y){
			_bind(u, m); _push(u, a, b);
			return;
		}
		if(x<(a+b)/2) _modify(2*u, a, (a+b)/2, x, y, m); else _push(2*u, a, (a+b)/2);
		if((a+b)/2<y) _modify(2*u+1, (a+b)/2, b, x, y, m); else _push(2*u+1, (a+b)/2, b);
		V[u] = sum(V[2*u], V[2*u+1]);
	}
	val_t _query(int u, int a, int b, int x, int y){
		_push(u, a, b);
		if(x <= a && b <= y) return V[u];
		if(y <= (a+b)/2) return _query(2*u, a, (a+b)/2, x, y);
		if((a+b)/2 <= x) return _query(2*u+1, (a+b)/2, b, x, y);
		return sum(_query(2*u, a, (a+b)/2, x, y), _query(2*u+1, (a+b)/2, b, x, y));
	}
} S;

int n, m;
int A[300010];

int main(){
	matrix a;
	FWD(i,0,3) FWD(j,0,3) POW[0].T[i][j] = (i==j?1:0), a.T[i][j] = 0;
	a.T[0][1] = a.T[0][2] = a.T[1][0] = a.T[1][1] = a.T[2][2] = 1;
	FWD(i,1,300010) POW[i] = POW[i-1] * a;
	scanf("%d %d", &n, &m);
	FWD(i,0,n) scanf("%d", &A[i]);
	S.init(n, A);
	FWD(i,0,m){
		int t, a, b;
		scanf("%d %d %d", &t, &a, &b);
		--a;
		if(t == 1){
			S.modify(a, b, {a, 1, 1});
		}else{
			printf("%d\n", S.query(a, b));
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define REP(a,b) for(int a=0; a<(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define x first
#define y second
#define pb push_back
#define re real()
#define im imag()

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef double K;
typedef vector<int> VI;

const int mod = 1000000009;

int n, m, d;
vector<int> I[1024*1024+3];
LL S[1024*1024+3];

LL F[300010];
LL P[300010];

int get(int i, int k){
	return (P[i+k-1] - P[i-1] + mod) % mod;
}

void push(int u, int k){
	for(int i : I[u]){
		S[u] = (S[u] + get(i, k)) % mod;
		if(u < d){
			I[2*u].push_back(i);
			I[2*u+1].push_back(i+k/2);
		}
	}
	I[u].clear();
}

LL dadd(int u, int a, int b, int x, int y){
	if(b < x || y < a) return 0;
	if(x <= a && b <= y){
		I[u].push_back(a-x+1);
		return get(a-x+1, b-a+1);
	}
	LL wz = (dadd(2*u, a, (a+b)/2, x, y) + dadd(2*u+1, (a+b)/2+1, b, x, y)) % mod;
	S[u] = (S[u] + wz) % mod;
}

LL dget(int u, int a, int b, int x, int y){
	if(b < x || y < a) return 0;
	push(u, b-a+1);
	if(x <= a && b <= y){
		return S[u];
	}
	return (dget(2*u, a, (a+b)/2, x, y) + dget(2*u+1, (a+b)/2+1, b, x, y)) % mod;
}

int main(){
	P[0] = F[0] = 0;
	P[1] = F[1] = 1;
	FWD(i,2,300010){
		F[i] = (F[i-1] + F[i-2]) % mod;
		P[i] = (P[i-1] + F[i]) % mod;
	}
	scanf("%d %d", &n, &m);
	d = 1; while(d < n) d *= 2;
	FWD(i,0,n){
		scanf("%d", &S[d+i]);
	}
	BCK(i,d-1,0) S[i] = (S[2*i]+S[2*i+1]) % mod;
	FWD(i,0,m){
		int t, a, b;
		scanf("%d %d %d", &t, &a, &b);
		--a; --b;
		if(t == 1)
			dadd(1, 0, d-1, a, b);
		else
			printf("%d\n", (int)dget(1, 0, d-1, a, b));
	}
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>

// BEGIN CUT HERE
#ifdef _MSC_VER
#include <agents.h>
#endif
// END CUT HERE

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define MP make_pair
#define MT make_tuple
#define X first
#define Y second

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

const int N = 3e5 + 10;
ll fib[N], sum[N];
ll a[N], asum[N];
ll add[N];

int L[N], R[N];

const ll MOD = 1e9 + 9;
const int CNT = sqrt(N);

int main(){
	ios::sync_with_stdio(false);
	int n, m;
	cin >> n >> m;

	rep(i, n) cin >> a[i];
	fib[0] = fib[1] = 1;
	FOR(i, 2, n) fib[i] = (fib[i - 1] + fib[i - 2]) % MOD;
	rep(i, n) sum[i + 1] = (sum[i] + fib[i]) % MOD;
	rep(i, n) asum[i + 1] = (asum[i] + a[i]) % MOD;

	int cnt = 0;
	rep(i, m){
		int t, l, r;
		cin >> t >> l >> r;
		l--;
		if (t == 1){
			L[cnt] = l, R[cnt] = r;
			(add[l] += 1) %= MOD;
			(add[r] += MOD - fib[r - l - 1]) %= MOD;
			if (r - l > 1) (add[r + 1] += MOD - fib[r - l - 2]) %= MOD;

			if (++cnt == CNT){
				rep(i, n){
					(add[i + 1] += add[i]) %= MOD;
					(add[i + 2] += add[i]) %= MOD;
				}
				rep(i, n){
					(asum[i + 1] += add[i]) %= MOD;
					(add[i + 1] += add[i]) %= MOD;
				}
				MEMSET(add, 0);
				cnt = 0;
			}
		}
		else{
			int res = (asum[r] - asum[l] + MOD) % MOD;
			rep(i, cnt){
				int nl = max(l, L[i]), nr = min(r, R[i]);
				if (nr > nl) (res += sum[nr - L[i]] - sum[nl - L[i]] + MOD) %= MOD;
			}
			cout << res << '\n';
		}
	}

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>

// BEGIN CUT HERE
#ifdef _MSC_VER
#include <agents.h>
#endif
// END CUT HERE

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define MP make_pair
#define MT make_tuple
#define X first
#define Y second

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

const int N = 3e5 + 10;
ll fib[N], sum[N];
ll a[N], asum[N];

int L[N], R[N];
int add[N];

const ll MOD = 1e9 + 9;
const int CNT = sqrt(N);

int main(){
	ios::sync_with_stdio(false);
	int n, m;
	cin >> n >> m;

	rep(i, n) cin >> a[i];
	fib[0] = fib[1] = 1;
	FOR(i, 2, n) fib[i] = (fib[i - 1] + fib[i - 2]) % MOD;
	rep(i, n) sum[i + 1] = (sum[i] + fib[i]) % MOD;
	rep(i, n) asum[i + 1] = (asum[i] + a[i]) % MOD;

	int cnt = 0;
	rep(i, m){
		int t, l, r;
		cin >> t >> l >> r;
		l--;
		if (t == 1){
			L[cnt] = l, R[cnt] = r;
			(add[l] += 1) %= MOD;
			(add[r] += MOD - fib[r - l - 1]) %= MOD;
			if (r - l > 1) (add[r + 1] += MOD - fib[r - l - 2]) %= MOD;

			if (++cnt == CNT){
				rep(i, n){
					(add[i + 1] += add[i]) %= MOD;
					(add[i + 2] += add[i]) %= MOD;
				}
				rep(i, n){
					(asum[i + 1] += add[i]) %= MOD;
					(add[i + 1] += add[i]) %= MOD;
				}
				MEMSET(add, 0);
				cnt = 0;
			}
		}
		else{
			int res = (asum[r] - asum[l] + MOD) % MOD;
			rep(i, cnt){
				int nl = max(l, L[i]), nr = min(r, R[i]);
				if (nr > nl) (res += sum[nr - L[i]] - sum[nl - L[i]] + MOD) %= MOD;
			}
			cout << res << '\n';
		}
	}

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>

// BEGIN CUT HERE
#ifdef _MSC_VER
#include <agents.h>
#endif
// END CUT HERE

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define MP make_pair
#define MT make_tuple
#define X first
#define Y second

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

const int N = 3e5 + 10;
ll fib[N], sum[N];
ll a[N], asum[N];
ll add[N];

int L[N], R[N];

const ll MOD = 1e9 + 9;
const int CNT = sqrt(N);

int main(){
	ios::sync_with_stdio(false);
	int n, m;
	cin >> n >> m;

	rep(i, n) cin >> a[i];
	fib[0] = fib[1] = 1;
	FOR(i, 2, n) fib[i] = (fib[i - 1] + fib[i - 2]) % MOD;
	rep(i, n) sum[i + 1] = (sum[i] + fib[i]) % MOD;
	rep(i, n) asum[i + 1] = (asum[i] + a[i]) % MOD;

	int cnt = 0;
	rep(i, m){
		int t, l, r;
		cin >> t >> l >> r;
		l--;
		if (t == 1){
			L[cnt] = l, R[cnt] = r;
			(add[l] += 1) %= MOD;
			(add[r] += MOD - fib[r - l]) %= MOD;
			(add[r + 1] += MOD - fib[r - l - 1]) %= MOD;

			if (++cnt == CNT){
				rep(i, n){
					(add[i + 1] += add[i]) %= MOD;
					(add[i + 2] += add[i]) %= MOD;
				}
				rep(i, n){
					(asum[i + 1] += add[i]) %= MOD;
					(add[i + 1] += add[i]) %= MOD;
				}
				MEMSET(add, 0);
				cnt = 0;
			}
		}
		else{
			int res = (asum[r] - asum[l] + MOD) % MOD;
			rep(i, cnt){
				int nl = max(l, L[i]), nr = min(r, R[i]);
				if (nr > nl) (res += sum[nr - L[i]] - sum[nl - L[i]] + MOD) %= MOD;
			}
			cout << res << '\n';
		}

	}

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>

// BEGIN CUT HERE
#ifdef _MSC_VER
#include <agents.h>
#endif
// END CUT HERE

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define MP make_pair
#define MT make_tuple
#define X first
#define Y second

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

const int N = 3e5 + 10;
ll fib[N], sum[N];
ll a[N], asum[N];
ll add[N];

int L[N], R[N];

const ll MOD = 1e9 + 9;
const int CNT = sqrt(N);

int main(){
	ios::sync_with_stdio(false);
	int n, m;
	cin >> n >> m;

	rep(i, n) cin >> a[i];
	fib[0] = fib[1] = 1;
	FOR(i, 2, n) fib[i] = (fib[i - 1] + fib[i - 2]) % MOD;
	rep(i, n) sum[i + 1] = (sum[i] + fib[i]) % MOD;
	rep(i, n) asum[i + 1] = (asum[i] + a[i]) % MOD;

	int cnt = 0;
	rep(i, m){
		int t, l, r;
		cin >> t >> l >> r;
		l--;
		if (t == 1){
			L[cnt] = l, R[cnt] = r;
			(add[l] += 1) %= MOD;
			(add[r] += MOD - fib[r - l]) %= MOD;
			(add[r + 1] += MOD - fib[r - l - 1]) %= MOD;

			if (++cnt == CNT){
				rep(i, n){
					(add[i + 1] += add[i]) %= MOD;
					(add[i + 2] += add[i]) %= MOD;
				}
				rep(i, n){
					(asum[i + 1] += add[i]) %= MOD;
					(add[i + 1] += add[i]) %= MOD;
				}
				MEMSET(add, 0);
				cnt = 0;
			}
		}
		else{
			ll res = (asum[r] - asum[l] + MOD) % MOD;
			rep(i, cnt){
				int nl = max(l, L[i]), nr = min(r, R[i]);
				if (nr > nl) (res += sum[nr - L[i]] - sum[nl - L[i]] + MOD) %= MOD;
			}
			cout << res << '\n';
		}

	}

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>

// BEGIN CUT HERE
#ifdef _MSC_VER
#include <agents.h>
#endif
// END CUT HERE

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define MP make_pair
#define MT make_tuple
#define X first
#define Y second

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

const int N = 3e5 + 10;
ll fib[N], sum[N];
ll a[N], asum[N];
ll add[N];

int L[N], R[N];

const ll MOD = 1e9 + 9;
const int CNT = sqrt(N);

int main(){
	ios::sync_with_stdio(false);
	int n, m;
	cin >> n >> m;

	rep(i, n) cin >> a[i];
	fib[0] = fib[1] = 1;
	FOR(i, 2, n) fib[i] = (fib[i - 1] + fib[i - 2]) % MOD;
	rep(i, n) sum[i + 1] = (sum[i] + fib[i]) % MOD;
	rep(i, n) asum[i + 1] = (asum[i] + a[i]) % MOD;

	int cnt = 0;
	rep(i, m){
		const int CNT = 1;
		int t, l, r;
		cin >> t >> l >> r;
		l--;
		if (t == 1){
			L[cnt] = l, R[cnt] = r;
			(add[l] += 1) %= MOD;
			(add[r] += MOD - fib[r - l - 1]) %= MOD;
			if (r - l > 1) (add[r + 1] += MOD - fib[r - l - 2]) %= MOD;

			if (++cnt == CNT){
				rep(i, n){
					(add[i + 1] += add[i]) %= MOD;
					(add[i + 2] += add[i]) %= MOD;
				}
				rep(i, n){
					(asum[i + 1] += add[i]) %= MOD;
					(add[i + 1] += add[i]) %= MOD;
				}
				MEMSET(add, 0);
				cnt = 0;
			}
		}
		else{
			int res = (asum[r] - asum[l] + MOD) % MOD;
			rep(i, cnt){
				int nl = max(l, L[i]), nr = min(r, R[i]);
				if (nr > nl) (res += sum[nr - L[i]] - sum[nl - L[i]] + MOD) %= MOD;
			}
			cout << res << '\n';
		}

	}

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>

// BEGIN CUT HERE
#ifdef _MSC_VER
#include <agents.h>
#endif
// END CUT HERE

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define MP make_pair
#define MT make_tuple
#define X first
#define Y second

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

const int N = 3e5 + 10;
ll fib[N], sum[N];
ll a[N], asum[N];
ll add[N];

int L[N], R[N];

const ll MOD = 1e9 + 9;
const int CNT = sqrt(N) * 2;

int main(){
	ios::sync_with_stdio(false);
	int n, m;
	cin >> n >> m;

	rep(i, n) cin >> a[i];
	fib[0] = fib[1] = 1;
	FOR(i, 2, n) fib[i] = (fib[i - 1] + fib[i - 2]) % MOD;
	rep(i, n) sum[i + 1] = (sum[i] + fib[i]) % MOD;
	rep(i, n) asum[i + 1] = (asum[i] + a[i]) % MOD;

	int cnt = 0;
	rep(i, m){
		int t, l, r;
		cin >> t >> l >> r;
		l--;
		if (t == 1){
			L[cnt] = l, R[cnt] = r;
			(add[l] += 1) %= MOD;
			(add[r] += MOD - fib[r - l]) %= MOD;
			(add[r + 1] += MOD - fib[r - l - 1]) %= MOD;

			if (++cnt == CNT){
				rep(i, n){
					(add[i + 1] += add[i]) %= MOD;
					(add[i + 2] += add[i]) %= MOD;
				}
				rep(i, n){
					(asum[i + 1] += add[i]) %= MOD;
					(add[i + 1] += add[i]) %= MOD;
				}
				MEMSET(add, 0);
				cnt = 0;
			}
		}
		else{
			ll res = (asum[r] - asum[l] + MOD) % MOD;
			rep(i, cnt){
				int nl = max(l, L[i]), nr = min(r, R[i]);
				if (nr > nl) (res += sum[nr - L[i]] - sum[nl - L[i]] + MOD) %= MOD;
			}
			cout << res << '\n';
		}

	}

	return 0;
}


#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

typedef long long ll;

const int MOD = 1000000009, TOUR = 1<<19, MAX = 300100;

struct tour {
    int val, prop1, prop2;
} t[2*TOUR];

int pocmat[3][3] = {0, 1, 0,
                    1, 1, 0,
                    1, 1, 1};

int mat[MAX][3][3];

void mnoz(int a[3][3], int b[3][3], int c[3][3])
{
    int i, j, k;

    for (i=0; i<3; i++)
        for (j=0; j<3; j++) {
            c[i][j] = 0;
            for (k=0; k<3; k++)
                c[i][j] = (c[i][j] + (ll) a[i][k] * b[k][j]) % MOD;
        }
}

int pot(int poc1, int poc2, int eksp, int st) // 1 - zbroj, 0 - n-ti
{
    if (!eksp)
        return 0;

    if (eksp == 1)
        return poc1;

    if (!st)
        eksp++;
    eksp -= 2;

    if (st == 1)
        return (((ll) mat[eksp][2][0] * poc1 + (ll) mat[eksp][2][1] * poc2) % MOD + (ll) mat[eksp][2][2] * (poc1 + poc2)) % MOD;
    return ((ll) mat[eksp][0][0] * poc1 + (ll) mat[eksp][0][1] * poc2) % MOD;
}

void Prop(int node, int lo, int hi)
{
    int p1=t[node].prop1, p2=t[node].prop2, t1, t2;

    if (t[node].prop2) {
        t[2*node].prop1 = (t[2*node].prop1 + p1) % MOD;
        t[2*node].prop2 = (t[2*node].prop2 + p2) % MOD;
        t[2*node].val = ((ll) t[2*node].val + pot(p1, p2, (hi-lo) / 2, 1)) % MOD;
        t1 = pot(p1, p2, (hi-lo)/2 + 1, 0);
        t2 = pot(p1, p2, (hi-lo)/2 + 2, 0);
        t[2*node+1].prop1 = (t[2*node+1].prop1 + t1) % MOD;
        t[2*node+1].prop2 = (t[2*node+1].prop2 + t2) % MOD;
        t[2*node+1].val = ((ll) t[2*node+1].val + pot(t1, t2, (hi-lo)/2, 1)) % MOD;
    }

    t[node].prop1 = t[node].prop2 = 0;
}

void Stavi(int pos, int lo, int hi, int begin, int end, int p1, int p2)
{
    int poc1, poc2;

    if (lo >= end || hi <= begin)
        return;
    if (lo >= begin && hi <= end) {
        poc1 = pot(p1, p2, lo - begin + 1, 0);
        poc2 = pot(p1, p2, lo - begin + 2, 0);
        t[pos].prop1 = (t[pos].prop1 + poc1) % MOD;
        t[pos].prop2 = (t[pos].prop2 + poc2) % MOD;
        t[pos].val = (t[pos].val + pot(poc1, poc2, hi-lo, 1)) % MOD;
        return;
    }

    Prop(pos, lo, hi);

    Stavi(2*pos+0, lo, (lo+hi)/2, begin, end, p1, p2);
    Stavi(2*pos+1, (lo+hi)/2, hi, begin, end, p1, p2);
    t[pos].val = (t[2*pos+0].val + t[2*pos+1].val) % MOD;
}

int Vrati(int pos, int lo, int hi, int begin, int end)
{
    int r;

    if (lo >= end || hi <= begin)
        return 0;
    if (lo >= begin && hi <= end)
        return t[pos].val;

    Prop(pos, lo, hi);

    r = (Vrati(2*pos+0, lo, (lo+hi)/2, begin, end) +
         Vrati(2*pos+1, (lo+hi)/2, hi, begin, end)) % MOD;

    t[pos].val = (t[2*pos].val + t[2*pos+1].val) % MOD;

    return r;
}

int main()
{
    int n, q, i, st, tmp, l, r;

    for (i=0; i<3; i++)
        mat[0][i][i] = 1;

    for (i=1; i<MAX; i++)
        mnoz(mat[i-1], pocmat, mat[i]);

    scanf("%d%d", &n, &q);

    for (i=0; i<n; i++) {
        scanf("%d", &tmp);
        Stavi(1, 0, TOUR, i, i+1, tmp, tmp);
    }

    for (i=0; i<q; i++) {
        scanf("%d%d%d", &st, &l, &r); l--;
        if (st == 1)
            Stavi(1, 0, TOUR, l, r, 1, 1);
        else
            printf("%d\n", Vrati(1, 0, TOUR, l, r));
    }

    return 0;
}