#include<bits/stdc++.h>
#define int long long
using namespace std;
int read(){
	int c=0,nx,sign=1;
	do{
		nx=getchar()-'0';
		if(nx=='-'-'0')
			sign=-1;
	}while(nx<0 or nx>9);
	while(nx>=0 and nx<=9){
		c=c*10+nx;
		nx=getchar()-'0';
	}
	return sign*c;
}
const int N=5e5+10,mod=1e9+7;
int fib[2*N],a[N];
struct stree{
	int tot,a,b;
	stree *ls,*rs;
}c[4*N];
stree* New(){
	static int now=0;
	stree &s=c[++now];
	s.tot=s.a=s.b=0;
	s.ls=s.rs=c;
	return c+now;
}
inline int h(int a,int b,int x){
	if(x>=2)
		return (a*fib[x-2] + b*fib[x-1]) % mod;
	else
		return a;
}
inline void pd(stree &s,int a,int b,int l,int r){
	s.a = (s.a + a) % mod;
	s.b = (s.b + b) % mod;
	s.tot = (s.tot + h(a,b,r-l+3) - b + mod) % mod;
}
void pushdown(stree &s,int l,int r){
	if(!s.a and !s.b or l==r)
		return ;
	int mid=(l+r)>>1;
	int &a=s.a,&b=s.b;
	pd(*s.ls,a,b,l,mid);
	pd(*s.rs,h(a,b,mid+2-l),h(a,b,mid+3-l),mid+1,r);
	a=b=0;
}
inline void pushup(stree &s){
	s.tot = (s.ls->tot + s.rs->tot) % mod;
}
void add(int ql,int qr,stree &s,int l,int r){
	if(ql<=l and r<=qr){
		pd(s,fib[l-ql+1],fib[l-ql+2],l,r);
		return ;
	}
	pushdown(s,l,r);
	int mid=(l+r)>>1;
	if(ql<=mid)
		add(ql,qr,*s.ls,l,mid);
	if(qr>mid)
		add(ql,qr,*s.rs,mid+1,r);
	pushup(s);
}
int query(int ql,int qr,stree &s,int l,int r){
	if(ql<=l and r<=qr){
		return s.tot;
	}
	pushdown(s,l,r);
	int mid=(l+r)>>1,ans=0;
	if(ql<=mid)
		ans+=query(ql,qr,*s.ls,l,mid);
	if(qr>mid)
		ans+=query(ql,qr,*s.rs,mid+1,r);
	return ans % mod;
}
void build(stree &s,int l,int r){
	if(l==r){
		s.tot=a[l];
		return ;
	}
	s.ls = New();
	s.rs = New();
	int mid = (l + r) >> 1;
	build(*s.ls,l,mid);
	build(*s.rs,mid+1,r);
	pushup(s);
}

signed main(){
	fib[1]=1;
	for(int i=2;i<=1e6;i++)
		fib[i]=(fib[i-1] + fib[i-2]) % mod;

	int n=read(),t=read();
	for(int i=1;i<=n;i++)
		a[i]=read();

	stree &root=*New();
	build(root,1,n);

	while(t--){
		int ord=read(),l=read(),r=read();
		switch(ord){
			case 1:
				add(l,r,root,1,n);
				break;
			case 2:
				printf("%lld\n",query(l,r,root,1,n));
				break;
		}
//		cout<<'*';
//		for(int i=1;i<=n;i++)
//			cout<<query(i,i,root,1,n)<<' ';
//		cout<<endl;
	}
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ls (k << 1)
#define rs (k << 1 | 1)
#define L (T[k].l)
#define R (T[k].r)
#define Len (T[k].len)

using namespace std;
typedef long long LL;
const int p = 1e9+9;
const int N = 3e5+5;
int n, m;
struct Tree {
	LL sum, lay, tag;
	int l, r, len;
}T[N<<2];
LL f[N], a[N];

inline void update(int k) {	T[k].sum = (T[ls].sum + T[rs].sum) % p; }

inline void add(int k, LL a, LL b) {
	T[k].tag = (T[k].tag + a) % p;
	T[k].lay = (T[k].lay + b) % p;
	T[k].sum = (T[k].sum + a * f[Len] % p + b * f[Len + 1] % p - b) % p;
}

inline void pushdown(int k) {
	LL a = (T[k].tag * f[T[ls].len - 1] % p + T[k].lay * f[T[ls].len] % p) % p;
	LL b = (T[k].tag * f[T[ls].len] % p + T[k].lay * f[T[ls].len + 1] % p) % p;
	add(ls, T[k].tag, T[k].lay);
	add(rs, a, b);
	T[k].tag = T[k].lay = 0;
}

void build(int k, int l, int r) {
	T[k].l = l, T[k].r = r, T[k].len = r - l + 1;
	if(l == r) { T[k].sum = a[l] % p; return; }
	int mid = (l + r) >> 1;
	build(ls, l, mid), build(rs, mid + 1, r);
	update(k);
}

void Change(int k, int l, int r) {
	if(L >= l && R <= r) {
		add(k, f[L - l + 1], f[L - l + 2]);
		return;
	}
	if(T[k].tag) pushdown(k);
	int mid = (L + R) >> 1;
	if(l <= mid) Change(ls, l, r);
	if(r > mid) Change(rs, l, r);
	update(k);
}

LL query(int k ,int l, int r) {
	if(L >= l && R <= r) return T[k].sum;
	if(T[k].tag) pushdown(k);
	int mid = (L + R) >> 1;
	LL res = 0;
	if(l <= mid) res = (res + query(ls, l, r) % p) % p;
	if(r > mid) res = (res + query(rs, l, r) % p) % p;
	return res;
}

inline void init() {
	f[1] = f[2] = 1;
	for(int i = 3;i < N;++ i)
		f[i] = (f[i - 1] + f[i - 2]) % p;
}

int main() {
	// freopen("d.in", "r", stdin);
	// freopen("d.out", "w", stdout);
	init();
	scanf("%d%d", &n, &m);
	for(int i = 1;i <= n;++ i) scanf("%lld", &a[i]);
	build(1, 1, n);
	for(int i = 1, op, l, r, x;i <= m;++ i) {
		scanf("%d%d%d", &op, &l, &r);
		if(op == 2) printf("%lld\n", (query(1, l, r) + p) % p);
		if(op == 1) scanf("%d", &x), Change(1, l, r);
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}


#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
const ll mxn=1e6+5,mod=1e9+9;
ll n,m,cnt,a[mxn],hd[mxn];
ll f[mxn],tr[mxn<<2],vis[mxn<<2],tag[mxn<<2][2];

inline ll read() {
	char c=getchar(); ll x=0,f=1;
	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
	return x*f;
}
inline void chkmax(ll &x,ll y) {if(x<y) x=y;}
inline void chkmin(ll &x,ll y) {if(x>y) x=y;}

struct ed {
	ll to,nxt;
}t[mxn<<1];

inline void add(ll u,ll v) {
	t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}

void push_up(ll p) {
	tr[p]=(tr[ls]+tr[rs])%mod;
}

struct ST {
	ll x,y;
};

ST fibget(ST tp,ll len) {
	ll c=tp.x*f[len]%mod+tp.y*f[len+1]%mod,d=tp.x*f[len+1]%mod+tp.y*f[len+2]%mod;
	return (ST) {c%mod,d%mod};
}

ll fibcal(ll f1,ll f2,ll len) {
	ll res=0;
	if(len>=1) res=f1;
	if(len>=2) res=(res+f2)%mod;
	if(len>=3) res=(res+f2*(f[len+1]-2)%mod+f1*(f[len]-1)%mod+mod)%mod;
	//前两项的系数的值,直接乘以当前f[i+1],f[i],计算出f[i+2]
	return res;
}

void push_down(ll p,ll l,ll r) {
	ll mid=(l+r)>>1;
	if(vis[p]) {
		ll &a=tag[p][0],&b=tag[p][1];
		tag[ls][0]=(tag[ls][0]+a)%mod;
		tag[ls][1]=(tag[ls][1]+b)%mod;
		tr[ls]=(tr[ls]+fibcal(a,b,mid-l+1))%mod;
		vis[ls]=1;

		ll c=a*f[mid-l]+b*f[mid-l+1],d=a*f[mid-l+1]+b*f[mid-l+2];
		c%=mod; d%=mod;
		tag[rs][0]=(tag[rs][0]+c)%mod;
		tag[rs][1]=(tag[rs][1]+d)%mod;
		tr[rs]=(tr[rs]+fibcal(c,d,r-mid))%mod;
		vis[rs]=1;

		vis[p]=tag[p][0]=tag[p][1]=0;
	}
}

void build(ll l,ll r,ll p) {
	if(l==r) {tr[p]=a[l]; return ;}
	ll mid=(l+r)>>1;
	build(l,mid,ls); build(mid+1,r,rs); push_up(p);
}

void modify(ll l,ll r,ll ql,ll qr,ll val1,ll val2,ll p) {
	if(ql<=l&&r<=qr) {
		tag[p][0]=(tag[p][0]+val1)%mod;
		tag[p][1]=(tag[p][1]+val2)%mod;
		tr[p]=(tr[p]+fibcal(val1,val2,r-l+1))%mod;
		vis[p]=1; return ;
	}
	ll mid=(l+r)>>1; push_down(p,l,r);
	if(qr<=mid) modify(l,mid,ql,qr,val1,val2,ls);
	else if(ql>mid) modify(mid+1,r,ql,qr,val1,val2,rs);
	else {
		modify(l,mid,ql,qr,val1,val2,ls);
		ST z=fibget((ST){val1,val2},mid-ql);
		modify(mid+1,r,ql,qr,z.x,z.y,rs); //算出区间前两个fib,貌似也可以用前缀和
	}
	push_up(p);
}

ll query(ll l,ll r,ll ql,ll qr,ll p) {
	if(ql<=l&&r<=qr) return tr[p];
	ll mid=(l+r)>>1; push_down(p,l,r); ll res=0;
	if(ql<=mid) res=(res+query(l,mid,ql,qr,ls))%mod;
	if(qr>mid) res=(res+query(mid+1,r,ql,qr,rs))%mod;
	return res;
}

void init() {
	n=read(); m=read(); ll x,y,opt; f[1]=f[2]=1;
	for(ll i=3;i<=n+4;++i) f[i]=(f[i-1]+f[i-2])%mod;
	for(ll i=1;i<=n;++i) a[i]=read()%mod; build(1,n,1);
	for(ll i=1;i<=m;++i) {
		opt=read(); x=read(); y=read();
		if(opt==1) modify(1,n,x,y,1,1,1);
		else printf("%d\n",query(1,n,x,y,1));
	}
}

int main()
{
	init();
    return 0;
}


#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
const ll mxn=1e6+5,mod=1e9+9;
ll n,m,cnt,a[mxn],hd[mxn];
ll f[mxn],tr[mxn<<2],vis[mxn<<2],tag[mxn<<2][2];

inline ll read() {
	char c=getchar(); ll x=0,f=1;
	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
	return x*f;
}
inline void chkmax(ll &x,ll y) {if(x<y) x=y;}
inline void chkmin(ll &x,ll y) {if(x>y) x=y;}

struct ed {
	ll to,nxt;
}t[mxn<<1];

inline void add(ll u,ll v) {
	t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}

void push_up(ll p) {
	tr[p]=(tr[ls]+tr[rs])%mod;
}

struct ST {
	ll x,y;
};

ST fibget(ST tp,ll len) {
	ll c=tp.x*f[len]%mod+tp.y*f[len+1]%mod,d=tp.x*f[len+1]%mod+tp.y*f[len+2]%mod;
	return (ST) {c%mod,d%mod};
}

ll fibcal(ll f1,ll f2,ll len) {
	ll res=0;
	if(len>=1) res=f1;
	if(len>=2) res=(res+f2)%mod;
	if(len>=3) res=(res+f2*(f[len+1]-2)%mod+f1*(f[len]-1)%mod+mod)%mod;
	//前两项的系数的值,直接乘以当前f[i+1],f[i],计算出f[i+2]
	return res;
}

void push_down(ll p,ll l,ll r) {
	ll mid=(l+r)>>1;
	if(vis[p]) {
		ll &a=tag[p][0],&b=tag[p][1];
		tag[ls][0]=(tag[ls][0]+a)%mod;
		tag[ls][1]=(tag[ls][1]+b)%mod;
		tr[ls]=(tr[ls]+fibcal(a,b,mid-l+1))%mod;
		vis[ls]=1;

		ll c=a*f[mid-l]+b*f[mid-l+1],d=a*f[mid-l+1]+b*f[mid-l+2];
		c%=mod; d%=mod;
		tag[rs][0]=(tag[rs][0]+c)%mod;
		tag[rs][1]=(tag[rs][1]+d)%mod;
		tr[rs]=(tr[rs]+fibcal(c,d,r-mid))%mod;
		vis[rs]=1;

		vis[p]=tag[p][0]=tag[p][1]=0;
	}
}

void build(ll l,ll r,ll p) {
	if(l==r) {tr[p]=a[l]; return ;}
	ll mid=(l+r)>>1;
	build(l,mid,ls); build(mid+1,r,rs); push_up(p);
}

void modify(ll l,ll r,ll ql,ll qr,ll val1,ll val2,ll p) {
	if(ql<=l&&r<=qr) {
		tag[p][0]=(tag[p][0]+val1)%mod;
		tag[p][1]=(tag[p][1]+val2)%mod;
		tr[p]=(tr[p]+fibcal(val1,val2,r-l+1))%mod;
		vis[p]=1; return ;
	}
	ll mid=(l+r)>>1; push_down(p,l,r);
	if(qr<=mid) modify(l,mid,ql,qr,val1,val2,ls);
	else if(ql>mid) modify(mid+1,r,ql,qr,val1,val2,rs);
	else {
		modify(l,mid,ql,qr,val1,val2,ls);
		ST z=fibget((ST){val1,val2},mid-ql);
		modify(mid+1,r,ql,qr,z.x,z.y,rs); //算出区间前两个fib,貌似也可以用前缀和
	}
	push_up(p);
}

ll query(ll l,ll r,ll ql,ll qr,ll p) {
	if(ql<=l&&r<=qr) return tr[p];
	ll mid=(l+r)>>1; push_down(p,l,r); ll res=0;
	if(ql<=mid) res=(res+query(l,mid,ql,qr,ls))%mod;
	if(qr>mid) res=(res+query(mid+1,r,ql,qr,rs))%mod;
	return res;
}

void init() {
	n=read(); m=read(); ll x,y,opt; f[1]=f[2]=1;
	for(ll i=3;i<=n+4;++i) f[i]=(f[i-1]+f[i-2])%mod;
	for(ll i=1;i<=n;++i) a[i]=read()%mod; build(1,n,1);
	for(ll i=1;i<=m;++i) {
		opt=read(); x=read(); y=read();
		if(opt==1) modify(1,n,x,y,1,1,1);
		else printf("%lld\n",(query(1,n,x,y,1)+mod)%mod);
	}
}

int main()
{
	init();
    return 0;
}


#include<cstdio>
#define lson pos<<1
#define rson pos<<1|1
using namespace std;
const int maxn=3*1e5+10;
const int mod=1e9+9;
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
    int x=0,f=1;
    char ch=nc();
    while(ch<48){if(ch=='-')f=-1;ch=nc();}
    while(ch>47)    x=(((x<<2)+x)<<1)+ch-48,ch=nc();
    return x*f;
}
int n,m;
int a[maxn],sum[maxn],fib[maxn],ffib[maxn];
int tree[maxn<<2],add1[maxn<<2],add2[maxn<<2];
void fibonacci()
{
    fib[1]=fib[2]=sum[1]=ffib[1]=1;
    sum[2]=2;
    ffib[2]=mod-1;
    for(int i=3;i<=n+1;i++)
    {
        fib[i]=(fib[i-1]+fib[i-2])%mod;
        sum[i]=(sum[i-1]+fib[i])%mod;
        ffib[i]=(i&1)?fib[i]:mod-fib[i];
    }
}
void build(int pos,int l,int r)
{
    int mid=(l+r)>>1;
    if(l==r)
    {
        tree[pos]=a[l]%mod;
        return;
    }
    build(lson,l,mid);
    build(rson,mid+1,r);
    tree[pos]=(tree[lson]+tree[rson])%mod;
}
void mark(int pos,int l,int r,int a1,int a2)
{
    add1[pos]=(add1[pos]+a1)%mod;
    add2[pos]=(add2[pos]+a2)%mod;
    tree[pos]=(tree[pos]+1ll*(sum[r+1]-sum[l]+mod)%mod*a1%mod)%mod;
    tree[pos]=(tree[pos]+1ll*(sum[r]-sum[l-1]+mod)%mod*a2%mod)%mod;
}
void pushdown(int pos,int l,int r)
{
    int mid=(l+r)>>1;
    mark(lson,l,mid,add1[pos],add2[pos]);
    mark(rson,mid+1,r,add1[pos],add2[pos]);
    add1[pos]=add2[pos]=0;
}
void update(int pos,int l,int r,int x,int y,int a1,int a2)
{
    int mid=(l+r)>>1;
    if(x<=l && r<=y)
    {
        mark(pos,l,r,a1,a2);
        return;
    }
    pushdown(pos,l,r);
    if(x<=mid)
        update(lson,l,mid,x,y,a1,a2);
    if(y>mid)
        update(rson,mid+1,r,x,y,a1,a2);
    tree[pos]=(tree[lson]+tree[rson])%mod;
}
int query(int pos,int l,int r,int x,int y)
{
    int ret=0;
    int mid=(l+r)>>1;
    if(x<=l && r<=y)
        return tree[pos]%mod;
    pushdown(pos,l,r);
    if(x<=mid)
        ret=(ret+query(lson,l,mid,x,y))%mod;
    if(y>mid)
        ret=(ret+query(rson,mid+1,r,x,y))%mod;
    return ret%mod;
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    fibonacci();
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int opt,l,r;
        opt=read();l=read();r=read();
        if(opt==1)
            update(1,1,n,l,r,ffib[l-1],ffib[l]);
        else
            printf("%d\n",query(1,1,n,l,r));
    }
    return 0;
}


#include<bits/stdc++.h>
#define REP(i,first,last) for(int i=first;i<=last;++i)
#define DOW(i,first,last) for(int i=first;i>=last;--i)
using namespace std;
const int maxN=3e5+7;
const int mod=1e9+7;
int N,M;
int arr[maxN];
long long sum[maxN];
int Mod(long long a)
{
	a%=mod;
	a+=mod;
	a%=mod;
	return a;
}
int f[maxN];
int CalcNext(int fir,int sec,int len)
{
	if(len==1)
	{
		return fir;
	}
	if(len==2)
	{
		return sec;
	}
	return Mod(1ll*fir*f[len-2]+1ll*sec*f[len-1]);
}
int CalcSum(int fir,int sec,int len)
{
	if(len==1)
	{
		return fir;
	}
	if(len==2)
	{
		return Mod(fir+sec);
	}
	return Mod(CalcNext(fir,sec,len+2)-sec);
}
struct Tree
{
	long long sum;
	long long first,second;
}tree[maxN*4];
#define LSON (now<<1)
#define RSON (now<<1|1)
#define MIDDLE ((left+right)>>1)
#define LEFT LSON,left,MIDDLE
#define RIGHT RSON,MIDDLE+1,right
#define NOW now_left,now_right
void PushUp(int now)
{
	tree[now].sum=Mod(tree[LSON].sum+tree[RSON].sum);
}
void Build(int now=1,int left=1,int right=N)
{
	if(left==right)
	{
		tree[now].sum=arr[left];
		return;
	}
	Build(LEFT);
	Build(RIGHT);
	PushUp(now);
}
#define LEN (right-left+1)
void Down(int now,int left,int right,int add_first,int add_second)
{
	tree[now].first=Mod(tree[now].first+add_first);
	tree[now].second=Mod(tree[now].second+add_second);
	tree[now].sum=Mod(tree[now].sum+CalcSum(add_first,add_second,LEN));
}
#undef LEN
#define TWO tree[now].first,tree[now].second
void PushDown(int now,int left,int right)
{
	Down(LEFT,TWO);
	Down(RIGHT,CalcNext(TWO,MIDDLE-left+2),CalcNext(TWO,MIDDLE-left+3));
	tree[now].first=tree[now].second=0;
}
#undef TWO
#define LEN (left-now_left+1)
void Updata(int now_left,int now_right,int now=1,int left=1,int right=N)
{
	if(right<now_left||now_right<left)
	{
		return;
	}
	if(now_left<=left&&right<=now_right)
	{
		Down(now,left,right,f[LEN],f[LEN+1]);
		return;
	}
	PushDown(now,left,right);
	Updata(NOW,LEFT);
	Updata(NOW,RIGHT);
	PushUp(now);
}
int Query(int now_left,int now_right,int now=1,int left=1,int right=N)
{
	if(right<now_left||now_right<left)
	{
		return 0;
	}
	if(now_left<=left&&right<=now_right)
	{
		return tree[now].sum;
	}
	PushDown(now,left,right);
	int result=Mod(Query(NOW,LEFT)+Query(NOW,RIGHT));
	PushUp(now);
	return result;
}
int main()
{
//	freopen("data.in","r",stdin);
//	freopen("data.out","w",stdout);
	scanf("%d%d",&N,&M);
	REP(i,1,N)
	{
		scanf("%d",&arr[i]);
	}
	Build();
	f[1]=f[2]=1;
	REP(i,3,N+2)
	{
		f[i]=Mod(f[i-1]+f[i-2]);
	}
	int op,left,right;
	REP(i,1,M)
	{
		scanf("%d%d%d",&op,&left,&right);
		if(op==1)
		{
			Updata(left,right);
		}
		if(op==2)
		{
			printf("%d\n",Query(left,right));
		}
	}
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define pll pair<ll,ll>
#define mp make_pair
#define fst first
#define snd second
using namespace std;
const int N=3e5+10;
const ll P=1e9+7;
ll fib[N];
ll a[N<<2],ta[N<<2],tb[N<<2];
inline void getfib(int n){
	fib[1]=fib[2]=1;
	for(int i=3;i<=n;++i)
		(fib[i]=fib[i-1]+fib[i-2])%=P;
}
inline ll sum(ll pa,ll pb,int len){
	ll res=0;
	if(len>=1)(res+=pa)%=P;
	if(len>=2)(res+=pb)%=P;
	if(len>=3)(res+=pa*(fib[len]-1)%P+pb*(fib[len+1]-2)%P)%=P;
	return res;
}
inline pll get(ll pa,ll pb,int len){
	ll ppa=pa*fib[len]%P+pb*fib[len+1]%P;
	ll ppb=pa*fib[len+1]%P+pb*fib[len+2]%P;
	ppa%=P;ppb%=P;
	return mp(ppa,ppb);
}
void build(int r,int x,int y){
	if(x==y){
		scanf("%lld",&a[r]);
		a[r]%=P;
		return;
	}
	int m=(x+y)>>1;
	build(r<<1,x,m);
	build(r<<1|1,m+1,y);
	(a[r]=a[r<<1]+a[r<<1|1])%=P;
}
inline void update(int r,int x,int y){
	int m=(x+y)>>1;
	ll pa=ta[r],pb=tb[r];
	(a[r<<1]+=sum(pa,pb,m-x+1))%=P;
	(ta[r<<1]+=pa)%=P;
	(tb[r<<1]+=pb)%=P;
	ll ppa=pa*fib[m-x]%P+pb*fib[m-x+1]%P;
	ll ppb=pa*fib[m-x+1]%P+pb*fib[m-x+2]%P;
	ppa%=P;ppb%=P;
	(a[r<<1|1]+=sum(ppa,ppb,y-m))%=P;
	(ta[r<<1|1]+=ppa)%=P;
	(tb[r<<1|1]+=ppb)%=P;
	ta[r]=tb[r]=0;
}
void change(int r,int x,int y,int u,int v,ll pa,ll pb){
	if(u<=x&&y<=v){
		(a[r]+=sum(pa,pb,y-x+1))%=P;
		(ta[r]+=pa)%=P;
		(tb[r]+=pb)%=P;
		return;
	}
	if(ta[r]||tb[r])update(r,x,y);
	int m=(x+y)>>1;
	if(v<=m)change(r<<1,x,m,u,v,pa,pb);
	else if(u>m)change(r<<1|1,m+1,y,u,v,pa,pb);
	else{
		change(r<<1,x,m,u,m,pa,pb);
		pll p=get(pa,pb,m-u);
		change(r<<1|1,m+1,y,m+1,v,p.fst,p.snd);
	}
	(a[r]=a[r<<1]+a[r<<1|1])%=P;
}
ll query(int r,int x,int y,int u,int v){
	if(u<=x&&y<=v)return a[r];
	if(ta[r]||tb[r])update(r,x,y);
	int m=(x+y)>>1;ll res=0;
	if(u<=m)(res+=query(r<<1,x,m,u,v))%=P;
	if(m<v)(res+=query(r<<1|1,m+1,y,u,v))%=P;
	return res;
}
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	getfib(n+4);
	build(1,1,n);
	while(m--){
		int t,x,y;
		scanf("%d%d%d",&t,&x,&y);
		if(t==1)change(1,1,n,x,y,1,1);
		else printf("%lld\n",query(1,1,n,x,y));
	}
	return 0;
}


//you_std.cpp
//Code by Qriskno
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define clar(a, b) memset((a), (b), sizeof(a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug(s) debug("The massage in line %d, Function %s: %s\n", __LINE__, __FUNCTION__, s)
typedef long long LL;
typedef long double LD;
int read() {
    char ch = getchar();
    int x = 0, flag = 1;
    for(;!isdigit(ch); ch = getchar()) if(ch == '-') flag *= -1;
    for(;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    return x * flag;
}
void write(int x) {
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar(x % 10 + 48);
}

#define Maxn 300009
const LL Mod = (LL)(1e9 + 9);
int n, a[Maxn], m; LL f[Maxn];
struct node { LL x, y; };
LL FibDelta(LL F1, LL F2, LL len) {
    LL res = 0;
    if(len >= 1) (res += F1) %= Mod;
    if(len >= 2) (res += F2) %= Mod;
    if(len >= 3) (res += (F2 * (f[len + 1] - 2ll) % Mod + F1 * (f[len] - 1ll) % Mod) % Mod) %= Mod;
    return res;
}// needs to be analyzed in different conditions
node FibForward(node s, int len) {
    LL c = s.x * f[len] % Mod + s.y * f[len + 1] % Mod, d = s.x * f[len + 1] % Mod + s.y * f[len + 2] % Mod;
    return (node){c % Mod, d % Mod};
}
namespace SGMT_tree {
    LL tree[Maxn << 2], beg[Maxn << 2][2], val[Maxn << 2];
#define lc(x) (x) << 1
#define rc(x) (x) << 1 | 1
#define ls rt << 1, l, mid
#define rs rt << 1 | 1, mid + 1, r
    void pushup(int rt) { tree[rt] = (1ll * tree[lc(rt)] + 1ll * tree[rc(rt)]) % Mod; }
    void pushdown(int rt, int l, int r) {
        int mid = (l + r) >> 1;
        if(val[rt]) {
            LL &a = beg[rt][0], &b = beg[rt][1];
			printf("%d %d\n",beg[rt][0],beg[rt][1]);
            (beg[lc(rt)][0] += a) %= Mod, (beg[lc(rt)][1] += b) %= Mod;
            (tree[lc(rt)] += FibDelta(a, b, mid - l + 1)) %= Mod;
            val[lc(rt)] = 1;

            LL c = a * f[mid - l] + b * f[mid - l + 1], d = a * f[mid - l + 1] + b * f[mid - l + 2];
            c %= Mod, d %= Mod;
            (beg[rc(rt)][0] += c) %= Mod, (beg[rc(rt)][1] += d) %= Mod;
            (tree[rc(rt)] += FibDelta(c, d, r - mid)) %= Mod;
            val[rc(rt)] = 1;
            beg[rt][0] = beg[rt][1] = 0;
            val[rt] = 0;
//			printf("%d %d %d %d %d %d %d \n",beg[rt][0],beg[rt][1],tree[rt],beg[lc(rt)][0],beg[lc(rt)][1],beg[rc(rt)][0],beg[rc(rt)][1]);
//			printf("%d %d %d %d\n",&a,&b,c,d);
        }
    }
    void build(int rt, int l, int r) {
        if(l == r) {
            tree[rt] = a[l];
            return ;
        }
        int mid = (l + r) >> 1;
        build(ls), build(rs);
        pushup(rt);
    }
    void modify(int rt, int l, int r, int x, int y, int p1, int p2) {
		//printf("%d %d %d %d %d %d %d\n",rt,l,r,x,y,p1,p2);
        if(x <= l && r <= y) {
            (beg[rt][0] += p1) %= Mod, (beg[rt][1] += p2) %= Mod;
            (tree[rt] += FibDelta(p1, p2, r - l + 1)) %= Mod;
            val[rt] = 1;
            return ;
        }

        int mid = (l + r) >> 1;
        pushdown(rt, l, r);

        if(y <= mid)  modify(ls, x, y, p1, p2);
        else if(mid + 1 <= x)  modify(rs, x, y, p1, p2);
        else {
            modify(ls, x, mid, p1, p2); /**/
            node z = FibForward((node){p1, p2}, mid - x);/**/
            //F[i] -> F[i + mid - x]: p1 -> z.x, p2 -> z.y
            modify(rs, mid + 1, y, z.x, z.y);/*The InterVal's Range needs to be moved*/
        }
        pushup(rt);
    }
    int query(int rt, int l, int r, int x, int y) {
		//printf("%d %d %d %d %d %d\n",rt,l,r,x,y,tree[rt]);
        if(x <= l && r <= y) return tree[rt];

        int mid = (l + r) >> 1; pushdown(rt, l, r);

        if(y <= mid) return query(ls, x, y);
        else if(mid + 1 <= x) return query(rs, x, y);
        else return (1ll * query(ls, x, y) + 1ll * query(rs, x, y)) % Mod;
    }
#undef lc
#undef rc
#undef ls
#undef rs
}
namespace INIT {
    void Main() {
        n = read(), m = read();

        f[1] = 1; f[2] = 1;
        rep(i, 3, n + 4) f[i] = (f[i - 1] * 1ll + f[i - 2]) % Mod;

        rep(i, 1, n) a[i] = read() % Mod;

        SGMT_tree :: build(1, 1, n);
    }
}
namespace SOLVE {
    void Main() {
        rep(i, 1, m) {
            int opt = read();

            if(opt == 1) {
                int x = read(), y = read();
                SGMT_tree :: modify(1, 1, n, x, y, 1, 1);
            }
            if(opt == 2) {
                int x = read(), y = read();
                write(SGMT_tree :: query(1, 1, n, x, y) % Mod), putchar('\n');
            }
        }
    }
}
int main() {
//	freopen("you.in", "r", stdin);
//	freopen("you_std.out", "w", stdout);

    INIT :: Main();
    SOLVE :: Main();
#ifdef Qrsikno
    debug("\nRunning time: %.3lf(s)\n", clock() * 1.0 / CLOCKS_PER_SEC);
#endif
    return 0;
}


#include<iostream>
#include<cstring>
#include<cstdio>
#define int long long
using namespace std;
const int mod=1e9+9;
const int N=500005;
inline int read()
{
    register int x=0,y=1;register char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')y=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*y;
}
struct node
{
	int f1;
	int f2;
	int sum;
}tr[N<<2];
int a[N],sum[N];
int f[N];
int n,m;
void init()
{
	f[1]=1;f[2]=1;
	for(int i=3;i<=N-1;i++) f[i]=(f[i-1]+f[i-2])%mod;
}
void up(int k,int len)
{tr[k].f1%=mod,tr[k].f2%=mod,tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum+(tr[k].f1*f[len]%mod+tr[k].f2*f[len+1]%mod-tr[k].f2)%mod;}
void down(int k,int l,int r)
{
	if(tr[k].f1==0&&tr[k].f2==0) return;
	int mid=(l+r)>>1;
	tr[k<<1].f1+=tr[k].f1;
	tr[k<<1].f1%=mod;
	tr[k<<1].f2+=tr[k].f2;
	tr[k<<1].f2%=mod;
	tr[k<<1|1].f1+=tr[k].f1*f[mid-l]%mod+tr[k].f2*f[mid-l+1]%mod;
	tr[k<<1|1].f1%=mod;
	tr[k<<1|1].f2+=tr[k].f1*f[mid-l+1]%mod+tr[k].f2*f[mid-l+2]%mod;
	tr[k<<1|1].f2%=mod;
	tr[k].f1=0;tr[k].f2=0;
	up(k<<1,mid-l+1);up(k<<1|1,r-mid);
}
void change(int k,int l,int r,int ql,int qr)
{
	if(ql<=l&&r<=qr)
	{
		tr[k].f1+=f[l-ql+1];
		tr[k].f2+=f[l-ql+2];
		tr[k].f1%=mod;
		tr[k].f2%=mod;
		up(k,r-l+1);
		return;
	}
	down(k,l,r);
	int mid=(l+r)>>1;
	if(ql<=mid) change(k<<1,l,mid,ql,qr);
	if(mid<qr) change(k<<1|1,mid+1,r,ql,qr);
	up(k,r-l+1);
}
int query(int k,int l,int r,int ql,int qr)
{
	if(l>=ql&&r<=qr) return tr[k].sum;
	down(k,l,r);
	int mid=(l+r)>>1;
	int res=0;
	if(ql<=mid) res+=query(k<<1,l,mid,ql,qr);
	if(mid<qr) res+=query(k<<1|1,mid+1,r,ql,qr);
	return res;
}
signed main()
{
	n=read();m=read();
	init();
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=1;i<=n;i++) sum[i]=(sum[i-1]+a[i])%mod;
	for(int i=1;i<=m;i++)
    {
        int opt,l,r;
       opt=read();l=read();r=read();
        if(opt==1)change(1,1,n,l,r);
        else printf("%lld\n",(query(1,1,n,l,r)+sum[r]-sum[l-1]+mod)%mod);
    }
}


#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
const ll mxn=1e6+5,mod=1e9+9;
ll n,m,cnt,a[mxn],hd[mxn];
ll f[mxn],tr[mxn<<2],vis[mxn<<2],tag[mxn<<2][2];

inline ll read() {
	char c=getchar(); ll x=0,f=1;
	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
	return x*f;
}
inline void chkmax(ll &x,ll y) {if(x<y) x=y;}
inline void chkmin(ll &x,ll y) {if(x>y) x=y;}

struct ed {
	ll to,nxt;
}t[mxn<<1];

inline void add(ll u,ll v) {
	t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}

void push_up(ll p) {
	tr[p]=(tr[ls]+tr[rs])%mod;
}

struct ST {
	ll x,y;
};

ST fibget(ST tp,ll len) {
	ll c=tp.x*f[len]%mod+tp.y*f[len+1]%mod,d=tp.x*f[len+1]%mod+tp.y*f[len+2]%mod;
	return (ST) {c%mod,d%mod};
}

ll fibcal(ll f1,ll f2,ll len) {
	ll res=0;
	if(len>=1) res=f1;
	if(len>=2) res=(res+f2)%mod;
	if(len>=3) res=(res+f2*(f[len+1]-2)%mod+f1*(f[len]-1)%mod+mod)%mod;
	//前两项的系数的值,直接乘以当前f[i+1],f[i],计算出f[i+2]
	return res;
}

void push_down(ll p,ll l,ll r) {
	ll mid=(l+r)>>1;
	if(vis[p]) {
		ll &a=tag[p][0],&b=tag[p][1];
		tag[ls][0]=(tag[ls][0]+a)%mod;
		tag[ls][1]=(tag[ls][1]+b)%mod;
		tr[ls]=(tr[ls]+fibcal(a,b,mid-l+1))%mod;
		vis[ls]=1;

		ll c=a*f[mid-l]+b*f[mid-l+1],d=a*f[mid-l+1]+b*f[mid-l+2];
		c%=mod; d%=mod;
		tag[rs][0]=(tag[rs][0]+c)%mod;
		tag[rs][1]=(tag[rs][1]+d)%mod;
		tr[rs]=(tr[rs]+fibcal(c,d,r-mid))%mod;
		vis[rs]=1;

		vis[p]=tag[p][0]=tag[p][1]=0;
	}
}

void build(ll l,ll r,ll p) {
	if(l==r) {tr[p]=a[l]; return ;}
	ll mid=(l+r)>>1;
	build(l,mid,ls); build(mid+1,r,rs); push_up(p);
}

void modify(ll l,ll r,ll ql,ll qr,ll val1,ll val2,ll p) {
	if(ql<=l&&r<=qr) {
		tag[p][0]=(tag[p][0]+val1)%mod;
		tag[p][1]=(tag[p][1]+val2)%mod;
		tr[p]=(tr[p]+fibcal(val1,val2,r-l+1))%mod;
		vis[p]=1; return ;
	}
	ll mid=(l+r)>>1; push_down(p,l,r);
	if(qr<=mid) modify(l,mid,ql,qr,val1,val2,ls);
	else if(ql>mid) modify(mid+1,r,ql,qr,val1,val2,rs);
	else {
		modify(l,mid,ql,qr,val1,val2,ls);
		ST z=fibget((ST){val1,val2},mid-ql);
		modify(mid+1,r,ql,qr,z.x,z.y,rs); //算出区间前两个fib,貌似也可以用前缀和
	}
	push_up(p);
}

ll query(ll l,ll r,ll ql,ll qr,ll p) {
	if(ql<=l&&r<=qr) return tr[p];
	ll mid=(l+r)>>1; push_down(p,l,r); ll res=0;
	if(ql<=mid) res=(res+query(l,mid,ql,qr,ls))%mod;
	if(qr>mid) res=(res+query(mid+1,r,ql,qr,rs))%mod;
	return res;
}

void init() {
	n=read(); m=read(); ll x,y,opt; f[1]=f[2]=1;
	for(ll i=3;i<=n+4;++i) f[i]=(f[i-1]+f[i-2])%mod;
	for(ll i=1;i<=n;++i) a[i]=read()%mod; build(1,n,1);
	for(ll i=1;i<=m;++i) {
		opt=read(); x=read(); y=read();
		if(opt==1) modify(1,n,x,y,1,1,1);
		else printf("%lld\n",query(1,n,x,y,1));
	}
}

int main()
{
	init();
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=300005;
const int mod=1e9+9;
const int sq=383008016;
const int isq=276601605;
const int A=691504013;
const int B=308495997;
int n,m;
int poa[N],pob[N];
struct sgt{
	int l,r,ls,rs;
	int tag1,tag2,sum1,sum2;
}s[3*N];
int P,rt;
int a[N];
inline int get1(int p){
	return (s[p].sum1+ll(poa[s[p].r-s[p].l+1]-1)*A%mod*s[p].tag1)%mod;
}
inline int get2(int p){
	return (s[p].sum2+ll(pob[s[p].r-s[p].l+1]-1)*B%mod*s[p].tag2)%mod;
}
inline void pushd(int p){
	int len=s[s[p].ls].r-s[s[p].ls].l+1;
	s[s[p].rs].tag1=(s[s[p].rs].tag1+poa[len]*ll(s[p].tag1))%mod;
	s[s[p].rs].tag2=(s[s[p].rs].tag2+pob[len]*ll(s[p].tag2))%mod;
	s[s[p].ls].tag1=(s[s[p].ls].tag1+s[p].tag1)%mod;
	s[s[p].ls].tag2=(s[s[p].ls].tag2+s[p].tag2)%mod;
	s[p].sum1=get1(p);
	s[p].sum2=get2(p);
	s[p].tag1=s[p].tag2=0;
}
inline void upd(int p){
	s[p].sum1=(get1(s[p].ls)+get1(s[p].rs))%mod;
	s[p].sum2=(get2(s[p].ls)+get2(s[p].rs))%mod;
}
int build(int l,int r){
	int p=++P;
	s[p].l=l;s[p].r=r;
	if(l==r){
		s[p].sum1=a[l];
		return p;
	}
	int mid=(l+r)>>1;
	s[p].ls=build(l,mid);
	s[p].rs=build(mid+1,r);
	upd(p);
	return p;
}
void chg(int p,int l,int r,int x1,int x2){
	if(s[p].l==l&&s[p].r==r){
		s[p].tag1=(s[p].tag1+x1)%mod;
		s[p].tag2=(s[p].tag2+x2)%mod;
		return;
	}
	pushd(p);
	int mid=(s[p].l+s[p].r)>>1;
	if(r<=mid) chg(s[p].ls,l,r,x1,x2);
	else if(l>mid) chg(s[p].rs,l,r,x1,x2);
	else{
		chg(s[p].ls,l,mid,x1,x2);
		x1=ll(x1)*poa[mid-l+1]%mod;
		x2=ll(x2)*pob[mid-l+1]%mod;
		chg(s[p].rs,mid+1,r,x1,x2);
	}
	upd(p);
}
int qry(int p,int l,int r){
	if(s[p].l==l&&s[p].r==r){
		return (get1(p)-get2(p))%mod;
	}
	pushd(p);
	int mid=(s[p].l+s[p].r)>>1;
	if(r<=mid) return qry(s[p].ls,l,r);
	else if(l>mid) return qry(s[p].rs,l,r);
	else return (qry(s[p].ls,l,mid)+qry(s[p].rs,mid+1,r))%mod;
}
int main(){
	int i,j;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++) scanf("%d",&a[i]);
	poa[0]=pob[0]=1;
	for(i=1;i<N;i++){
		poa[i]=poa[i-1]*ll(A)%mod;
		pob[i]=pob[i-1]*ll(B)%mod;
	}
	rt=build(1,n);
	int op,x,y;
	while(m--){
		scanf("%d%d%d",&op,&x,&y);
		if(op==1)
			chg(rt,x,y,isq*ll(A)%mod,isq*ll(B)%mod);
		else printf("%lld\n",qry(rt,x,y));
	//	for(i=1;i<=n;i++) cout<<qry(rt,i,i)<<" ";
	//	cout<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>

namespace Tethys{
	inline long long read(){
		long long s = 0, f = 1; char ch;
		while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
		for(s = ch ^ 48; isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
		return (s *= f);
	}
}

#define ls(o) (o << 1)
#define rs(o) (o << 1 | 1)
#define mid ((l + r) >> 1)

using namespace std;
using namespace Tethys;
const int N = 1e5 + 5, mod = 1e9 + 9;

int n, m;
long long lst[3], tr[N << 2];

struct node{
	long long a[2][2];
}s, ss, ans;

node mul(node op, node opp){
	node res;
	for(int i = 0; i < 2; i ++){
		for(int j = 0; j < 2; j ++) res.a[i][j] = 0;
	}
	for(int i = 0; i < 2; i ++){
		for(int j = 0; j < 2; j ++){
			for(int k = 0; k < 2; k ++){
				res.a[i][j] = (res.a[i][j] + op.a[i][k] * opp.a[k][j] % mod) % mod;
			}
		}
	}
	return res;
}

long long calc(int x){
	s.a[1][1] = s.a[0][1] = 0; s.a[0][0] = s.a[1][0] = 1;
	ss.a[0][0] = ss.a[0][1] = ss.a[1][0] = 1; ss.a[1][1] = 0;
	x --;
	while(x){
		if(x & 1) s = mul(s, ss);
		ss = mul(ss, ss);
		x >>= 1;
	}
	return s.a[1][0];
}

void up(int o){ tr[o] = (tr[ls(o)] + tr[rs(o)]) % mod;}

void build(int o, int l, int r){
	if(l == r){ tr[o] = read(); return ;}
	build(ls(o), l, mid); build(rs(o), mid + 1, r);
	up(o);
}

void change(int o, int l, int r, int x, long long val){
	if(l == r){
		tr[o] = (tr[o] + val) % mod;
		return ;
	}
	if(x <= mid) change(ls(o), l, mid, x, val);
	else change(rs(o), mid + 1, r, x, val);
	up(o);
}

long long query(int o, int l, int r, int L, int R){
	if(L <= l && r <= R) return tr[o];
	long long res = 0;
	if(L <= mid) res = (res + query(ls(o), l, mid, L, R)) % mod;
	if(R > mid) res = (res + query(rs(o), mid + 1, r, L, R)) % mod;
	return res % mod;
}

signed main(){
	// freopen("d.in","r",stdin); freopen("d.out","w",stdout);
	n = read(); m = read(); build(1, 1, n);
	for(int i = 1, opt, l, r, x; i <= m; i ++){
		opt = read(); l = read(); r = read();
		if(l > r) swap(l, r);
		if(opt == 2) printf("%lld\n", query(1, 1, n, l, r) % mod);
		else{
			lst[0] = calc(1);
			if(l == r) change(1, 1, n, l, lst[0]);
			else{
				change(1, 1, n, l, lst[0]);
				lst[1] = calc(2); change(1, 1, n, l + 1, lst[1]);
				for(int j = l + 2; j <= r; j ++){
					lst[(j - l) & 1] = (lst[0] + lst[1]) % mod;
					change(1, 1, n, j, lst[(j - l) & 1]);
				}
			}
		}
	}
	fclose(stdin); fclose(stdout);
	return 0;
}


#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdalign>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif
#define int long long
#pragma GCC optimize(3)
using namespace std;
const int mod=1e9+9;
int n,m,fib[300010]={0,1},fibs[300010]={0,1},a[300010],sum[2400010],add[2400010][2];
int cal(int l,int r){
    return (fibs[r]-fibs[l-1]+mod)%mod;
}
void build(int k,int l,int r){
    if(l==r){
        sum[k]=a[l];
        return;
    }
    int mid=(l+r)/2;
    build(2*k,l,mid);
    build(2*k+1,mid+1,r);
    sum[k]=(sum[2*k]+sum[2*k+1])%mod;
}
void push_down(int k,int l,int r){
    if(!add[k][0]||l==r) return;
    int mid=(l+r)/2;
//	printf("%lld %lld %lld\n",k,add[k][0],add[k][1]);
    sum[2*k]=(sum[2*k]+cal(add[k][0],add[k][0]+mid-l))%mod;
    add[2*k][0]=add[k][0];
    add[2*k][1]=add[k][0]+mid-l;
//	printf("%lld %lld %lld\n",2*k,add[2*k][0],add[2*k][1]);
    sum[2*k+1]=(sum[2*k+1]+cal(add[k][0]+mid-l+1,add[k][1]))%mod;
    add[2*k+1][0]=add[k][0]+mid-l+1;
    add[2*k+1][1]=add[k][1];
    add[k][0]=add[k][1]=0;
}
int query(int k,int l,int r,int x,int y){
    push_down(k,l,r);
    if(x<=l&&r<=y) return sum[k];
    int mid=(l+r)/2,res=0;
    if(x<=mid) res=(res+query(k*2,l,mid,x,y))%mod;
    if(mid<y) res=(res+query(k*2+1,mid+1,r,x,y))%mod;
    return res;
}
void modify(int k,int l,int r,int x,int y){
    push_down(k,l,r);
    if(x<=l&&r<=y){
        add[k][0]=l-x+1;
        add[k][1]=r-x+1;
        sum[k]=(sum[k]+cal(add[k][0],add[k][1]));
//		printf("%lld\n",k);
        return;
    }
    int mid=(l+r)/2;
    if(x<=mid) modify(2*k,l,mid,x,y);
    if(mid<y) modify(2*k+1,mid+1,r,x,y);
    sum[k]=(sum[2*k]+sum[2*k+1])%mod;
}
signed main(){
    scanf("%lld %lld",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=2;i<=300000;i++) fib[i]=(fib[i-1]+fib[i-2])%mod,fibs[i]=(fibs[i-1]+fib[i])%mod;
    build(1,1,n);
    int x,y,z;
    for(int i=1;i<=m;i++){
        scanf("%lld %lld %lld",&x,&y,&z);
        if(x==1){
            modify(1,1,n,y,z);
            int k;
            srand(rand());
            for(int j=1;j<=100;j++) k=rand()%n+1,query(1,1,n,k,k);
		}
        else printf("%lld\n",query(1,1,n,y,z));
    }
    return 0;
}


#include <bits/stdc++.h>
#define ls u<<1
#define rs u<<1|1
using namespace std;
const int maxn = 3e5;
const int mod = 1e9+9;
int n, m, num, a[maxn+10], f[maxn+10], g[maxn+10], sum[maxn*4+10], tag[maxn*4+10][2];
void pushup(int u) {
	sum[u] = (sum[ls]+sum[rs])%mod;
}
void build(int u, int l, int r) {
	if (l == r) {
		sum[u] = a[l]; return;
	}
	int mid = (l+r)>>1;
	build(ls, l, mid);
	build(rs, mid+1, r);
	pushup(u);
}
void pushdown(int u, int l, int r) {
    //printf("%d %d %d : fuck -- %d %d %d\n", u, l, r, sum[u], tag[u][0], tag[u][1]);
	int mid = (l+r)/2, k;
	if (r-l <= 1) {
		(tag[ls][0] += tag[u][0]) %= mod;
        (tag[rs][0] += tag[u][1]) %= mod;
		(sum[ls] += tag[u][0]) %= mod;
        (sum[rs] += tag[u][1]) %= mod;
	} else {
		(tag[ls][0] += tag[u][0]) %= mod;
        (tag[ls][1] += tag[u][1]) %= mod;
		(tag[rs][0] += (1ll*f[mid-l]*tag[u][0]%mod+1ll*f[mid-l+1]*tag[u][1]%mod)%mod) %= mod;
		(tag[rs][1] += (1ll*f[mid-l+1]*tag[u][0]%mod+1ll*f[mid-l+2]*tag[u][1]%mod)) %= mod;
		(sum[ls] += (k = (1ll*f[mid-l+1]*tag[u][0]%mod+1ll*g[mid-l]*tag[u][1])%mod)) %= mod;
		(sum[rs] += ((1ll*f[r-l+1]*tag[u][0]%mod+1ll*g[r-l]*tag[u][1]%mod)%mod-k+mod)%mod) %= mod;
	}
    //printf("ls: %d %d %d\n", sum[ls], tag[ls][0], tag[ls][1]);
    //printf("rs: %d %d %d\n", sum[rs], tag[rs][0], tag[rs][1]);
	tag[u][0] = tag[u][1] = 0;
}
void update(int u, int l, int r, int L, int R) {
	//printf("%d %d %d %d %d : %d\n", u, l, r, L, R, num);
	if (L <= l && r <= R) {
		int d = r-l+1;
		(tag[u][0] += f[num]) %= mod;
		if (d > 1) (tag[u][1] += f[num+1]) %= mod;
		(sum[u] += (g[num+d-1]-g[num-1]+mod)%mod) %= mod;
		//printf("%d %d %d\n", sum[u], tag[u][0], tag[u][1]);
		num += d; return;
	}
	int mid = (l+r)>>1;
	pushdown(u, l, r);
	if (L <= mid) update(ls, l, mid, L, R);
	if (R > mid) update(rs, mid+1, r, L, R);
	pushup(u);
	//printf("%d %d: %d\n", l, r, sum[u]);
}
int query(int u, int l, int r, int L, int R) {
	//printf("%d %d %d:\n", u, l, r);
	//printf("%d %d %d\n", sum[u], tag[u][0], tag[u][1]);
	if (L <= l && r <= R) return sum[u];
	int mid = (l+r)>>1, res = 0;
	pushdown(u, l, r);
	if (L <= mid) (res += query(ls, l, mid, L, R)) %= mod;
	if (R > mid) (res += query(rs, mid+1, r, L, R)) %= mod;
	return res;
}
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1 ; i <= n; ++i)
		scanf("%d", &a[i]);
	f[1] = g[1] = 1;
	for (int i = 2; i <= maxn; ++i) {
		f[i] = (f[i-1]+f[i-2])%mod;
		g[i] = (g[i-1]+f[i])%mod;
	}
	build(1, 1, n);
	for (int i = 1; i <= m; ++i) {
		int opt, l, r;
		scanf("%d%d%d", &opt, &l, &r); num = 1;
		if (opt == 1) update(1, 1, n, l, r);
		else printf("%d\n", query(1, 1, n, l, r));
	}
	return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#define lson (2*id)
#define rson (2*id+1)
using namespace std;
const __int64 p=1000000009;
const __int64 q1=691504013,q2=308495997;
const __int64 k=276601605;
int n,Q;
__int64 a[300005],p1[300005],p2[300005];
__int64 sp1[300005],sp2[300005];
struct tree
{
    int l,r,len;
    __int64 s1,s2,first1,first2;
}tr[1200005];
void build(int l,int r,int id)
{
    tr[id].l=l;
    tr[id].r=r;
    tr[id].len=r-l+1;
    tr[id].first2=tr[id].first1=0;
    tr[id].s1=tr[id].s2=0;
    if(l!=r)
    {
        int mid=(tr[id].l+tr[id].r)/2;
        build(l,mid,lson);
        build(mid+1,r,rson);
    }
}
void pushdown(int id)
{
    if(tr[id].first1!=0)
    {
        __int64 t=tr[id].first1;
        tr[id].first1=0;
        tr[lson].s1=(tr[lson].s1+t*sp1[tr[lson].len-1])%p;
        tr[lson].first1=(tr[lson].first1+t)%p;
        tr[rson].s1=(tr[rson].s1+t*p1[tr[lson].len]%p*sp1[tr[rson].len-1])%p;
        tr[rson].first1=(tr[rson].first1+t*p1[tr[lson].len])%p;
    }
    if(tr[id].first2!=0)
    {
        __int64 t=tr[id].first2;
        tr[id].first2=0;
        tr[lson].s2=(tr[lson].s2+t*sp2[tr[lson].len-1])%p;
        tr[lson].first2=(tr[lson].first2+t)%p;
        tr[rson].s2=(tr[rson].s2+t*p2[tr[lson].len]%p*sp2[tr[rson].len-1])%p;
        tr[rson].first2=(tr[rson].first2+t*p2[tr[lson].len])%p;
    }
}
void update(int l,int r,int id,int x)
{
    if(tr[id].l>=l&&tr[id].r<=r)
    {
        int y=tr[id].l-l+x;
        tr[id].s1=(tr[id].s1+k*p1[y]%p*sp1[tr[id].len-1]%p)%p;
        tr[id].s2=(tr[id].s2+k*p2[y]%p*sp2[tr[id].len-1]%p)%p;
        tr[id].first1=(tr[id].first1+k*p1[y])%p;
        tr[id].first2=(tr[id].first2+k*p2[y])%p;
        return ;
    }
    pushdown(id);
    int mid=(tr[id].l+tr[id].r)/2;
    if(l<=mid) update(l,r,lson,x);
    if(r>mid) update(l,r,rson,x);
    tr[id].s1=(tr[lson].s1+tr[rson].s1)%p;
    tr[id].s2=(tr[lson].s2+tr[rson].s2)%p;
}
__int64 query(int l,int r,int id)
{
    if(tr[id].l>=l&&tr[id].r<=r) return ((tr[id].s1-tr[id].s2)+p)%p;
    pushdown(id);
    int mid=(tr[id].l+tr[id].r)/2;
    __int64 ans1=0,ans2=0;
    if(l<=mid) ans1=query(l,r,lson);
    if(r>mid) ans2=query(l,r,rson);
    return (ans1+ans2)%p;
}
void init()
{
    p1[0]=p2[0]=1;
    sp1[0]=sp2[0]=1;
    scanf("%d%d",&n,&Q);
    for(int i=1;i<=n;i++)
    {
        p1[i]=p1[i-1]*q1%p;
        p2[i]=p2[i-1]*q2%p;
        sp1[i]=(sp1[i-1]+p1[i])%p;
        sp2[i]=(sp2[i-1]+p2[i])%p;
    }
}
int main()
{
    init();
    a[0]=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%I64d",&a[i]);
        a[i]+=a[i-1];
    }
    build(1,n,1);
    while(Q--)
    {
        int op,l,r;
        scanf("%d%d%d",&op,&l,&r);
        if(op==1) update(l,r,1,1);
        else
        {
            __int64 v1=query(l,r,1),v2=((a[r]-a[l-1])+p)%p;
            printf("%I64d\n",(v1+v2)%p);
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 300000
#define MOD 1000000009
using namespace std;
int maxdel;
void read(long long &x)
{
	char ch=getchar(); x=0;
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
}

long long del[N+1],f[N+1],a[N+1],q[N+1][2],sum[N+1],d[N+1],sumf[N+1],tot=0,n,m;

void rebuild()
{
	memset(del,0,sizeof del);
	for (;tot>0;tot--)
	{
		(++del[q[tot][0]])%=MOD;
		(del[q[tot][1]+1]-=f[q[tot][1]-q[tot][0]+2]-MOD)%=MOD;
		(del[q[tot][1]+2]-=f[q[tot][1]-q[tot][0]+1]-MOD)%=MOD;
	}
	d[1]=del[1];
	for (int i=2;i<=n;i++) (del[i]+=(del[i-1]+del[i-2])%MOD)%=MOD,d[i]=(d[i-1]+del[i])%MOD;
	for (int i=1;i<=n;i++) (sum[i]+=d[i])%=MOD;
}

long long getans(long long l,long long r)
{
	long long s=0;
	for (int i=1;i<=tot;i++)
	{
		if (q[i][0]<l&&q[i][1]>=l&&q[i][1]<=r) (s+=sumf[q[i][1]-q[i][0]+1]-sumf[l-q[i][0]])%=MOD;
		else if (q[i][0]>=l&&q[i][0]<=r&&q[i][1]>r) (s+=sumf[r-q[i][0]+1])%=MOD;
		else if (q[i][0]>=l&&q[i][1]<=r&&q[i][0]<=q[i][1]) (s+=sumf[q[i][1]-q[i][0]+1])%=MOD;
		else if (q[i][0]<l&&q[i][1]>r) (s+=sumf[r-q[i][0]+1]-sumf[l-q[i][0]])%=MOD;
	}
	return (long long)((a[r]-a[l-1])+(sum[r]-sum[l-1])+s+(long long)MOD*100)%MOD;
}

int main()
{
	read(n),read(m);
	maxdel=pow(n,0.55);
	for (int i=1;i<=n;i++) read(a[i]),(a[i]+=a[i-1])%=MOD;
	f[1]=f[2]=1;
	for (int i=3;i<=n;i++) f[i]=(f[i-1]+f[i-2])%MOD;
	for (int i=1;i<=n;i++) sumf[i]=(sumf[i-1]+f[i])%MOD;
	long long L,R,ch;
	memset(sum,0,sizeof sum);
	for (;m>0;m--)
	{
		read(ch),read(L),read(R);
		if (ch==1){
			q[++tot][0]=L;q[tot][1]=R;
			if (tot>=maxdel) rebuild();
		}
		else
			printf("%lld\n",getans(L,R));
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define MOD 1000000007
long long tree[1200001],laz1[1200001],laz2[1200001],f[300011],g[300011],F[300011];
long long a1[300011],x,y,i,n,m,ans,opt;
void build(long long o,long long l,long long r){
	if(l==r){
		tree[o]=a1[l]%MOD;
		return;
	}
	long long mid=(l+r)>>1;
	build(o<<1,l,mid);
	build(o<<1|1,mid+1,r);
	tree[o]=(tree[o<<1]+tree[o<<1|1])%MOD;
}
void pushdown(long long o,long long ll){
	if(laz1[o]||laz2[o]){
		laz1[o<<1]=(laz1[o<<1]+laz1[o])%MOD;
		laz2[o<<1]=(laz2[o<<1]+laz2[o])%MOD;
		tree[o<<1]=(tree[o<<1]+F[ll-(ll>>1)-1]*laz1[o]+g[ll-(ll>>1)-1]*laz2[o])%MOD;
		int vaa=(f[ll-(ll>>1)]*laz2[o]+f[ll-(ll>>1)-1]*laz1[o])%MOD;
		int vbb=(f[ll-(ll>>1)+1]*laz2[o]+f[ll-(ll>>1)]*laz1[o])%MOD;
		tree[o<<1|1]=(tree[o<<1|1]+F[(ll>>1)-1]*vaa+g[(ll>>1)-1]*vbb)%MOD;
		laz1[o<<1|1]=(laz1[o<<1|1]+vaa)%MOD;
		laz2[o<<1|1]=(laz2[o<<1|1]+vbb)%MOD;
		laz1[o]=laz2[o]=0;
	}
}
void update(long long o,long long l,long long r,long long L,long long R,long long va,long long vb){
	if(L<=l&&r<=R){
		laz1[o]=(laz1[o]+va)%MOD;laz2[o]=(laz2[o]+vb)%MOD;
		tree[o]=(tree[o]+g[r-l]*vb+F[r-l]*va)%MOD;
		return;
	}
	long long mid=(l+r)>>1;
	pushdown(o,r-l+1);
	if(L<=mid) update(o<<1,l,mid,L,R,va,vb);
	if(mid<R){
		long long vaa=va;long long vbb=vb;
		if(L<=mid){
			    int len=mid-max(L,l)+1;
                vaa=(f[len]*vb +f[len-1]*va)%MOD;
                vbb=(f[len+1]*vb+f[len]*va)%MOD;
		}
		update(o<<1|1,mid+1,r,L,R,vaa,vbb);
	}
	tree[o]=(tree[o<<1]+tree[o<<1|1])%MOD;
}
void query(long long o,long long l,long long r,long long L,long long R){
	if(L<=l&&r<=R){
		ans=(ans+tree[o])%MOD;
		return;
	}
	long long mid=(l+r)>>1;
	pushdown(o,r-l+1);
	if(L<=mid) query(o<<1,l,mid,L,R);
	if(mid<R) query(o<<1|1,mid+1,r,L,R);
}
int main(){
	scanf("%lld%lld",&n,&m);
	for(i=1;i<=n;i++)
	  scanf("%lld",&a1[i]);
	f[1]=1;g[1]=1;F[0]=F[1]=1;
	for(i=2;i<=3000000;i++){
		f[i]=(f[i-1]+f[i-2])%MOD;
		g[i]=(g[i-1]+f[i])%MOD;
		F[i]=(F[i-1]+f[i-1])%MOD;
	}
	build(1,1,n);
	for(i=1;i<=m;i++){
		scanf("%lld%lld%lld",&opt,&x,&y);
		switch(opt){
			case 1:
				update(1,1,n,x,y,1,1);
				break;
			case 2:
				ans=0;
				query(1,1,n,x,y);
				printf("%lld\n",ans);
				break;
		}
	}
}


//you_std.cpp
//Code by Qriskno

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define clar(a, b) memset((a), (b), sizeof(a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug(s) debug("The massage in line %d, Function %s: %s\n", __LINE__, __FUNCTION__, s)
typedef long long LL;
typedef long double LD;
int read() {
    char ch = getchar();
    int x = 0, flag = 1;
    for(;!isdigit(ch); ch = getchar()) if(ch == '-') flag *= -1;
    for(;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    return x * flag;
}
void write(int x) {
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar(x % 10 + 48);
}

#define Maxn 300009
const LL Mod = (LL)(1e9 + 9);
int n, a[Maxn], m; LL f[Maxn];
struct node { LL x, y; };
LL FibDelta(LL F1, LL F2, LL len) {
    LL res = 0;
    if(len >= 1) (res += F1) %= Mod;
    if(len >= 2) (res += F2) %= Mod;
    if(len >= 3) (res += (F2 * (f[len + 1] - f[3]) % Mod + F1 * (f[len] - f[2]) % Mod) % Mod) %= Mod;
    return res;
}// needs to be analyzed in different conditions
node FibForward(node s, int len) {
    LL c = s.x * f[len] % Mod + s.y * f[len + 1] % Mod, d = s.x * f[len + 1] % Mod + s.y * f[len + 2] % Mod;
    return (node){c % Mod, d % Mod};
}
namespace SGMT_tree {
    LL tree[Maxn << 2], beg[Maxn << 2][2], val[Maxn << 2];
#define lc(x) (x) << 1
#define rc(x) (x) << 1 | 1
#define ls rt << 1, l, mid
#define rs rt << 1 | 1, mid + 1, r
    void pushup(int rt) { tree[rt] = (1ll * tree[lc(rt)] + 1ll * tree[rc(rt)]) % Mod; }
    void pushdown(int rt, int l, int r) {
        int mid = (l + r) >> 1;
        if(val[rt]) {
            LL &a = beg[rt][0], &b = beg[rt][1];
            (beg[lc(rt)][0] += a) %= Mod, (beg[lc(rt)][1] += b) %= Mod;
            (tree[lc(rt)] += FibDelta(a, b, mid - l + 1)) %= Mod;
            val[lc(rt)] = 1;

            LL c = a * f[mid - l] + b * f[mid - l + 1], d = a * f[mid - l + 1] + b * f[mid - l + 2];
            c %= Mod, d %= Mod;
            (beg[rc(rt)][0] += c) %= Mod, (beg[rc(rt)][1] += d) %= Mod;
            (tree[rc(rt)] += FibDelta(c, d, r - mid)) %= Mod;
            val[rc(rt)] = 1;
            beg[rt][0] = beg[rt][1] = 0;
            val[rt] = 0;
        }
    }
    void build(int rt, int l, int r) {
        if(l == r) {
            tree[rt] = a[l];
            return ;
        }
        int mid = (l + r) >> 1;
        build(ls), build(rs);
        pushup(rt);
    }
    void modify(int rt, int l, int r, int x, int y, int p1, int p2) {
        if(x <= l && r <= y) {
            (beg[rt][0] += p1) %= Mod, (beg[rt][1] += p2) %= Mod;
            (tree[rt] += FibDelta(p1, p2, r - l + 1)) %= Mod;
            val[rt] = 1;
            return ;
        }

        int mid = (l + r) >> 1;
        pushdown(rt, l, r);

        if(y <= mid)  modify(ls, x, y, p1, p2);
        else if(mid + 1 <= x)  modify(rs, x, y, p1, p2);
        else {
            modify(ls, x, mid, p1, p2); /**/
            node z = FibForward((node){p1, p2}, mid - x);/**/
            //F[i] -> F[i + mid - x]: p1 -> z.x, p2 -> z.y
            modify(rs, mid + 1, y, z.x, z.y);/*The InterVal's Range needs to be moved*/
        }
        pushup(rt);
    }
    int query(int rt, int l, int r, int x, int y) {
        if(x <= l && r <= y) return tree[rt];

        int mid = (l + r) >> 1; pushdown(rt, l, r);

        if(y <= mid) return query(ls, x, y);
        else if(mid + 1 <= x) return query(rs, x, y);
        else return (1ll * query(ls, x, y) + 1ll * query(rs, x, y)) % Mod;
    }
#undef lc
#undef rc
#undef ls
#undef rs
}
namespace INIT {
    void Main() {
        n = read(), m = read();

        f[1] = 1; f[2] = 1;
        rep(i, 3, n + 4) f[i] = (f[i - 1] * 1ll + f[i - 2]) % Mod;

        rep(i, 1, n) a[i] = read() % Mod;

        SGMT_tree :: build(1, 1, n);
    }
}
namespace SOLVE {
    void Main() {
        rep(i, 1, m) {
            int opt = read();

            if(opt == 1) {
                int x = read(), y = read();
                SGMT_tree :: modify(1, 1, n, x, y, 1, 1);
            }
            if(opt == 2) {
                int x = read(), y = read();
                write(SGMT_tree :: query(1, 1, n, x, y) % Mod), putchar('\n');
            }
        }
    }
}
int main() {
//	freopen("you.in", "r", stdin);
//	freopen("you.out", "w", stdout);

    INIT :: Main();
    SOLVE :: Main();
#ifdef Qrsikno
    debug("\nRunning time: %.3lf(s)\n", clock() * 1.0 / CLOCKS_PER_SEC);
#endif
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int mo=1e9+9,N=700000;
#define ll long long

int n,m;
ll s[N],f[N],P[N];

struct node
{
	ll tag1,tag2,sum1,sum2;
} t[N<<3];

void pushdown(int x,int l,int r)
{
	int ls=x<<1,rs=ls|1,mid=(l+r)>>1;
	t[ls].tag1=(t[ls].tag1+t[x].tag1)%mo;
	t[rs].tag1=(t[rs].tag1+t[x].tag1)%mo;
	t[ls].tag2=(t[ls].tag2+t[x].tag2)%mo;
	t[rs].tag2=(t[rs].tag2+t[x].tag2)%mo;
	t[ls].sum1=(t[ls].sum1+t[x].tag1*(P[mid+1+n]-P[l+n]+mo))%mo;
	t[rs].sum1=(t[rs].sum1+t[x].tag1*(P[n+1+r]-P[mid+1+n]+mo))%mo;
	t[ls].sum2=(t[ls].sum2+t[x].tag2*(P[mid+n]-P[l+n-1]+mo))%mo;
	t[rs].sum2=(t[rs].sum2+t[x].tag2*(P[n+r]-P[mid+n]+mo))%mo;
	t[x].tag1=t[x].tag2=0;
}

void pushup(int x)
{
	int ls=x<<1,rs=ls|1;
	t[x].sum1=(t[ls].sum1+t[rs].sum1)%mo;
	t[x].sum2=(t[ls].sum2+t[rs].sum2)%mo;
}

void update1(int i,int l,int r,int x,int y,int z)
{
	if (l>=x&&r<=y) {t[i].tag1=(t[i].tag1+z)%mo;t[i].sum1=(t[i].sum1+(ll)z*(P[r+n+1]-P[l+n]+mo))%mo;return;}
	int mid=(l+r)>>1;
	pushdown(i,l,r);
	if (mid>=x) update1(i<<1,l,mid,x,y,z);
	if (mid<y) update1(i<<1|1,mid+1,r,x,y,z);
	pushup(i);
}

void update2(int i,int l,int r,int x,int y,int z)
{
	if (l>=x&&r<=y) {t[i].tag2=(t[i].tag2+z)%mo;t[i].sum2=(t[i].sum2+(ll)z*(P[r+n]-P[l-1+n]+mo))%mo;return;}
	int mid=(l+r)>>1;
	pushdown(i,l,r);
	if (mid>=x) update2(i<<1,l,mid,x,y,z);
	if (mid<y) update2(i<<1|1,mid+1,r,x,y,z);
	pushup(i);
}

ll query(int i,int l,int r,int x,int y)
{
	if (l>=x&&r<=y) return (t[i].sum1+t[i].sum2)%mo;
	int mid=(l+r)>>1;
	pushdown(i,l,r);
	ll ans=0;
	if (mid>=x) ans=(ans+query(i<<1,l,mid,x,y))%mo;
	if (mid<y) ans=(ans+query(i<<1|1,mid+1,r,x,y))%mo;
	return ans;
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) {int x;scanf("%d",&x);s[i]=(s[i-1]+x)%mo;}
	f[n+1]=f[n+2]=1;
	for (int i=n;i>=0;i--) f[i]=(f[i+2]-f[i+1]+mo)%mo;
	for (int i=n+3;i<=n*2+1;i++) f[i]=(f[i-1]+f[i-2])%mo;
	P[0]=f[0];
	for (int i=1;i<=n*2+1;i++) P[i]=(P[i-1]+f[i])%mo;
	while (m--)
	{
		int opt,l,r;
		scanf("%d%d%d",&opt,&l,&r);
		if (opt==1) {update1(1,1,n,l,r,f[-l+1+n]);update2(1,1,n,l,r,f[n-l]);};
		if (opt==2) printf("%d\n",(query(1,1,n,l,r)+s[r]-s[l-1]+mo)%mo);
	}
}


#include<bits/stdc++.h>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
const ll mxn=3e5+5,mod=1e9+9;
struct T { ll x,y; };
ll n,m;
ll f[mxn],a[mxn],val[mxn<<2];
ll tag[mxn<<2][2],t[mxn<<2];

inline ll read()
{
	char c=getchar(); ll x=0,f=1;
	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}

inline void push_up(ll p)
{
	t[p]=(t[ls]+t[rs])%mod;
}

inline ll cal(ll x,ll y,ll len)
{
	ll res=0;
	if(len>=1) res=(res+x)%mod;
	if(len>=2) res=(res+y)%mod;
	if(len>=3) res=(res+y*(f[len+1]-2)%mod+x*(f[len]-1)%mod)%mod;
	return res;
}
T fibcal(T tp,ll len)
{
	ll c=tp.x*f[len]%mod+tp.y*f[len+1]%mod,
	   d=tp.x*f[len+1]%mod+tp.y*f[len+2]%mod;
	return (T){ c%mod,d%mod };
}

void build(ll l,ll r,ll p)
{
	if(l==r) {
		t[p]=a[l];
		return ;
	}
	ll mid=(l+r)>>1;
	build(l,mid,ls);
	build(mid+1,r,rs);
	push_up(p);
}

void push_down(ll l,ll r,ll p)
{
	if(val[p]) {
		ll mid=(l+r)>>1;

		ll x=tag[p][0],y=tag[p][1];
		tag[ls][0]=(tag[ls][0]+x)%mod;
		tag[ls][1]=(tag[ls][1]+y)%mod;
		t[ls]=(t[ls]+cal(x,y,mid-l+1))%mod;
		val[ls]=1;

		ll c=(x*f[mid-l]%mod+y*f[mid-l+1]%mod)%mod,
		   d=(x*f[mid-l+1]%mod+y*f[mid-l+2]%mod)%mod;
		tag[rs][0]=(tag[rs][0]+c)%mod;
		tag[rs][1]=(tag[rs][1]+d)%mod;
		t[rs]=(t[rs]+cal(c,d,r-mid))%mod;
		val[rs]=1;

		tag[p][0]=tag[p][1]=0; val[p]=0;
	}
}

void update(ll l,ll r,ll ql,ll qr,ll x,ll y,ll p)
{
	if(ql<=l&&r<=qr) {
		tag[p][0]=(tag[p][0]+x)%mod;
		tag[p][1]=(tag[p][1]+y)%mod;
		t[p]=(t[p]+cal(x,y,r-l+1));
		val[p]=1; return ;
	}
	ll mid=(l+r)>>1; push_down(l,r,p);
	if(qr<=mid) update(l,mid,ql,qr,x,y,ls);
	else if(mid+1<=ql) update(mid+1,r,ql,qr,x,y,rs);
	else {
		update(l,mid,ql,mid,x,y,ls);
		T tp=fibcal((T){x,y},mid-ql);
		update(mid+1,r,mid+1,qr,tp.x,tp.y,rs);
	}
	push_up(p);
}

ll query(ll l,ll r,ll ql,ll qr,ll p)
{
	if(ql<=l&&r<=qr) return t[p]; ll ans=0;
	ll mid=(l+r)>>1; push_down(l,r,p);
	if(ql<=mid) ans=(ans+query(l,mid,ql,qr,ls))%mod;
	if(qr>mid) ans=(ans+query(mid+1,r,ql,qr,rs))%mod;
	return ans;
}

int main()
{
	n=read(); m=read(); f[1]=f[2]=1;
	for(ll i=3;i<mxn;++i) f[i]=(f[i-1]+f[i-2])%mod;
	for(ll i=1;i<=n;++i) a[i]=read()%mod;
	build(1,n,1); ll opt,l,r;
	for(ll i=1;i<=m;++i) {
		opt=read(); l=read(); r=read();
		if(opt==1) update(1,n,l,r,1,1,1);
		else printf("%lld\n",query(1,n,l,r,1));
	}
}


#include<bits/stdc++.h>
namespace my_std{
	using namespace std;
	#define pii pair<int,int>
	#define fir first
	#define sec second
	#define MP make_pair
	#define rep(i,x,y) for (int i=(x);i<=(y);i++)
	#define drep(i,x,y) for (int i=(x);i>=(y);i--)
	#define go(x) for (int i=head[x];i;i=edge[i].nxt)
	#define sz 303030
	typedef long long ll;
	const ll mod=1e9+9;
	template<typename T>
	inline void read(T& t)
	{
		t=0;char f=0,ch=getchar();
		double d=0.1;
		while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
		while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
		if(ch=='.')
		{
			ch=getchar();
			while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();
		}
		t=(f?-t:t);
	}
	template<typename T,typename... Args>
	inline void read(T& t,Args&... args){read(t); read(args...);}
	void file()
	{
		#ifndef ONLINE_JUDGE
		freopen("a.txt","r",stdin);
		#endif
	}
//	inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;

int n,m;
int a[sz];

ll f[sz],ff[sz],F[sz];
void init()
{
	f[0]=0;F[1]=f[1]=1;
	rep(i,2,sz-1) F[i]=(F[i-1]+(f[i]=(f[i-1]+f[i-2])%mod))%mod;
	rep(i,1,sz-1) ff[i]=(i&1)?f[i]:mod-f[i];
}

ll tg1[sz<<1],tg2[sz<<1],sum[sz<<1];
#define ls k<<1
#define rs k<<1|1
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
#define S int k,int l,int r
#define I inline
I void Add1(S,ll s){(tg1[k]+=s)%=mod;(sum[k]+=s*(F[r]-F[l-1]+mod)%mod)%=mod;}
I void Add2(S,ll s){(tg2[k]+=s)%=mod;(sum[k]+=s*(F[r+1]-F[l]+mod)%mod)%=mod;}
I void pushdown(S)
{
	if (!(tg1[k]+tg2[k])) return;
	int mid=(l+r)>>1;
	ll &t1=tg1[k],&t2=tg2[k];
	Add1(lson,t1);Add1(rson,t1);
	Add2(lson,t2);Add2(rson,t2);
	t1=t2=0;
}
void pushup(int k){sum[k]=(sum[ls]+sum[rs])%mod;}
void add(S,int x,int y,ll s1,ll s2)
{
	if (x<=l&&r<=y) return Add1(k,l,r,s1),Add2(k,l,r,s2);
	pushdown(k,l,r);
	int mid=(l+r)>>1;
	if (x<=mid) add(lson,x,y,s1,s2);
	if (y>mid) add(rson,x,y,s1,s2);
	pushup(k);
}
ll query(S,int x,int y)
{
	if (x<=l&&r<=y) return sum[k];
	pushdown(k,l,r);
	int mid=(l+r)>>1;
	ll ret=0;
	if (x<=mid) ret+=query(lson,x,y);
	if (y>mid) ret+=query(rson,x,y);
	return ret%mod;
}
void build(S)
{
	if (l==r) return (void)(sum[k]=a[l]);
	int mid=(l+r)>>1;
	build(lson);build(rson);
	pushup(k);
}

int main()
{
	file();
	int x,y,z;
	read(n,m);
	rep(i,1,n) read(a[i]);
	init();
	build(1,1,n);
	while (m--)
	{
		read(z,x,y);
		if (z==1) add(1,1,n,x,y,ff[x],ff[x-1]);
		else printf("%lld\n",query(1,1,n,x,y));
	}
	return 0;
}


#include<bits/stdc++.h>
#define REP(i,first,last) for(int i=first;i<=last;++i)
#define DOW(i,first,last) for(int i=first;i>=last;--i)
using namespace std;
const int maxN=3e5+7;
const int mod=1e9+9;
int N,M;
int arr[maxN];
int Mod(long long a)
{
	a%=mod;
	a+=mod;
	a%=mod;
	return a;
}
int f[maxN];
int CalcNext(int fir,int sec,int len)
{
	if(len==1)
	{
		return fir;
	}
	if(len==2)
	{
		return sec;
	}
	return Mod(1ll*fir*f[len-2]+1ll*sec*f[len-1]);
}
int CalcSum(int fir,int sec,int len)
{
	if(len==1)
	{
		return fir;
	}
	if(len==2)
	{
		return Mod(fir+sec);
	}
	return Mod(CalcNext(fir,sec,len+2)-sec);
}
struct Tree
{
	int sum;
	int first,second;
}tree[maxN*3];
#define LSON (now<<1)
#define RSON (now<<1|1)
#define MIDDLE ((left+right)>>1)
#define LEFT LSON,left,MIDDLE
#define RIGHT RSON,MIDDLE+1,right
#define NOW now_left,now_right
void PushUp(int now)
{
	tree[now].sum=Mod(tree[LSON].sum+tree[RSON].sum);
}
void Build(int now=1,int left=1,int right=N)
{
	if(left==right)
	{
		tree[now].sum=arr[left];
		return;
	}
	Build(LEFT);
	Build(RIGHT);
	PushUp(now);
}
#define LEN (right-left+1)
void Down(int now,int left,int right,int add_first,int add_second)
{
	tree[now].first=Mod(tree[now].first+add_first);
	tree[now].second=Mod(tree[now].second+add_second);
	tree[now].sum=Mod(tree[now].sum+CalcSum(add_first,add_second,LEN));
}
#undef LEN
#define TWO tree[now].first,tree[now].second
#define LEN (MIDDLE-left+1)
void PushDown(int now,int left,int right)
{
	Down(LEFT,TWO);
	Down(RIGHT,CalcNext(TWO,LEN+1),CalcNext(TWO,LEN+2));
	tree[now].first=tree[now].second=0;
}
#undef TWO
#undef LEN
#define LEN (left-now_left+1)
void Updata(int now_left,int now_right,int now=1,int left=1,int right=N)
{
	if(right<now_left||now_right<left)
	{
		return;
	}
	if(now_left<=left&&right<=now_right)
	{
		Down(now,left,right,f[LEN],f[LEN+1]);
		return;
	}
	Updata(NOW,LEFT);
	Updata(NOW,RIGHT);
	PushUp(now);
}
#undef LEN
#define L max(now_left,left)
#define R min(now_right,right)
#define TWO tree[now].first,tree[now].second
int Query(int now_left,int now_right,int now=1,int left=1,int right=N)
{
	if(right<now_left||now_right<left)
	{
		return 0;
	}
	if(now_left<=left&&right<=now_right)
	{
		return tree[now].sum;
	}
	int result=CalcSum(CalcNext(TWO,L-left+1),CalcNext(TWO,L-left+2),R-L+1)+Mod(Query(NOW,LEFT)+Query(NOW,RIGHT));
	PushUp(now);
	return result;
}
int main()
{
	scanf("%d%d",&N,&M);
	REP(i,1,N)
	{
		scanf("%d",&arr[i]);
	}
	Build();
	f[1]=f[2]=1;
	REP(i,3,N+2)
	{
		f[i]=Mod(f[i-1]+f[i-2]);
	}
	int op,left,right;
	REP(i,1,M)
	{
		scanf("%d%d%d",&op,&left,&right);
		if(op==1)
		{
			Updata(left,right);
		}
		if(op==2)
		{
			printf("%d\n",Query(left,right));
		}
	}
	return 0;
}


#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
int n,m,a[300001],s[300001],tree[1200001],mod=1e9+9;
void pushup(int o){tree[o]=(tree[o<<1]+tree[o<<1|1])%mod;}
void pushdown(int o,int l,int r){

}
void build(int o,int l,int r){
	if(l==r){
		tree[o]=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(o<<1,l,mid);build(o<<1|1,mid+1,r);
	pushup(o);
}
void add(int o,int l,int r,int ql,int qr,int l1,int r1){
	if(ql<=l&&r<=qr){
		tree[o]+=s[r1]-s[l1-1];
		return;
	}
	int mid=(l+r)>>1,mid1=(l1+r1)>>1;
	pushdown(o,l,r);
	add(o<<1,l,mid,ql,qr,l1,mid1);
	add(o<<1|1,mid+1,r,ql,qr,mid1+1,r1);
	pushup(o);
}
int sum(int o,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr)return tree[o];
	int mid=(l+r)>>1,ans=0;pushdown(o,l,r);
	if(mid>=ql)ans=(ans+sum(o<<1,l,mid,ql,qr))%mod;
	if(mid<qr)ans=(ans+sum(o<<1|1,mid+1,r,ql,qr))%mod;
	return ans;
}
int main(){
cin>>n>>m;for(int i=1;i<=n;i++)cin>>a[i];
s[1]=s[2]=1;for(int i=3;i<=n;i++)s[i]=(s[i-1]+s[i-2])%mod;
for(int i=1;i<=n;i++)s[i]=(s[i]+s[i-1])%mod;
build(1,1,n);
while(m--){
	int opt,l,r;
	cin>>opt>>l>>r;
	if(opt==1)add(1,1,n,l,r,1,r-l+1);
	else cout<<sum(1,1,n,l,r)<<endl;
}
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1000000009;
const ll sq5=383008016;
const ll inv=276601605;
const ll xp=691504013;
const ll yp=308495997;
const ll invx=691504013;
const ll invy=308495997;
const int N=300050;

int n,m;
ll sumv[N],XI[N],YI[N],VALX[N],VALY[N];
ll *xi,*valx;

ll KSM(ll a,ll p){
    ll ret=1;
    while(p){
        if(p&1) ret=ret*a%mod;
        a=a*a%mod;p>>=1;
    } return ret;
}

struct Node{
    Node *l,*r;
    ll sum,addv;
    Node(){sum=0,addv=0;}
};Node *Rtx,*Rty;

inline ll len(ll x,ll y){return y-x+1;}

Node* NewNode(){return new Node();}

inline void pushdown(Node* now,int l,int r){
    if(now->l==NULL) now->l=NewNode();
    if(now->r==NULL) now->r=NewNode();
    int mid=((l+r)>>1);
    now->l->addv+=now->addv;
    now->r->addv+=now->addv*xi[len(l,mid)]%mod;
    now->l->sum+=now->addv*valx[mid-l+1]%mod;
    now->r->sum+=(now->addv*xi[len(l,mid)]%mod)*valx[r-mid]%mod;
    now->l->addv%=mod;now->r->addv%=mod;
    now->l->sum%=mod;now->r->sum%=mod;
    now->addv=0;
    return;
}

void upd(Node* now,int l,int r,int ql,int qr){
//  cout<<l<<" "<<r<<endl;
    if(ql<=l && r<=qr){
//      cout<<l<<" "<<r<<" "<<ql<<" "<<qr<<" "<<xi[l-ql]<<" "<<valx[r-l+1]<<endl;
        now->addv=(xi[l-ql]+now->addv)%mod;
        now->sum+=valx[r-l+1]*xi[l-ql]%mod;
        now->sum%=mod;return;
    }
    int mid=((l+r)>>1);pushdown(now,l,r);
    if(ql<=mid) upd(now->l,l,mid,ql,qr);
    if(qr>mid) upd(now->r,mid+1,r,ql,qr);
    now->sum=(now->l->sum+now->r->sum)%mod;
}

ll que(Node* now,int l,int r,int ql,int qr){
//  cout<<l<<" "<<r<<endl;
    if(ql<=l && r<=qr) return now->sum;
    int mid=((l+r)>>1);
    pushdown(now,l,r);ll ret=0;
    if(ql<=mid) ret+=que(now->l,l,mid,ql,qr);
    if(qr>mid) ret+=que(now->r,mid+1,r,ql,qr);
    return ret%mod;
}

int main()
{
    Rtx=NewNode();Rty=NewNode();
    scanf("%d%d",&n,&m);XI[0]=YI[0]=1;
    for(int i=1;i<=n;i++) scanf("%lld",&sumv[i]);
    for(int i=1;i<=n;i++) sumv[i]=(sumv[i-1]+sumv[i])%mod;
    for(int i=1;i<=n+1;i++) XI[i]=XI[i-1]*xp%mod;
    for(int i=1;i<=n+1;i++) YI[i]=YI[i-1]*yp%mod;
    for(int i=1;i<=n;i++) VALX[i]=((XI[i+1]-XI[1])%mod)*invx%mod;
    for(int i=1;i<=n;i++) VALY[i]=((YI[i+1]-YI[1])%mod)*invy%mod;

//  for(int i=1;i<=n;i++) cout<<((XI[i]-YI[i])*inv%mod+mod)%mod<<endl;
//  ll wf=0;
//  for(int i=1;i<=n;i++) {
//      wf=(wf+XI[i])%mod;
//      cout<<(VALX[i]+mod)%mod<<" "<<wf<<endl;
//  }

    while(m--){
        int f,x,y;
        scanf("%d%d%d",&f,&x,&y);
        if(f==1){
            xi=XI;valx=VALX;
            upd(Rtx,1,n,x,y);
//          return 0;
            xi=YI,valx=VALY;
            upd(Rty,1,n,x,y);
        }else{
            xi=XI;valx=VALX;
//          cout<<que(Rtx,1,n,2,2)<<" "<<XI[1]<<" "<<que(Rtx,1,n,3,3)<<" "<<XI[2]<<endl;
            ll ans=que(Rtx,1,n,x,y);
            xi=YI,valx=VALY;
//          cout<<que(Rty,1,n,2,2)<<" "<<YI[1]<<" "<<que(Rty,1,n,3,3)<<" "<<YI[2]<<endl;
            ans=(ans-que(Rty,1,n,x,y)+mod)%mod;
            ans=ans*inv%mod;ans=(ans+sumv[y]-sumv[x-1])%mod;
            printf("%lld\n",(ans+mod)%mod);
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair <int, int> ii;
typedef vector <int> vi;
typedef vector <vi> vvi;
typedef vector <ii> vii;
typedef vector <vii> vvii;
#define endl '\n'
#define PB push_back
#define MP make_pair
#define OO (1000000000)         // ToDo
#define EPS (1e-9)              // ToDo
#define MOD (1000000009)        // ToDo
#define all(v) ((v).begin()),((v).end())
#define DEBUG(x) cout<< #x <<" = "<<"\""<< (x) <<"\""<<endl
#define FASTIO ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
void read_file(bool outToFile = true){
#ifdef LOCAL_TEST
    freopen("in.in", "rt", stdin);
    if(outToFile)
    freopen("out.out", "wt", stdout);
#endif
}
//
#define nMax 300000+2+1
int n, nq;
//
void add(int &x, int v){
    x += v;
    if(x >= MOD) x -= MOD;
}
//

//
// fibo stuff begin
//
const int matMax = 2;
struct matrix{
    int n, m;
    int mat[matMax][matMax];
    matrix(int nn=0, int nm=0, int d=0){
        n = nn, m = nm;
        memset(mat, 0, sizeof mat);

        if(d)
        {
            for(int i=0; i<n; i++)
                mat[i][i] = d;
        }
    }
};
matrix MAT[nMax];
matrix SMAT[nMax];
matrix T;
//
matrix operator+ (const matrix &A, const matrix &B){
    int n, m;
    n = A.n, m = A.m;
    assert(n == B.n && m == B.m);

    matrix C = A;
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
            add(C.mat[i][j], B.mat[i][j]);

    return C;
}
matrix operator* (const matrix &A, const matrix &B){
    int n, m, p;
    n = A.n;
    m = A.m;
    p = B.m;
    assert(B.n == m);

    matrix C(n, p);
    for(int i=0; i<n; i++)
    {
        for(int k=0; k<m; k++)
        {
            if(A.mat[i][k] == 0) continue;
            for(int j=0; j<p; j++)
                add(C.mat[i][j], 1LL * A.mat[i][k] * B.mat[k][j] %MOD);
        }
    }
    return C;
}
//
void build(){

    T = matrix(2, 2);
    T.mat[0][0] = 1;
    T.mat[0][1] = 1;
    T.mat[1][0] = 1;
    T.mat[1][1] = 0;

    MAT[0] = matrix(2, 2, 1);
    SMAT[0] = matrix(2, 2, 1);

    for(int i=1; i<nMax; i++)
    {
        MAT[i] = MAT[i-1] * T;
        SMAT[i] = SMAT[i-1] + MAT[i];
    }
}
//int query_F(int f0, int f1, int n){
//    int a = SMAT[n-1].mat[1][0];
//    int b = SMAT[n-1].mat[1][1];
//
//    int ret = 1LL * a * f1 %MOD;
//    add(ret, 1LL * b * f0 %MOD);
//    return ret;
//}
int query_F(int f0, int f1, int n){

    matrix X0(2, 1);
    X0.mat[0][0] = f1;
    X0.mat[1][0] = f0;

    matrix cum = SMAT[n-1]* X0;
    int ret = cum.mat[1][0];
    return ret;
}
int get_F(int f0, int f1, int n){

    matrix X0(2, 1);
    X0.mat[0][0] = f1;
    X0.mat[1][0] = f0;

    matrix F = MAT[n] * X0;
    int ret = F.mat[1][0];
    return ret;
}
//
// fibo stuff end
//

//
// segment tree stuff begin
//
struct node{
    int val;
    int fst, scd;
};
//
#define stMax 1048576
node ST[stMax];
int GS, GE;
//
void init(){
    GS = 0, GE = n-1;
    for(int i=0; i<stMax; i++)
    {
        ST[i].val = 0;
        ST[i].fst = ST[i].scd = 0;
    }
}
void merge(int p){
    ST[p].val = ST[2*p].val;
    add(ST[p].val, ST[2*p+1].val);
}
void insert(int idx, int val, int s=GS, int e=GE, int p=1){

    if(s == e)
    {
        ST[p].val = val;
        return;
    }

    int m = (s+e)/2;
    if(idx <= m)
        insert(idx, val, s, m, 2*p);
    else
        insert(idx, val, m+1, e, 2*p+1);

    merge(p);
}
void update_node(int fst, int scd, int s, int e, int p){

    add(ST[p].fst, fst);

    add(ST[p].scd, scd);

    add(ST[p].val, query_F(fst, scd, e - s + 1));
}
void update_child(int s, int e, int p){
    int m = (s+e)/2;

    int f0 = ST[p].fst, f1 = ST[p].scd;
    update_node(f0, f1, s, m, 2*p);

    int k = m - s;
    int fkplus1 = get_F(f0, f1, k+1);
    int fkplus2 = get_F(f0, f1, k+2);
    update_node(fkplus1, fkplus2, m+1, e, 2*p+1);

    ST[p].fst = ST[p].scd = 0;
}
void update(int fr, int to, int fst, int scd, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
    {
        update_node(fst, scd, s, e, p);
        return;
    }

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        update(fr, to, fst, scd, s, m, 2*p);
    else if(fr >= m+1)
        update(fr, to, fst, scd, m+1, e, 2*p+1);
    else
    {
        update(fr, to, fst, scd, s, m, 2*p);

        // f0           f1              f2              ...             fl
        // max(fr, s)   ...             ...             ...             min(to, e)
        // m is included in [max(fr, s), min(to, e)] and opposite to fk

        int k = m - max(fr, s);
        int fkplus1 = get_F(fst, scd, k+1);
        int fkplus2 = get_F(fst, scd, k+2);

        update(fr, to, fkplus1, fkplus2, m+1, e, 2*p+1);
    }

    merge(p);
}
void update1(int fr, int to, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
    {
        int f0 = get_F(0, 1, s - fr + 1);
        int f1 = get_F(0, 1, s - fr + 1 + 1);
        update_node(f0, f1, s, e, p);
        return;
    }

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        update1(fr, to, s, m, 2*p);
    else if(fr >= m+1)
        update1(fr, to, m+1, e, 2*p+1);
    else
    {
        update1(fr, to, s, m, 2*p);
        update1(fr, to, m+1, e, 2*p+1);
    }

    merge(p);
}
int query(int fr, int to, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
        return ST[p].val;

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        return query(fr, to, s, m, 2*p);
    else if(fr >= m+1)
        return query(fr, to, m+1, e, 2*p+1);
    else
    {
        int ql = query(fr, to, s, m, 2*p);
        int qr = query(fr, to, m+1, e, 2*p+1);

        int ret = ql;
        add(ret, qr);
        return ret;
    }
}
//
// segment tree stuff end
//

int main()
{
    read_file();
    build();
    while(scanf("%d%d", &n, &nq)!=EOF)
    {
        init();
        for(int i=0; i<n; i++)
        {
            int x;
            scanf("%d", &x);
            insert(i, x);
        }

        while(nq--)
        {
            int cmd, fr, to;
            scanf("%d%d%d", &cmd, &fr, &to);
            fr--, to--;

            if(cmd == 1)
            {
                update(fr, to, 1, 1);
//                update1(fr, to);
                continue;
            }

            int ans;
            ans = query(fr, to);

            printf("%d\n", ans);
        }
        printf("\n");
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair <int, int> ii;
typedef vector <int> vi;
typedef vector <vi> vvi;
typedef vector <ii> vii;
typedef vector <vii> vvii;
#define endl '\n'
#define PB push_back
#define MP make_pair
#define OO (1000000000)         // ToDo
#define EPS (1e-9)              // ToDo
#define MOD (1000000009)        // ToDo
#define all(v) ((v).begin()),((v).end())
#define DEBUG(x) cout<< #x <<" = "<<"\""<< (x) <<"\""<<endl
#define FASTIO ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
void read_file(bool outToFile = true){
#ifdef LOCAL_TEST
    freopen("in.in", "rt", stdin);
    if(outToFile)
    freopen("out.out", "wt", stdout);
#endif
}
//
#define nMax 300000+2+1
int n, nq;
//
void add(int &x, int v){
    x += v;
    if(x >= MOD) x -= MOD;
}
//

//
// fibo stuff begin
//
const int matMax = 2;
struct matrix{
    int n, m;
    int mat[matMax][matMax];
    matrix(int nn=0, int nm=0, int d=0){
        n = nn, m = nm;
        memset(mat, 0, sizeof mat);

        if(d)
        {
            for(int i=0; i<n; i++)
                mat[i][i] = d;
        }
    }

    matrix operator+ (const matrix &B) const{
        assert(n == B.n && m == B.m);

        matrix C = *this;
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                add(C.mat[i][j], B.mat[i][j]);

        return C;
    }

    matrix operator* (const matrix &B) const{
        int p = B.m;
        assert(B.n == m);

        matrix C(n, p);
        for(int i=0; i<n; i++)
        {
            for(int k=0; k<m; k++)
            {
                if(mat[i][k] == 0) continue;
                for(int j=0; j<p; j++)
                    add(C.mat[i][j], 1LL * mat[i][k] * B.mat[k][j] %MOD);
            }
        }
        return C;
    }
};
matrix MAT[nMax];
matrix SMAT[nMax];
matrix T;
//
//matrix operator+ (const matrix &A, const matrix &B){
//    int n, m;
//    n = A.n, m = A.m;
//    assert(n == B.n && m == B.m);
//
//    matrix C = A;
//    for(int i=0; i<n; i++)
//        for(int j=0; j<m; j++)
//            add(C.mat[i][j], B.mat[i][j]);
//
//    return C;
//}
//matrix operator* (const matrix &A, const matrix &B){
//    int n, m, p;
//    n = A.n;
//    m = A.m;
//    p = B.m;
//    assert(B.n == m);
//
//    matrix C(n, p);
//    for(int i=0; i<n; i++)
//    {
//        for(int k=0; k<m; k++)
//        {
//            if(A.mat[i][k] == 0) continue;
//            for(int j=0; j<p; j++)
//                add(C.mat[i][j], 1LL * A.mat[i][k] * B.mat[k][j] %MOD);
//        }
//    }
//    return C;
//}
//
void build(){

    T = matrix(2, 2);
    T.mat[0][0] = 1;
    T.mat[0][1] = 1;
    T.mat[1][0] = 1;
    T.mat[1][1] = 0;

    MAT[0] = matrix(2, 2, 1);
    SMAT[0] = matrix(2, 2, 1);

    for(int i=1; i<nMax; i++)
    {
        MAT[i] = MAT[i-1] * T;
        SMAT[i] = SMAT[i-1] + MAT[i];
    }
}
//int query_F(int f0, int f1, int n){
//    int a = SMAT[n-1].mat[1][0];
//    int b = SMAT[n-1].mat[1][1];
//
//    int ret = 1LL * a * f1 %MOD;
//    add(ret, 1LL * b * f0 %MOD);
//    return ret;
//}
int query_F(int f0, int f1, int n){

    matrix X0(2, 1);
    X0.mat[0][0] = f1;
    X0.mat[1][0] = f0;

    matrix cum = SMAT[n-1]* X0;
    int ret = cum.mat[1][0];
    return ret;
}
int get_F(int f0, int f1, int n){

    matrix X0(2, 1);
    X0.mat[0][0] = f1;
    X0.mat[1][0] = f0;

    matrix F = MAT[n] * X0;
    int ret = F.mat[1][0];
    return ret;
}
//
// fibo stuff end
//

//
// segment tree stuff begin
//
struct node{
    int val;
    int fst, scd;
};
//
#define stMax 1048576
node ST[stMax];
int GS, GE;
//
void init(){
    GS = 0, GE = n-1;
    for(int i=0; i<stMax; i++)
    {
        ST[i].val = 0;
        ST[i].fst = ST[i].scd = 0;
    }
}
void merge(int p){
    ST[p].val = ST[2*p].val;
    add(ST[p].val, ST[2*p+1].val);
}
void insert(int idx, int val, int s=GS, int e=GE, int p=1){

    if(s == e)
    {
        ST[p].val = val;
        return;
    }

    int m = (s+e)/2;
    if(idx <= m)
        insert(idx, val, s, m, 2*p);
    else
        insert(idx, val, m+1, e, 2*p+1);

    merge(p);
}
void update_node(int fst, int scd, int s, int e, int p){

    add(ST[p].fst, fst);

    add(ST[p].scd, scd);

    add(ST[p].val, query_F(fst, scd, e - s + 1));
}
void update_child(int s, int e, int p){
    int m = (s+e)/2;

    int f0 = ST[p].fst, f1 = ST[p].scd;
    update_node(f0, f1, s, m, 2*p);

    int k = m - s;
    int fkplus1 = get_F(f0, f1, k+1);
    int fkplus2 = get_F(f0, f1, k+2);
    update_node(fkplus1, fkplus2, m+1, e, 2*p+1);

    ST[p].fst = ST[p].scd = 0;
}
void update(int fr, int to, int fst, int scd, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
    {
        update_node(fst, scd, s, e, p);
        return;
    }

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        update(fr, to, fst, scd, s, m, 2*p);
    else if(fr >= m+1)
        update(fr, to, fst, scd, m+1, e, 2*p+1);
    else
    {
        update(fr, to, fst, scd, s, m, 2*p);

        // f0           f1              f2              ...             fl
        // max(fr, s)   ...             ...             ...             min(to, e)
        // m is included in [max(fr, s), min(to, e)] and opposite to fk

        int k = m - max(fr, s);
        int fkplus1 = get_F(fst, scd, k+1);
        int fkplus2 = get_F(fst, scd, k+2);

        update(fr, to, fkplus1, fkplus2, m+1, e, 2*p+1);
    }

    merge(p);
}
void update1(int fr, int to, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
    {
        int f0 = get_F(0, 1, s - fr + 1);
        int f1 = get_F(0, 1, s - fr + 1 + 1);
        update_node(f0, f1, s, e, p);
        return;
    }

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        update1(fr, to, s, m, 2*p);
    else if(fr >= m+1)
        update1(fr, to, m+1, e, 2*p+1);
    else
    {
        update1(fr, to, s, m, 2*p);
        update1(fr, to, m+1, e, 2*p+1);
    }

    merge(p);
}
int query(int fr, int to, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
        return ST[p].val;

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        return query(fr, to, s, m, 2*p);
    else if(fr >= m+1)
        return query(fr, to, m+1, e, 2*p+1);
    else
    {
        int ql = query(fr, to, s, m, 2*p);
        int qr = query(fr, to, m+1, e, 2*p+1);

        int ret = ql;
        add(ret, qr);
        return ret;
    }
}
//
// segment tree stuff end
//

int main()
{
    read_file();
    build();
    while(scanf("%d%d", &n, &nq)!=EOF)
    {
        init();
        for(int i=0; i<n; i++)
        {
            int x;
            scanf("%d", &x);
            insert(i, x);
        }

        while(nq--)
        {
            int cmd, fr, to;
            scanf("%d%d%d", &cmd, &fr, &to);
            fr--, to--;

            if(cmd == 1)
            {
                update(fr, to, 1, 1);
//                update1(fr, to);
                continue;
            }

            int ans;
            ans = query(fr, to);

            printf("%d\n", ans);
        }
        printf("\n");
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair <int, int> ii;
typedef vector <int> vi;
typedef vector <vi> vvi;
typedef vector <ii> vii;
typedef vector <vii> vvii;
#define endl '\n'
#define PB push_back
#define MP make_pair
#define OO (1000000000)         // ToDo
#define EPS (1e-9)              // ToDo
#define MOD (1000000009)        // ToDo
#define all(v) ((v).begin()),((v).end())
#define DEBUG(x) cout<< #x <<" = "<<"\""<< (x) <<"\""<<endl
#define FASTIO ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
void read_file(bool outToFile = true){
#ifdef LOCAL_TEST
    freopen("in.in", "rt", stdin);
    if(outToFile)
    freopen("out.out", "wt", stdout);
#endif
}
//
#define nMax 300000+2+1
int n, nq;
//
void add(int &x, int v){
    x += v;
    if(x >= MOD) x -= MOD;
}
//

//
// fibo stuff begin
//
const int matMax = 2;
struct matrix{
    int n, m;
    int mat[matMax][matMax];
    matrix(int nn=0, int nm=0){
        n = nn, m = nm;
    }
};
matrix MAT[nMax];
matrix SMAT[nMax];
matrix T;
//
matrix zero(int n, int m){
    matrix A(n, m);
    memset(A.mat, 0, sizeof A.mat);
    return A;
}
matrix identity(int n){
    matrix A = zero(n, n);
    for(int i=0; i<n; i++)
        A.mat[i][i] = 1;
    return A;
}
matrix operator+ (const matrix &A, const matrix &B){
    int n, m;
    n = A.n, m = A.m;
    assert(n == B.n && m == B.m);

    matrix C = A;
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
            add(C.mat[i][j], B.mat[i][j]);

    return C;
}
matrix operator* (const matrix &A, const matrix &B){
    int n, m, p;
    n = A.n;
    m = A.m;
    p = B.m;
    assert(B.n == m);

    matrix C = zero(n, p);
    for(int i=0; i<n; i++)
    {
        for(int k=0; k<m; k++)
        {
            if(A.mat[i][k] == 0) continue;
            for(int j=0; j<p; j++)
                add(C.mat[i][j], 1LL * A.mat[i][k] * B.mat[k][j] %MOD);
        }
    }
    return C;
}
//
void build(){

    T = zero(2, 2);
    T.mat[0][0] = 1;
    T.mat[0][1] = 1;
    T.mat[1][0] = 1;
    T.mat[1][1] = 0;

    MAT[0] = identity(2);
    SMAT[0] = identity(2);

    for(int i=1; i<nMax; i++)
    {
        MAT[i] = MAT[i-1] * T;
        SMAT[i] = (SMAT[i-1] + MAT[i]);
    }
}
//int query_F(int f0, int f1, int n){
//    int a = SMAT[n-1].mat[1][0];
//    int b = SMAT[n-1].mat[1][1];
//
//    int ret = 1LL * a * f1 %MOD;
//    add(ret, 1LL * b * f0 %MOD);
//    return ret;
//}
int query_F(int f0, int f1, int n){

    matrix X0 = zero(2, 1);
    X0.mat[0][0] = f1;
    X0.mat[1][0] = f0;

    matrix cum = SMAT[n-1]* X0;
    int ret = cum.mat[1][0];
    return ret;
}
int get_F(int f0, int f1, int n){

    matrix X0 = zero(2, 1);
    X0.mat[0][0] = f1;
    X0.mat[1][0] = f0;

    matrix F = MAT[n] * X0;
    int ret = F.mat[1][0];
    return ret;
}
//
// fibo stuff end
//

//
// segment tree stuff begin
//
struct node{
    int val;
    int fst, scd;
};
//
#define stMax 1048576
node ST[stMax];
int GS, GE;
//
void init(){
    GS = 0, GE = n-1;
    for(int i=0; i<stMax; i++)
    {
        ST[i].val = 0;
        ST[i].fst = ST[i].scd = 0;
    }
}
void merge(int p){
    ST[p].val = ST[2*p].val;
    add(ST[p].val, ST[2*p+1].val);
}
void insert(int idx, int val, int s=GS, int e=GE, int p=1){

    if(s == e)
    {
        ST[p].val = val;
        return;
    }

    int m = (s+e)/2;
    if(idx <= m)
        insert(idx, val, s, m, 2*p);
    else
        insert(idx, val, m+1, e, 2*p+1);

    merge(p);
}
void update_node(int fst, int scd, int s, int e, int p){

    add(ST[p].fst, fst);

    add(ST[p].scd, scd);

    add(ST[p].val, query_F(fst, scd, e - s + 1));
}
void update_child(int s, int e, int p){
    int m = (s+e)/2;

    int f0 = ST[p].fst, f1 = ST[p].scd;
    update_node(f0, f1, s, m, 2*p);

    int k = m - s;
    int fkplus1 = get_F(f0, f1, k+1);
    int fkplus2 = get_F(f0, f1, k+2);
    update_node(fkplus1, fkplus2, m+1, e, 2*p+1);

    ST[p].fst = ST[p].scd = 0;
}
void update(int fr, int to, int fst, int scd, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
    {
        update_node(fst, scd, s, e, p);
        return;
    }

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        update(fr, to, fst, scd, s, m, 2*p);
    else if(fr >= m+1)
        update(fr, to, fst, scd, m+1, e, 2*p+1);
    else
    {
        update(fr, to, fst, scd, s, m, 2*p);

        // f0           f1              f2              ...             fl
        // max(fr, s)   ...             ...             ...             min(to, e)
        // m is included in [max(fr, s), min(to, e)] and opposite to fk

        int k = m - max(fr, s);
        int fkplus1 = get_F(fst, scd, k+1);
        int fkplus2 = get_F(fst, scd, k+2);

        update(fr, to, fkplus1, fkplus2, m+1, e, 2*p+1);
    }

    merge(p);
}
void update1(int fr, int to, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
    {
        int f0 = get_F(0, 1, s - fr + 1);
        int f1 = get_F(0, 1, s - fr + 1 + 1);
        update_node(f0, f1, s, e, p);
        return;
    }

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        update1(fr, to, s, m, 2*p);
    else if(fr >= m+1)
        update1(fr, to, m+1, e, 2*p+1);
    else
    {
        update1(fr, to, s, m, 2*p);
        update1(fr, to, m+1, e, 2*p+1);
    }

    merge(p);
}
int query(int fr, int to, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
        return ST[p].val;

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        return query(fr, to, s, m, 2*p);
    else if(fr >= m+1)
        return query(fr, to, m+1, e, 2*p+1);
    else
    {
        int ql = query(fr, to, s, m, 2*p);
        int qr = query(fr, to, m+1, e, 2*p+1);

        int ret = ql;
        add(ret, qr);
        return ret;
    }
}
//
// segment tree stuff end
//

int main()
{
    read_file();
    build();
    while(scanf("%d%d", &n, &nq)!=EOF)
    {
        init();
        for(int i=0; i<n; i++)
        {
            int x;
            scanf("%d", &x);
            insert(i, x);
        }

        while(nq--)
        {
            int cmd, fr, to;
            scanf("%d%d%d", &cmd, &fr, &to);
            fr--, to--;

            if(cmd == 1)
            {
                update(fr, to, 1, 1);
//                update1(fr, to);
                continue;
            }

            int ans;
            ans = query(fr, to);

            printf("%d\n", ans);
        }
        printf("\n");
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair <int, int> ii;
typedef vector <int> vi;
typedef vector <vi> vvi;
typedef vector <ii> vii;
typedef vector <vii> vvii;
#define endl '\n'
#define PB push_back
#define MP make_pair
#define OO (1000000000)         // ToDo
#define EPS (1e-9)              // ToDo
#define MOD (1000000009)        // ToDo
#define all(v) ((v).begin()),((v).end())
#define DEBUG(x) cout<< #x <<" = "<<"\""<< (x) <<"\""<<endl
#define FASTIO ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
void read_file(bool outToFile = true){
#ifdef LOCAL_TEST
    freopen("in.in", "rt", stdin);
    if(outToFile)
    freopen("out.out", "wt", stdout);
#endif
}
//
#define nMax 300000+2+1
int n, nq;
//
inline void add(int &x, int v){
    x += v;
    if(x >= MOD) x -= MOD;
}
//

//
// fibo stuff begin
//
const int matMax = 2;
struct matrix{
    int n, m;
    int mat[matMax][matMax];

    matrix(){

    }

    matrix(int nn, int nm, int d=0){
        n = nn, m = nm;
        memset(mat, 0, sizeof mat);

        if(d)
        {
            for(int i=0; i<n; i++)
                mat[i][i] = d;
        }
    }

    matrix operator+ (const matrix &B) const{
        assert(n == B.n && m == B.m);

        matrix C = *this;
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                add(C.mat[i][j], B.mat[i][j]);

        return C;
    }

    matrix operator* (const matrix &B) const{
        int p = B.m;
        assert(B.n == m);

        matrix C(n, p);
        for(int i=0; i<n; i++)
        {
            for(int k=0; k<m; k++)
            {
                if(mat[i][k] == 0) continue;
                for(int j=0; j<p; j++)
                    add(C.mat[i][j], 1LL * mat[i][k] * B.mat[k][j] %MOD);
            }
        }
        return C;
    }
};
//
matrix MAT[nMax];
matrix SMAT[nMax];
matrix T;
//
void build(){

    T = matrix(2, 2);
    T.mat[0][0] = 1;
    T.mat[0][1] = 1;
    T.mat[1][0] = 1;
    T.mat[1][1] = 0;

    MAT[0] = matrix(2, 2, 1);
    SMAT[0] = matrix(2, 2, 1);

    for(int i=1; i<nMax; i++)
    {
        MAT[i] = MAT[i-1] * T;
        SMAT[i] = SMAT[i-1] + MAT[i];
    }
}
int query_F(int f0, int f1, int n){

    matrix X0(2, 1);
    X0.mat[0][0] = f1;
    X0.mat[1][0] = f0;

    matrix cum = SMAT[n-1]* X0;
    int ret = cum.mat[1][0];
    return ret;
}
int get_F(int f0, int f1, int n){

    matrix X0(2, 1);
    X0.mat[0][0] = f1;
    X0.mat[1][0] = f0;

    matrix F = MAT[n] * X0;
    int ret = F.mat[1][0];
    return ret;
}
//
// fibo stuff end
//

//
// segment tree stuff begin
//
struct node{
    int val;
    int fst, scd;
};
//
#define stMax 1048576
node ST[stMax];
int GS, GE;
//
void init(){
    GS = 0, GE = n-1;
    for(int i=0; i<stMax; i++)
    {
        ST[i].val = 0;
        ST[i].fst = ST[i].scd = 0;
    }
}
void merge(int p){
    ST[p].val = ST[2*p].val;
    add(ST[p].val, ST[2*p+1].val);
}
void insert(int idx, int val, int s=GS, int e=GE, int p=1){

    if(s == e)
    {
        ST[p].val = val;
        return;
    }

    int m = (s+e)/2;
    if(idx <= m)
        insert(idx, val, s, m, 2*p);
    else
        insert(idx, val, m+1, e, 2*p+1);

    merge(p);
}
void update_node(int fst, int scd, int s, int e, int p){

    add(ST[p].fst, fst);

    add(ST[p].scd, scd);

    add(ST[p].val, query_F(fst, scd, e - s + 1));
}
void update_child(int s, int e, int p){
    int m = (s+e)/2;

    int f0 = ST[p].fst, f1 = ST[p].scd;
    update_node(f0, f1, s, m, 2*p);

    int k = m - s;
    int fkplus1 = get_F(f0, f1, k+1);
    int fkplus2 = get_F(f0, f1, k+2);
    update_node(fkplus1, fkplus2, m+1, e, 2*p+1);

    ST[p].fst = ST[p].scd = 0;
}
void update(int fr, int to, int fst, int scd, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
    {
        update_node(fst, scd, s, e, p);
        return;
    }

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        update(fr, to, fst, scd, s, m, 2*p);
    else if(fr >= m+1)
        update(fr, to, fst, scd, m+1, e, 2*p+1);
    else
    {
        update(fr, to, fst, scd, s, m, 2*p);

        // f0           f1              f2              ...             fl
        // max(fr, s)   ...             ...             ...             min(to, e)
        // m is included in [max(fr, s), min(to, e)] and opposite to fk

        int k = m - max(fr, s);
        int fkplus1 = get_F(fst, scd, k+1);
        int fkplus2 = get_F(fst, scd, k+2);

        update(fr, to, fkplus1, fkplus2, m+1, e, 2*p+1);
    }

    merge(p);
}
void update1(int fr, int to, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
    {
        int f0 = get_F(0, 1, s - fr + 1);
        int f1 = get_F(0, 1, s - fr + 1 + 1);
        update_node(f0, f1, s, e, p);
        return;
    }

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        update1(fr, to, s, m, 2*p);
    else if(fr >= m+1)
        update1(fr, to, m+1, e, 2*p+1);
    else
    {
        update1(fr, to, s, m, 2*p);
        update1(fr, to, m+1, e, 2*p+1);
    }

    merge(p);
}
int query(int fr, int to, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
        return ST[p].val;

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        return query(fr, to, s, m, 2*p);
    else if(fr >= m+1)
        return query(fr, to, m+1, e, 2*p+1);
    else
    {
        int ql = query(fr, to, s, m, 2*p);
        int qr = query(fr, to, m+1, e, 2*p+1);

        int ret = ql;
        add(ret, qr);
        return ret;
    }
}
//
// segment tree stuff end
//

int main()
{
    read_file();
    build();
    while(scanf("%d%d", &n, &nq)!=EOF)
    {
        init();
        for(int i=0; i<n; i++)
        {
            int x;
            scanf("%d", &x);
            insert(i, x);
        }

        while(nq--)
        {
            int cmd, fr, to;
            scanf("%d%d%d", &cmd, &fr, &to);
            fr--, to--;

            if(cmd == 1)
            {
                update(fr, to, 1, 1);
//                update1(fr, to);
                continue;
            }

            int ans;
            ans = query(fr, to);

            printf("%d\n", ans);
        }
        printf("\n");
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair <int, int> ii;
typedef vector <int> vi;
typedef vector <vi> vvi;
typedef vector <ii> vii;
typedef vector <vii> vvii;
#define endl '\n'
#define PB push_back
#define MP make_pair
#define OO (1000000000)         // ToDo
#define EPS (1e-9)              // ToDo
#define MOD (1000000009)        // ToDo
#define all(v) ((v).begin()),((v).end())
#define DEBUG(x) cout<< #x <<" = "<<"\""<< (x) <<"\""<<endl
#define FASTIO ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
void read_file(bool outToFile = true){
#ifdef LOCAL_TEST
    freopen("in.in", "rt", stdin);
    if(outToFile)
    freopen("out.out", "wt", stdout);
#endif
}
//
#define nMax 300000+2+1
int n, nq;
//
inline void add(int &x, int v){
    x += v;
    if(x >= MOD) x -= MOD;
}
//

//
// fibo stuff begin
//
const int matMax = 2;
struct matrix{
    int n, m;
    int mat[matMax][matMax];

    matrix(int nn=0, int nm=0, int d=0){
        n = nn, m = nm;
        memset(mat, 0, sizeof mat);

        if(d)
        {
            for(int i=0; i<n; i++)
                mat[i][i] = d;
        }
    }

    matrix operator+ (const matrix &B) const{
        assert(n == B.n && m == B.m);

        matrix C = *this;
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                add(C.mat[i][j], B.mat[i][j]);

        return C;
    }

    matrix operator* (const matrix &B) const{
        int p = B.m;
        assert(B.n == m);

        matrix C(n, p);
        for(int i=0; i<n; i++)
        {
            for(int k=0; k<m; k++)
            {
                if(mat[i][k] == 0) continue;
                for(int j=0; j<p; j++)
                    add(C.mat[i][j], 1LL * mat[i][k] * B.mat[k][j] %MOD);
            }
        }
        return C;
    }
};
//
matrix MAT[nMax];
matrix SMAT[nMax];
matrix T;
//
void build(){

    T = matrix(2, 2);
    T.mat[0][0] = 1;
    T.mat[0][1] = 1;
    T.mat[1][0] = 1;
    T.mat[1][1] = 0;

    MAT[0] = matrix(2, 2, 1);
    SMAT[0] = matrix(2, 2, 1);

    for(int i=1; i<nMax; i++)
    {
        MAT[i] = MAT[i-1] * T;
        SMAT[i] = SMAT[i-1] + MAT[i];
    }
}
int query_F(int f0, int f1, int n){

    matrix X0(2, 1);
    X0.mat[0][0] = f1;
    X0.mat[1][0] = f0;

    matrix cum = SMAT[n-1]* X0;
    int ret = cum.mat[1][0];
    return ret;
}
int get_F(int f0, int f1, int n){

    matrix X0(2, 1);
    X0.mat[0][0] = f1;
    X0.mat[1][0] = f0;

    matrix F = MAT[n] * X0;
    int ret = F.mat[1][0];
    return ret;
}
//
// fibo stuff end
//

//
// segment tree stuff begin
//
struct node{
    int val;
    int fst, scd;
};
//
#define stMax 1048576
node ST[stMax];
int GS, GE;
//
void init(){
    GS = 0, GE = n-1;
    for(int i=0; i<stMax; i++)
    {
        ST[i].val = 0;
        ST[i].fst = ST[i].scd = 0;
    }
}
void merge(int p){
    ST[p].val = ST[2*p].val;
    add(ST[p].val, ST[2*p+1].val);
}
void insert(int idx, int val, int s=GS, int e=GE, int p=1){

    if(s == e)
    {
        ST[p].val = val;
        return;
    }

    int m = (s+e)/2;
    if(idx <= m)
        insert(idx, val, s, m, 2*p);
    else
        insert(idx, val, m+1, e, 2*p+1);

    merge(p);
}
void update_node(int fst, int scd, int s, int e, int p){

    add(ST[p].fst, fst);

    add(ST[p].scd, scd);

    add(ST[p].val, query_F(fst, scd, e - s + 1));
}
void update_child(int s, int e, int p){
    int m = (s+e)/2;

    int f0 = ST[p].fst, f1 = ST[p].scd;
    update_node(f0, f1, s, m, 2*p);

    int k = m - s;
    int fkplus1 = get_F(f0, f1, k+1);
    int fkplus2 = get_F(f0, f1, k+2);
    update_node(fkplus1, fkplus2, m+1, e, 2*p+1);

    ST[p].fst = ST[p].scd = 0;
}
void update(int fr, int to, int fst, int scd, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
    {
        update_node(fst, scd, s, e, p);
        return;
    }

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        update(fr, to, fst, scd, s, m, 2*p);
    else if(fr >= m+1)
        update(fr, to, fst, scd, m+1, e, 2*p+1);
    else
    {
        update(fr, to, fst, scd, s, m, 2*p);

        // f0           f1              f2              ...             fl
        // max(fr, s)   ...             ...             ...             min(to, e)
        // m is included in [max(fr, s), min(to, e)] and opposite to fk

        int k = m - max(fr, s);
        int fkplus1 = get_F(fst, scd, k+1);
        int fkplus2 = get_F(fst, scd, k+2);

        update(fr, to, fkplus1, fkplus2, m+1, e, 2*p+1);
    }

    merge(p);
}
void update1(int fr, int to, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
    {
        int f0 = get_F(0, 1, s - fr + 1);
        int f1 = get_F(0, 1, s - fr + 1 + 1);
        update_node(f0, f1, s, e, p);
        return;
    }

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        update1(fr, to, s, m, 2*p);
    else if(fr >= m+1)
        update1(fr, to, m+1, e, 2*p+1);
    else
    {
        update1(fr, to, s, m, 2*p);
        update1(fr, to, m+1, e, 2*p+1);
    }

    merge(p);
}
int query(int fr, int to, int s=GS, int e=GE, int p=1){

    if(fr <= s && e <= to)
        return ST[p].val;

    update_child(s, e, p);

    int m = (s+e)/2;
    if(to <= m)
        return query(fr, to, s, m, 2*p);
    else if(fr >= m+1)
        return query(fr, to, m+1, e, 2*p+1);
    else
    {
        int ql = query(fr, to, s, m, 2*p);
        int qr = query(fr, to, m+1, e, 2*p+1);

        int ret = ql;
        add(ret, qr);
        return ret;
    }
}
//
// segment tree stuff end
//

int main()
{
    read_file();
    build();
    while(scanf("%d%d", &n, &nq)!=EOF)
    {
        init();
        for(int i=0; i<n; i++)
        {
            int x;
            scanf("%d", &x);
            insert(i, x);
        }

        while(nq--)
        {
            int cmd, fr, to;
            scanf("%d%d%d", &cmd, &fr, &to);
            fr--, to--;

            if(cmd == 1)
            {
                update(fr, to, 1, 1);
//                update1(fr, to);
                continue;
            }

            int ans;
            ans = query(fr, to);

            printf("%d\n", ans);
        }
        printf("\n");
    }
}