#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("%d\n",query(1,n,l,r,1));
	}
}


#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)%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("%d\n",qry(rt,x,y));
	//	for(i=1;i<=n;i++) cout<<qry(rt,i,i)<<" ";
	//	cout<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>
#define mod 1000000009
#define five 383008016
#define inv5 276601605
#define five1 691504013
#define five2 308495997
using namespace std;
int n,m;
long long a[300005];
int op,L,R;

int sqrtn;
int bl[300005];//block
int l[1005],r[1005],tt;
int siz[1005];//size
long long lazy1[1005],lazy2[1005];
long long sum[1005];

long long mi(long long n,long long p)
{
    if(n==0) return 0;
    if(p==0) return 1;
    long long yuan=1,mul=n;
    while(p)
    {
        if(p&1) yuan*=mul;
        yuan%=mod;
        mul*=mul;
        mul%=mod;
        p>>=1;
    }
    return yuan%mod;
}

long long f[300005];
long long fs[300005];
long long m1[300005],m2[300005];
inline void init()
{
    f[1]=f[2]=1;
    for(int i=3;i<=300000;i++) f[i]=(f[i-1]+f[i-2])%mod;
    for(int i=1;i<=300000;i++) fs[i]=(fs[i-1]+f[i])%mod;
    m1[0]=m2[0]=1;
    for(int i=1;i<=n;i++)
    {
        m1[i]=m1[i-1]*(five+1)%mod*mi(2,mod-2)%mod;
        m2[i]=m2[i-1]*(1-five+mod)%mod*mi(2,mod-2)%mod;
    }
}

inline void inblock()
{
    for(int i=1;i<=n/sqrtn;i++)
    {
        tt++;
        l[tt]=r[tt-1]+1;
        r[tt]=r[tt-1]+sqrtn;
        siz[tt]=r[tt]-l[tt]+1;
        for(int j=l[tt];j<=r[tt];j++) bl[j]=tt;
    }
    if(sqrtn*sqrtn!=n)
    {
        tt++;l[tt]=r[tt-1]+1;r[tt]=n;siz[tt]=r[tt]-l[tt]+1;
        for(int j=l[tt];j<=r[tt];j++) bl[j]=tt;
    }
}

inline void push_down()
{
    if(lazy1[bl[L]]!=0 || lazy2[bl[L]]!=0)
    {
        int tot=0;
        for(int i=l[bl[L]];i<=r[bl[L]];i++)
        {
            a[i]+=lazy1[bl[L]]*m1[tot]%mod*inv5%mod;
            a[i]-=lazy2[bl[L]]*m2[tot]%mod*inv5%mod;
            a[i]%=mod;
            tot++;
        }
        lazy1[bl[L]]=lazy2[bl[L]]=0;
    }
    if(lazy1[bl[R]]!=0 || lazy2[bl[R]]!=0)
    {
        int tot=0;
        for(int i=l[bl[R]];i<=r[bl[R]];i++)
        {
            a[i]+=lazy1[bl[R]]*m1[tot]%mod*inv5%mod;
            a[i]-=lazy2[bl[R]]*m2[tot]%mod*inv5%mod;
            a[i]%=mod;
            tot++;
        }
        lazy1[bl[R]]=lazy2[bl[R]]=0;
    }
//  cout<<"pushed:"<<endl;
//  for(int i=1;i<=n;i++) cout<<a[i]<<" "; cout<<endl;
}

inline void insert()
{
    push_down();
    if(bl[L]==bl[R])
    {
        int tot=1;
        for(int i=L;i<=R;i++)
        {
            a[i]+=f[tot]%mod; a[i]%=mod;
            tot++;
        }
        sum[bl[L]]+=fs[tot-1]%mod; sum[bl[L]]%=mod;
        return ;
    }

    int tot=1;
    for(int i=L;i<=r[bl[L]];i++)
    {
        a[i]+=f[tot]%mod; a[i]%=mod;
        sum[bl[L]]+=f[tot]%mod; sum[bl[L]]%=mod;
        tot++;
    }
    for(int i=bl[L]+1;i<bl[R];i++)
    {
        lazy1[i]+=m1[tot]%mod; lazy1[i]%=mod;
        lazy2[i]+=m2[tot]%mod; lazy2[i]%=mod;
        sum[i]+=fs[tot+siz[i]-1]-fs[tot-1]; sum[i]%=mod;
        tot+=siz[i];
    }
    for(int i=l[bl[R]];i<=R;i++)
    {
        a[i]+=f[tot]%mod; a[i]%=mod;
        sum[bl[R]]+=f[tot]%mod; sum[bl[R]]%=mod;
        tot++;
    }
}

inline void ask()
{
    long long anss=0;
    push_down();

    if(bl[L]==bl[R])
    {
        for(int i=L;i<=R;i++)
        {
            anss+=a[i]%mod;
            anss%=mod;
        }
        cout<<(anss%mod+mod)%mod<<endl;
        return ;
    }

    for(int i=L;i<=r[bl[L]];i++)
    {
        anss+=a[i]%mod;
        anss%=mod;
    }
    for(int i=l[bl[R]];i<=R;i++)
    {
        anss+=a[i]%mod;
        anss%=mod;
    }
    for(int i=bl[L]+1;i<bl[R];i++)
    {
        anss+=sum[i]%mod;
        anss%=mod;
    }
    cout<<(anss%mod+mod)%mod<<endl;
    return ;
}

int main()
{
//  freopen("rd.in","r",stdin);
//  freopen("my.out","w",stdout);
    ios::sync_with_stdio(0);
    cin>>n>>m;
    sqrtn=pow(n,0.4);
    inblock();
    init();
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum[bl[i]]+=a[i];
        sum[bl[i]]%=mod;
    }

//  for(int i=1;i<=n;i++) cout<<bl[i]<<" "; cout<<endl;
//  for(int i=1;i<=tt;i++) cout<<sum[i]<<" "; cout<<endl;
//  cout<<endl;
    while(m--)
    {
        cin>>op>>L>>R;
        if(op==1)
        {
            insert();
//          cout<<endl;
//          for(int i=1;i<=n;i++) cout<<a[i]<<" "; cout<<endl;
//          for(int i=1;i<=tt;i++) cout<<sum[i]<<" "; cout<<endl;
//          cout<<endl;
        }
        else
        {
            ask();
        }
    }
}


#include<bits/stdc++.h>
#define mod 1000000009
#define five 383008016
#define inv5 276601605
#define five1 691504013
#define five2 308495997
using namespace std;
int n,m;
long long a[300005];
int op,L,R;

int sqrtn;
int bl[300005];//block
int l[1005],r[1005],tt;
int siz[1005];//size
long long lazy1[1005],lazy2[1005];
long long sum[1005];

long long mi(long long n,long long p)
{
    if(n==0) return 0;
    if(p==0) return 1;
    long long yuan=1,mul=n;
    while(p)
    {
        if(p&1) yuan*=mul;
        yuan%=mod;
        mul*=mul;
        mul%=mod;
        p>>=1;
    }
    return yuan%mod;
}

long long f[300005];
long long fs[300005];
long long m1[300005],m2[300005];
inline void init()
{
    f[1]=f[2]=1;
    for(int i=3;i<=300000;i++) f[i]=(f[i-1]+f[i-2])%mod;
    for(int i=1;i<=300000;i++) fs[i]=(fs[i-1]+f[i])%mod;
    m1[0]=m2[0]=1;
    for(int i=1;i<=n;i++)
    {
        m1[i]=m1[i-1]*(five+1)%mod*mi(2,mod-2)%mod;
        m2[i]=m2[i-1]*(1-five+mod)%mod*mi(2,mod-2)%mod;
    }
}

inline void inblock()
{
    for(int i=1;i<=n/sqrtn;i++)
    {
        tt++;
        l[tt]=r[tt-1]+1;
        r[tt]=r[tt-1]+sqrtn;
        siz[tt]=r[tt]-l[tt]+1;
        for(int j=l[tt];j<=r[tt];j++) bl[j]=tt;
    }
    if(sqrtn*sqrtn!=n)
    {
        tt++;l[tt]=r[tt-1]+1;r[tt]=n;siz[tt]=r[tt]-l[tt]+1;
        for(int j=l[tt];j<=r[tt];j++) bl[j]=tt;
    }
}

inline void push_down()
{
    if(lazy1[bl[L]]!=0 || lazy2[bl[L]]!=0)
    {
        int tot=0;
        for(int i=l[bl[L]];i<=r[bl[L]];i++)
        {
            a[i]+=lazy1[bl[L]]*m1[tot]%mod*inv5%mod;
            a[i]-=lazy2[bl[L]]*m2[tot]%mod*inv5%mod;
            a[i]%=mod;
            tot++;
        }
        lazy1[bl[L]]=lazy2[bl[L]]=0;
    }
    if(lazy1[bl[R]]!=0 || lazy2[bl[R]]!=0)
    {
        int tot=0;
        for(int i=l[bl[R]];i<=r[bl[R]];i++)
        {
            a[i]+=lazy1[bl[R]]*m1[tot]%mod*inv5%mod;
            a[i]-=lazy2[bl[R]]*m2[tot]%mod*inv5%mod;
            a[i]%=mod;
            tot++;
        }
        lazy1[bl[R]]=lazy2[bl[R]]=0;
    }
//  cout<<"pushed:"<<endl;
//  for(int i=1;i<=n;i++) cout<<a[i]<<" "; cout<<endl;
}

inline void insert()
{
    push_down();
    if(bl[L]==bl[R])
    {
        int tot=1;
        for(int i=L;i<=R;i++)
        {
            a[i]+=f[tot]%mod; a[i]%=mod;
            tot++;
        }
        sum[bl[L]]+=fs[tot-1]%mod; sum[bl[L]]%=mod;
        return ;
    }

    int tot=1;
    for(int i=L;i<=r[bl[L]];i++)
    {
        a[i]+=f[tot]%mod; a[i]%=mod;
        sum[bl[L]]+=f[tot]%mod; sum[bl[L]]%=mod;
        tot++;
    }
    for(int i=bl[L]+1;i<bl[R];i++)
    {
        lazy1[i]+=m1[tot]%mod; lazy1[i]%=mod;
        lazy2[i]+=m2[tot]%mod; lazy2[i]%=mod;
        sum[i]+=fs[tot+siz[i]-1]-fs[tot-1]; sum[i]%=mod;
        tot+=siz[i];
    }
    for(int i=l[bl[R]];i<=R;i++)
    {
        a[i]+=f[tot]%mod; a[i]%=mod;
        sum[bl[R]]+=f[tot]%mod; sum[bl[R]]%=mod;
        tot++;
    }
}

inline void ask()
{
    long long anss=0;
    push_down();

    if(bl[L]==bl[R])
    {
        for(int i=L;i<=R;i++)
        {
            anss+=a[i]%mod;
            anss%=mod;
        }
        cout<<(anss%mod+mod)%mod<<endl;
        return ;
    }

    for(int i=L;i<=r[bl[L]];i++)
    {
        anss+=a[i]%mod;
        anss%=mod;
    }
    for(int i=l[bl[R]];i<=R;i++)
    {
        anss+=a[i]%mod;
        anss%=mod;
    }
    for(int i=bl[L]+1;i<bl[R];i++)
    {
        anss+=sum[i]%mod;
        anss%=mod;
    }
    cout<<(anss%mod+mod)%mod<<endl;
    return ;
}

int main()
{
//  freopen("rd.in","r",stdin);
//  freopen("my.out","w",stdout);
    ios::sync_with_stdio(0);
    cin>>n>>m;
    sqrtn=pow(n,0.45);
    inblock();
    init();
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum[bl[i]]+=a[i];
        sum[bl[i]]%=mod;
    }

//  for(int i=1;i<=n;i++) cout<<bl[i]<<" "; cout<<endl;
//  for(int i=1;i<=tt;i++) cout<<sum[i]<<" "; cout<<endl;
//  cout<<endl;
    while(m--)
    {
        cin>>op>>L>>R;
        if(op==1)
        {
            insert();
//          cout<<endl;
//          for(int i=1;i<=n;i++) cout<<a[i]<<" "; cout<<endl;
//          for(int i=1;i<=tt;i++) cout<<sum[i]<<" "; cout<<endl;
//          cout<<endl;
        }
        else
        {
            ask();
        }
    }
}


#include<bits/stdc++.h>
#define mod 1000000009
#define five 383008016
#define five1 691504013
#define five2 308495997
using namespace std;
int n,m;
long long a[100005];
int op,L,R;

int sqrtn;
int bl[100005];//block
int l[1005],r[1005],tt;
int siz[1005];//size
long long lazy1[1005],lazy2[1005];
long long sum[1005];

long long f[300005];
long long fs[300005];
inline void init()
{
	f[1]=f[2]=1;
	for(int i=3;i<=300000;i++) f[i]=(f[i-1]+f[i-2])%mod;
	for(int i=1;i<=300000;i++) fs[i]=(fs[i-1]+f[i])%mod;
}

inline void inblock()
{
	for(int i=1;i<=n/sqrtn;i++)
	{
		tt++;
		l[tt]=r[tt-1]+1;
		r[tt]=r[tt-1]+sqrtn;
		siz[tt]=r[tt]-l[tt]+1;
		for(int j=l[tt];j<=r[tt];j++) bl[j]=tt;
	}
	if(sqrtn*sqrtn!=n)
	{
		tt++;l[tt]=r[tt-1]+1;r[tt]=n;siz[tt]=r[tt]-l[tt]+1;
		for(int j=l[tt];j<=r[tt];j++) bl[j]=tt;
	}
}

long long mi(long long n,long long p)
{
	if(n==0) return 0;
    if(p==0) return 1;
	long long yuan=1,mul=n;
	while(p)
    {
        if(p&1) yuan*=mul;
        yuan%=mod;
        mul*=mul;
        mul%=mod;
        p>>=1;
    }
    return yuan%mod;
}

inline void insert()
{
	if(bl[L]==bl[R])
	{
		int tot=1;
		for(int i=L;i<=R;i++)
		{
			a[i]+=f[tot]%mod; a[i]%=mod;
			tot++;
		}
		sum[bl[L]]+=fs[tot]%mod; sum[bl[L]]%=mod;
		return ;
	}

	int tot=1;
	for(int i=L;i<=r[bl[L]];i++)
	{
		a[i]+=f[tot]%mod; a[i]%=mod;
		sum[bl[L]]+=f[tot]%mod; sum[bl[L]]%=mod;
		tot++;
	}
	for(int i=bl[L]+1;i<bl[R];i++)
	{
		lazy1[i]+=mi(five1,tot)%mod;
		lazy2[i]+=mi(five2,tot)%mod;
		sum[i]+=fs[tot+siz[i]-1]-fs[tot-1]; sum[i]%=mod;
		tot+=siz[i];
	}
	for(int i=l[bl[R]];i<=R;i++)
	{
		a[i]+=f[tot]%mod; a[i]%=mod;
		sum[bl[R]]+=f[tot]%mod; sum[bl[R]]%=mod;
		tot++;
	}
}

inline void push_down()
{
	if(lazy1[bl[L]]!=0 || lazy2[bl[L]]!=0)
	{
		int tot=0;
		for(int i=L;i<=r[bl[L]];i++)
		{
			a[i]+=lazy1[bl[L]]*mi(five1,tot)%mod*mi(five,mod-2)%mod;
			a[i]-=lazy2[bl[L]]*mi(five2,tot)%mod*mi(five,mod-2)%mod;
			tot++;
		}
		lazy1[bl[L]]=lazy2[bl[L]]=0;
	}
	if(lazy1[bl[R]]!=0 || lazy2[bl[R]]!=0)
	{
		int tot=1;
		for(int i=l[bl[R]];i<=R;i++)
		{
			a[i]+=lazy1[bl[R]]*mi(five1,tot)%mod*mi(five,mod-2)%mod;
			a[i]-=lazy2[bl[R]]*mi(five2,tot)%mod*mi(five,mod-2)%mod;
			tot++;
		}
		lazy1[bl[R]]=lazy2[bl[R]]=0;
	}
}

inline void ask()
{
	long long anss=0;
	push_down();

	if(bl[L]==bl[R])
	{
		for(int i=L;i<=R;i++)
		{
			anss+=a[i]%mod;
			anss%=mod;
		}
		cout<<anss<<endl;
		return ;
	}

	for(int i=L;i<=r[bl[L]];i++)
	{
		anss+=a[i]%mod;
		anss%=mod;
	}
	for(int i=l[bl[R]];i<=R;i++)
	{
		anss+=a[i]%mod;
		anss%=mod;
	}
	for(int i=bl[L]+1;i<bl[R];i++)
	{
		anss+=sum[i]%mod;
		anss%=mod;
	}
	cout<<anss<<endl;
	return ;
}

int main()
{
	ios::sync_with_stdio(0);
	cin>>n>>m;
	sqrtn=pow(n,0.55);
	inblock();
	init();
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		sum[bl[i]]+=a[i];
		sum[bl[i]]%=mod;
	}

	while(m--)
	{
		cin>>op>>L>>R;
		if(op==1)
		{
			insert();
		}
		else
		{
			ask();
		}
	}
}


#include<bits/stdc++.h>
using namespace std;
#define N 300000
const long long P=1000000009;

int Fibo[N+9];

void prework()
{
	Fibo[1]=1,Fibo[2]=1;
	for(int i=3;i<=N;i++) Fibo[i]=(Fibo[i-2]+Fibo[i-1])%P;
}

long long f(long long f1,long long f2,int x)
{
	return (f1*Fibo[x]+f2*(Fibo[x+1]-1))%P;
}

struct seg_tree{
	int l,r;
	long long f1,f2,sum;
} t[N*5];

int n,m;
long long x,a[N+9];

void build(int l,int r,int id)
{
	t[id].l=l,t[id].r=r,t[id].f1=0,t[id].f2=0,t[id].sum=0;
	int mid=(l+r)>>1;
	if(l!=r) build(l,mid,id<<1),build(mid+1,r,id<<1|1);
}

void pushdown(int id)
{
	int ll=id<<1,rr=id<<1|1;
	int lpos=t[id].l,midpos=(t[id].l+t[id].r)>>1,rpos=t[id].r;
	t[ll].f1=(t[ll].f1+t[id].f1)%P,t[ll].f2=(t[ll].f2+t[id].f2)%P,
	t[ll].sum=(t[ll].sum+f(t[id].f1,t[id].f2,midpos-lpos+1))%P;
	int len=midpos-lpos;
	long long tmp1=(t[id].f1*Fibo[len]+t[id].f2*Fibo[len+1])%P;
	long long tmp2=(t[id].f1*Fibo[len+1]+t[id].f2*Fibo[len+2])%P;
	t[rr].f1=(t[rr].f1+tmp1)%P,
	t[rr].f2=(t[rr].f2+tmp2)%P,
	t[rr].sum=(t[rr].sum+f(tmp1,tmp2,rpos-midpos+1));
	t[id].f1=0,t[id].f2=0;
}

void modify(int x,int l,int r,int id)
{
	if(l==t[id].l && r==t[id].r)
	{
		t[id].f1=(t[id].f1+x)%P,t[id].f2=(t[id].f2+x)%P;
		t[id].sum=(t[id].sum+f(Fibo[x],Fibo[x+1],r-l+1))%P;
		return ;
	}
	pushdown(id);
	if(r<=t[id<<1].r) modify(x,l,r,id<<1);
	else if(l>=t[id<<1|1].l) modify(x,l,r,id<<1|1);
	else
		modify(x,l,t[id<<1].r,id<<1),
		modify(x+t[id<<1|1].l-l,t[id<<1|1].l,r,id<<1|1);
}

long long query(int l,int r,int id)
{
	if(l==t[id].l && r==t[id].r) return t[id].sum;
	pushdown(id);
	if(r<=t[id<<1].r) return query(l,r,id<<1);
	if(l>=t[id<<1|1].l) return query(l,r,id<<1|1);
	return (query(l,t[id<<1].r,id<<1)+query(t[id<<1|1].l,r,id<<1|1))%P;
}

int main()
{
	prework();
	scanf("%d%d",&n,&m),a[0]=0;
	for(int i=1;i<=n;i++) scanf("%lld",&x),a[i]=(a[i-1]+x)%P;
	build(1,n,1);
	while(m--)
	{
		int opt,l,r;
		scanf("%d%d%d",&opt,&l,&r);
		if(opt==1) modify(1,l,r,1);
		else
		{
			long long res=query(l,r,1);
			printf("%lld\n",(a[r]-a[l-1]+res+P)%P);
		}
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ls (rt << 1)
#define rs (rt << 1 | 1)

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

const int N = 2e6 + 9, Mod = 1e9 + 9;
ll n, m, ret, a[N], f[N], sum[N];
ll t[N], add[N], add2[N];

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

void spread(ll rt, ll l, ll r) {
	ll mid = l + r >> 1;
	(add[ls] += add[rt]) %= Mod, (add[rs] += add[rt]) %= Mod;
	(add2[ls] += add2[rt]) %= Mod, (add2[rs] += add2[rt]) %= Mod;
	(t[ls] += add[rt] * (sum[mid + 1] - sum[l]) + add2[rt] * (sum[mid] - sum[l - 1])) %= Mod;
	(t[rs] += add[rt] * (sum[r + 1] - sum[mid + 1]) + add2[rt] * (sum[r] - sum[mid])) %= Mod;
	add[rt] = add2[rt] = 0;
}

void modify(ll rt, ll l, ll r, ll x, ll y, ll k) {
	if (x <= l && r <= y) {
		(t[rt] += f[k - 1] * (sum[r + 1] - sum[l]) + f[k] * (sum[r] - sum[l - 1])) %= Mod;
		(add[rt] += f[k - 1]) %= Mod;
		(add2[rt] += f[k]) %= Mod;
		return ;
	}
	spread(rt, l, r);
	int mid = l + r >> 1;
	if (x <= mid) modify(ls, l, mid, x, y, k);
	if (y > mid) modify(rs, mid + 1, r, x, y, k);
	t[rt] = (t[ls] + t[rs]) % Mod;
}

void query(ll rt, ll l, ll r, ll x, ll y) {
	if (x <= l && r <= y) {
		(ret += t[rt]) %= Mod;
		return ;
	}
	spread(rt, l, r);
	int mid = l + r >> 1;
	if (x <= mid) query(ls, l, mid, x, y);
	if (y > mid) query(rs, mid + 1, r, x, y);
}

int main() {
	register ll i;
	n = read(), m = read();
	for (i = 1; i <= n; i ++) a[i] = read();
	build(1, 1, n);
	f[0] = 0, f[1] = 1;
	for (i = 2; i <= n; i ++) f[i] = f[i - 2] - f[i - 1];
	for (i = 1; i <= n; i ++) sum[i] = sum[i - 1] + abs(f[i]);

	for (i = 1; i <= m; i ++) {
		ll opt = read(), x = read(), y = read();
		if (opt == 1) modify(1, 1, n, x, y, x);
		else {
			ret = 0;
			query(1, 1, n, x, y);
			printf("%lld\n", ret);
		}
	}
	return 0;
}


#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<=4e5;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<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*f;
}
int n,m;
const int N = 310000;
const int mod = 1e9 + 9;
int tr[N << 2],tag[N << 2][2];
int sum[N],f[N << 1];

void update(int k){tr[k] = (tr[k << 1] + tr[k << 1 | 1]) % mod;}

void down(int k,int l,int r)
{
	int mid = (l + r) >> 1;

	int x = (tag[k][0] * f[mid - l] % mod + tag[k][1] * f[mid - l + 1] % mod) % mod;
	int y = (tag[k][0] * f[mid - l + 1] % mod + tag[k][1] * f[mid - l + 2] % mod) % mod;

	tag[k << 1][0] = (tag[k << 1][0] + tag[k][0]) % mod;
	tag[k << 1 | 1][0] = (tag[k << 1 | 1][0] + x) % mod;

	tag[k << 1][1] = (tag[k << 1][1] + tag[k][1]) % mod;
	tag[k << 1 | 1][1] = (tag[k << 1 | 1][1] + y) % mod;

	tr[k << 1] = ((tr[k << 1] + tag[k][0] * f[mid - l + 1] % mod + tag[k][1] * f[mid - l + 2] % mod) % mod - tag[k][1] + mod) % mod;
	tr[k << 1 | 1] = ((tr[k << 1 | 1] + x * f[r - mid] + y * f[r - mid + 1]) % mod - y + mod) % mod;
	tag[k][0] = tag[k][1] = 0;
}

void change(int k,int l,int r,int x,int y,int v)
{
	if(x <= l && y >= r)
	{
		int len = r - l + 1;
		tag[k][0] = (tag[k][0] + f[l - x + v]) % mod;
		tag[k][1] = (tag[k][1] + f[l - x + v + 1]) % mod;
		tr[k] = ((tr[k] + f[l - x + v] * f[len] % mod + f[l - x + v + 1] * f[len + 1] % mod - f[l - x + v + 1]) % mod + mod) % mod;
		return;
	}
	int mid = (l + r) >> 1;
	if(tag[k][0] || tag[k][1]) down(k,l,r);
	if(x <= mid)	change(k << 1,l,mid,x,y,v);
	if(y > mid) 	change(k << 1 | 1,mid + 1,r,x,y,v);
	update(k);
	return;
}

int ask(int k,int l,int r,int x,int y)
{
	if(x <= l && y >= r) return tr[k];
	int mid = (l + r) >> 1,ans = 0;
	if(tag[k][0] || tag[k][1]) down(k,l,r);
	if(x <= mid) ans = (ans + ask(k << 1,l,mid,x,y)) % mod;
	if(y > mid)	 ans = (ans + ask(k << 1 | 1,mid + 1,r,x,y)) % mod;
	return ans;
}

signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n = read();m = read();
	f[1] = f[2] = 1;
	for(int i = 3;i <= (n << 1);i ++) f[i] = (f[i - 1] + f[i - 2]) % mod;
	for(int i = 1;i <= n;i ++) sum[i] = (sum[i - 1] + read())  % mod;
	int opt,l,r,x = 1;
	while(m --)
	{
		opt = read();l = read();r = read();
		if(opt == 1)
		{
//			x = read();
			change(1,1,n,l,r,x);
		}
		else
		{
			printf("%lld\n",(sum[r] - sum[l - 1] + ask(1,1,n,l,r)) % mod);
		}
	}
//	fclose(stdin);fclose(stdout);
	return 0;
}
/*
1049358504
1000000009
49358495


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

const int maxn=300005;
const long long mdn=1000000009;
const long long csa=276601605;//383008016;
const long long csb=691504013;
const long long csc=308495997;
const long long ksb=308495996;
const long long ksc=691504012;

struct node{
	long long sm,lt1,lt2;
	int l,r;
	node* c[2];
};

long long a[maxn];
long long psb[maxn],psc[maxn];
int n;

node* nwnode(int l,int r){
	node* nw=new node;
	nw->l=l;nw->r=r;nw->sm=0;nw->lt1=0;nw->lt2=0;nw->c[0]=nw->c[1]=NULL;
	return nw;
}

void pu(node* rt){
	if(!rt) return;
	if(rt->l==rt->r) return;
	rt->sm=(rt->c[0]->sm+rt->c[1]->sm)%mdn;
}

void pd(node* rt){
	if(!rt) return;
	//rt->sm=(rt->sm+((((((rt->lt1*((((1-psb[rt->r-rt->l+1]+mdn)%mdn)*ksb)%mdn)%mdn))%mdn-(rt->lt2*(((1-psc[rt->r-rt->l+1]+mdn)%mdn)*ksc)%mdn)%mdn)%mdn+mdn)%mdn)%mdn*csa)%mdn)%mdn;
	rt->sm+=(((csa*rt->lt1)%mdn)*(((1ll-psb[rt->r-rt->l+2]+mdn)%mdn*ksb)%mdn))%mdn;
	rt->sm-=(((csa*rt->lt2)%mdn)*(((1ll-psc[rt->r-rt->l+2]+mdn)%mdn*ksc)%mdn))%mdn;
	rt->sm%=mdn;
	rt->sm+=mdn;
	rt->sm%=mdn;
	if(rt->l!=rt->r){
		rt->c[0]->lt1+=rt->lt1;rt->c[0]->lt2+=rt->lt2;
		rt->c[1]->lt1+=rt->lt1*psb[(rt->l+rt->r )/2-rt->l];rt->c[1]->lt2+=rt->lt2*psc[(rt->l+rt->r )/2-rt->l];
		rt->c[0]->lt1%=mdn;rt->c[0]->lt2%=mdn;rt->c[1]->lt1%=mdn;rt->c[1]->lt2%=mdn;
	}
	rt->lt1=0;
	rt->lt2=0;
}

node* bt(int l,int r){
	node* nw=nwnode(l,r);
	if(l==r){
		nw->sm=a[l];
	} else{
		nw->c[0]=bt(l,(l+r)/2);
		nw->c[1]=bt((l+r)/2+1,r);
		pu(nw);
	}
	return nw;
}

void chg(node* rt,int l,int r,long long k1,long long k2){
	int cl=rt->l,cr=rt->r,cm=(cl+cr)/2;
	pd(rt);
	if(cl==l&&cr==r){
		rt->lt1+=k1;rt->lt1%=mdn;
		rt->lt2+=k2;rt->lt2%=mdn;
		pd(rt);
		return;
	}else if(r<=cm){
		chg(rt->c[0],l,r,k1,k2);
	}else if(l>cm){
		chg(rt->c[1],l,r,k1,k2);
	}else{
		chg(rt->c[0],l,cm,k1,k2);
		chg(rt->c[1],cm+1,r,(k1*psb[cm-l])%mdn,(k2*psc[cm-l])%mdn);
	}
	pd(rt->c[0]);pd(rt->c[1]);pu(rt);
}

long long qry(node* rt,int l,int r){
	int cl=rt->l,cr=rt->r,cm=(cl+cr)/2;
	pd(rt);
	if(cl==l&&cr==r){
		return rt->sm;
	}else if(r<=cm){
		return qry(rt->c[0],l,r);
	}else if(l>cm){
		return qry(rt->c[1],l,r);
	}else{
		return (qry(rt->c[0],l,cm)+qry(rt->c[1],cm+1,r))%mdn;
	}
}

void dfs(node* rt){
	if(!rt) return;
	cout<<rt->l<<rt->r<<':'<<rt->sm<<'/'<<rt->lt1<<'/'<<rt->lt2<<endl;
	dfs(rt->c[0]);
	dfs(rt->c[1]);
}
int main(){
	psb[0]=1;psc[0]=1;
	for(int i=1;i<maxn;i++) psb[i]=(psb[i-1]*csb)%mdn;
	for(int i=1;i<maxn;i++) psc[i]=(psc[i-1]*csc)%mdn;/*
	node* rt=new node;rt->sm=0;rt->lt1=1;rt->lt2=1;rt->l=1;rt->r=2;
	rt->sm+=(((csa*rt->lt1)%mdn)*(((1ll-psb[rt->r-rt->l+1]+mdn)%mdn*ksb)%mdn))%mdn;
	rt->sm-=(((csa*rt->lt2)%mdn)*(((1ll-psc[rt->r-rt->l+1]+mdn)%mdn*ksc)%mdn))%mdn;
	rt->sm%=mdn;
	rt->sm+=mdn;
	rt->sm%=mdn;
	cout<<rt->sm;*/
	int q;
	cin>>n>>q;

	for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);
	node* rt=bt(1,n);
	while(q--){
		long long op,l,r;
		scanf("%I64d%I64d%I64d",&op,&l,&r);
		switch(op){
			case 1:
				chg(rt,l,r,1,1);
				break;
			case 2:
				printf("%I64d\n",qry(rt,l,r));
				break;
		}
		//dfs(rt);
	}
	return 0;
}


#include<bits/stdc++.h>
#define mod 1000000009
#define five 383008016
#define five1 691504013
#define five2 308495997
using namespace std;
int n,m;
long long a[300005];
int op,L,R;

int sqrtn;
int bl[300005];//block
int l[1005],r[1005],tt;
int siz[1005];//size
long long lazy1[1005],lazy2[1005];
long long sum[1005];

long long f[300005];
long long fs[300005];
inline void init()
{
	f[1]=f[2]=1;
	for(int i=3;i<=300000;i++) f[i]=(f[i-1]+f[i-2])%mod;
	for(int i=1;i<=300000;i++) fs[i]=(fs[i-1]+f[i])%mod;
}

inline void inblock()
{
	for(int i=1;i<=n/sqrtn;i++)
	{
		tt++;
		l[tt]=r[tt-1]+1;
		r[tt]=r[tt-1]+sqrtn;
		siz[tt]=r[tt]-l[tt]+1;
		for(int j=l[tt];j<=r[tt];j++) bl[j]=tt;
	}
	if(sqrtn*sqrtn!=n)
	{
		tt++;l[tt]=r[tt-1]+1;r[tt]=n;siz[tt]=r[tt]-l[tt]+1;
		for(int j=l[tt];j<=r[tt];j++) bl[j]=tt;
	}
}

long long mi(long long n,long long p)
{
	if(n==0) return 0;
    if(p==0) return 1;
	long long yuan=1,mul=n;
	while(p)
    {
        if(p&1) yuan*=mul;
        yuan%=mod;
        mul*=mul;
        mul%=mod;
        p>>=1;
    }
    return yuan%mod;
}

inline void insert()
{
	if(bl[L]==bl[R])
	{
		int tot=1;
		for(int i=L;i<=R;i++)
		{
			a[i]+=f[tot]%mod; a[i]%=mod;
			tot++;
		}
		sum[bl[L]]+=fs[tot-1]%mod; sum[bl[L]]%=mod;
		return ;
	}

	int tot=1;
	for(int i=L;i<=r[bl[L]];i++)
	{
		a[i]+=f[tot]%mod; a[i]%=mod;
		sum[bl[L]]+=f[tot]%mod; sum[bl[L]]%=mod;
		tot++;
	}
	for(int i=bl[L]+1;i<bl[R];i++)
	{
		lazy1[i]+=mi(five1,tot)%mod;
		lazy2[i]+=mi(five2,tot)%mod;
		sum[i]+=fs[tot+siz[i]-1]-fs[tot-1]; sum[i]%=mod;
		tot+=siz[i];
	}
	for(int i=l[bl[R]];i<=R;i++)
	{
		a[i]+=f[tot]%mod; a[i]%=mod;
		sum[bl[R]]+=f[tot]%mod; sum[bl[R]]%=mod;
		tot++;
	}
}

inline void push_down()
{
	if(lazy1[bl[L]]!=0 || lazy2[bl[L]]!=0)
	{
		int tot=0;
		for(int i=l[bl[L]];i<=r[bl[L]];i++)
		{
			a[i]+=lazy1[bl[L]]*mi(five1,tot)%mod*mi(five,mod-2)%mod;
			a[i]-=lazy2[bl[L]]*mi(five2,tot)%mod*mi(five,mod-2)%mod;
			tot++;
		}
		lazy1[bl[L]]=lazy2[bl[L]]=0;
	}
	if(lazy1[bl[R]]!=0 || lazy2[bl[R]]!=0)
	{
		int tot=0;
		for(int i=l[bl[R]];i<=r[bl[R]];i++)
		{
			a[i]+=lazy1[bl[R]]*mi(five1,tot)%mod*mi(five,mod-2)%mod;
			a[i]-=lazy2[bl[R]]*mi(five2,tot)%mod*mi(five,mod-2)%mod;
			tot++;
		}
		lazy1[bl[R]]=lazy2[bl[R]]=0;
	}
//	cout<<"pushed:"<<endl;
//	for(int i=1;i<=n;i++) cout<<a[i]<<" "; cout<<endl;
}

inline void ask()
{
	long long anss=0;
	push_down();

	if(bl[L]==bl[R])
	{
		for(int i=L;i<=R;i++)
		{
			anss+=a[i]%mod;
			anss%=mod;
		}
		cout<<anss<<endl;
		return ;
	}

	for(int i=L;i<=r[bl[L]];i++)
	{
		anss+=a[i]%mod;
		anss%=mod;
	}
	for(int i=l[bl[R]];i<=R;i++)
	{
		anss+=a[i]%mod;
		anss%=mod;
	}
	for(int i=bl[L]+1;i<bl[R];i++)
	{
		anss+=sum[i]%mod;
		anss%=mod;
	}
	cout<<(anss%mod+mod+mod)%mod<<endl;
	return ;
}

int main()
{
//	freopen("rd.in","r",stdin);
//	freopen("my.out","w",stdout);
	ios::sync_with_stdio(0);
	cin>>n>>m;
	sqrtn=pow(n,0.55);
	inblock();
	init();
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		sum[bl[i]]+=a[i];
		sum[bl[i]]%=mod;
	}

//	for(int i=1;i<=n;i++) cout<<bl[i]<<" "; cout<<endl;
//	for(int i=1;i<=tt;i++) cout<<sum[i]<<" "; cout<<endl;
//	cout<<endl;
	while(m--)
	{
		cin>>op>>L>>R;
		if(op==1)
		{
			insert();
//			cout<<endl;
//			for(int i=1;i<=n;i++) cout<<a[i]<<" "; cout<<endl;
//			for(int i=1;i<=tt;i++) cout<<sum[i]<<" "; cout<<endl;
//			cout<<endl;
		}
		else
		{
			ask();
		}
	}
}


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define R register
#define LL long long
const int MAXN=3e5+10;
const int Mod=1e9+9;

inline int read() {
	int x=0,f=1; char a=getchar();
	for(;a>'9'||a<'0';a=getchar()) if(a=='-') f=-1;
	for(;a>='0'&&a<='9';a=getchar()) x=x*10+a-'0';
	return x*f;
}

inline int add(int x,int y) {
	int res=x+y;
	if(res<0) res+=Mod;
	return res>=Mod?res-Mod:res;
}

int n,m;
int f[MAXN];
inline int Fib(int x,int y,int id) {
	if(id==1) return x;
	if(id==2) return y;
	return (1LL*f[id-1]*x+1LL*f[id-2]*y)%Mod;
}
inline int Fibsum(int x,int y,int id) {
	if(id==1) return x;
	if(id==2) return add(x,y);
	return add(Fib(x,y,id+2),-Fib(x,y,2));
}

#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
struct Node {
	int v1,v2,sum;
}t[MAXN<<2];
#define v1(x) t[x].v1
#define v2(x) t[x].v2
#define sum(x) t[x].sum

inline void update(int x) { sum(x)=add(sum(ls(x)),sum(rs(x))); }

inline void get(int x,int a,int b,int l,int r) {
	v1(x)=add(a,v1(x)); v2(x)=add(b,v2(x));
	sum(x)=add(Fibsum(a,b,r-l+1),sum(x));
	//printf("%d\n",Fib(1,1,6));
}

inline void pushdown(int x,int l,int r) {
	if(v1(x)) {
		int mid=((l+r)>>1);
		get(ls(x),v1(x),v2(x),l,mid);
		int a=Fib(v1(x),v2(x),mid-l+2),
			b=Fib(v1(x),v2(x),mid-l+3);
		get(rs(x),a,b,mid+1,r);
		v1(x)=v2(x)=0;
	}
}
inline void change(int x,int l,int r,int Le,int Ri) {
	if(l>=Le&&r<=Ri) {
		//printf("%d %d %d\n",x,f[l-Le+1],f[l-Le+2]);
		get(x,f[l-Le+1],f[l-Le+2],l,r);
		return ;
	}
	pushdown(x,l,r);
	int mid=(l+r); mid>>=1;
	if(Le<=mid) change(ls(x),l,mid,Le,Ri);
	if(Ri>mid) change(rs(x),mid+1,r,Le,Ri);
	update(x);
}
inline int ask(int x,int l,int r,int Le,int Ri) {
	if(l>=Le&&r<=Ri) return sum(x);
	pushdown(x,l,r);
	int mid=l+r;mid>>=1; int ans=0;
	if(Le<=mid) ans=add(ans,ask(ls(x),l,mid,Le,Ri));
	if(Ri>mid) ans=add(ans,ask(rs(x),mid+1,r,Le,Ri));
	update(x); return ans;
}
int sm[MAXN];
int main() {
//	freopen("a.in","r",stdin);
	n=read(); m=read();
	f[1]=f[2]=1;
	for(R int i=3;i<=n+2;i++) f[i]=add(f[i-1],f[i-2]);
	for(R int i=1;i<=n;i++) sm[i]=add(sm[i-1],read());
	//for(R int i=1;i<=n;i++) printf("%d\n",sm[i]);
	while(m--) {
		if(read()==1) {
			int x=read(),y=read();
			change(1,1,n,x,y);
		}
		else {
			int x=read(),y=read();
			printf("%d\n",add(ask(1,1,n,x,y),sm[y]-sm[x-1]));
		}
	}
	return 0;
}


#include<cstdio>
#include<iostream>
#define int long long
using namespace std;
const int mod = 1e9 + 9;
const int N = 300005;
int n,m;
long long f[N << 1],a[N],sum[N];
struct node{
	long long f1,f2,v;
	node(long long f1 = 0,long long f2 = 0,long long v = 0):f1(f1),f2(f2),v(v){};
}tr[N << 5];
void init()
{
	f[0] = 0;f[1] = 1;
	for(int i = 2;i <= 300000;i ++)	f[i] = (f[i - 1] + f[i - 2]) % mod;
}/*
void update(int k,int len)
{
	tr[k].f1 %= mod;	tr[k].f2 %= mod;
	tr[k].v = (((tr[k << 1].v + tr[k << 1 | 1].v) % mod + tr[k].f1 * f[len] % mod + tr[k].f2 * f[len + 1] % mod - tr[k].f2) % mod + mod) % mod;
}*/
void update(int rt,int pos)
{
	int ls = (rt << 1),rs = (rt << 1 | 1);
    tr[rt].f1%=mod,tr[rt].f2%=mod;
    tr[rt].v=tr[ls].v+tr[rs].v+(tr[rt].f1*f[pos]+tr[rt].f2*f[pos+1]-tr[rt].f2),tr[rt].v%=mod;
//    cout <<t[ls].v << " " << t[rs].v << endl;
}/*
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 | 1].f1 += (tr[k].f1 * f[mid - l] % mod + tr[k].f2 * f[mid - l + 1] % mod) % mod;
	tr[k << 1].f2 += tr[k].f2;
	tr[k << 1 | 1].f2 += (tr[k].f1 * f[mid - l + 1] % mod + tr[k].f2 * f[mid - l + 2] % mod) % mod;
	tr[k].f1 = tr[k].f2 = 0;
	update(k << 1,mid - l + 1);	update(k << 1 | 1,r - mid);
}*/
void down(int rt,int l,int r)
{
    if(tr[rt].f1==0&&tr[rt].f2==0)return ;
    int mid=(l+r)>>1,ls = (rt << 1),rs = (rt << 1 | 1);
    tr[ls].f1+=tr[rt].f1,tr[rs].f1+=tr[rt].f1*f[mid-l]+tr[rt].f2*f[mid-l+1];
    tr[ls].f2+=tr[rt].f2,tr[rs].f2+=tr[rt].f1*f[mid-l+1]+tr[rt].f2*f[mid-l+2];
    tr[rt].f1=tr[rt].f2=0;
    update(ls,mid-l+1),update(rs,r-mid);
}
long long ask(int k,int l,int r,int x,int y)
{
	if(x <= l && r <= y)	return tr[k].v %= mod;
	down(k,l,r);
	int mid = (l + r) >> 1;
	long long ans = 0;
	if(x <= mid)	ans = (ans + ask(k << 1,l,mid,x,y)) % mod;
	if(y > mid)		ans = (ans + ask(k << 1 | 1,mid + 1,r,x,y)) % mod;
	return ans;
}/*
void change(int k,int l,int r,int x,int y,int em)
{
	if(x <= l && r <= y)
	{
		tr[k].f1 = (tr[k].f1 + f[em + l - x + 1]) % mod;
		tr[k].f2 = (tr[k].f2 + f[em + l - x + 2]) % mod;
		update(k,r - l + 1);
		return;
	}
	down(k,l,r);
	int mid = (l + r) >> 1;
	if(x <= mid)	change(k << 1,l,mid,x,y,em);
	if(y > mid)		change(k << 1 | 1,mid + 1,r,x,y,em);
	update(k,r - l + 1);
}*/
void change(int rt,int l,int r,int L,int R)
{
    if(L<=l&&r<=R)//边界条件
    {
        tr[rt].f1+=f[l-L+1];
        tr[rt].f2+=f[l-L+2];
        tr[rt].f1%=mod,tr[rt].f2%=mod;
        update(rt,r-l+1);
        return ;
    }
    down(rt,l,r);
    int mid=(l+r)>>1,ls = (rt << 1),rs = (rt << 1 | 1);
    if(L<=mid)change(ls,l,mid,L,R);
    if(mid<R)change(rs,mid+1,r,L,R);
    update(rt,r-l+1);
}
/*
signed main()
{
//	freopen("d.in","r",stdin);
//	freopen("d.out","w",stdout);
	init();
	scanf("%lld%lld",&n,&m);
	for(int i = 1;i <= n;i ++)	scanf("%lld",&a[i]);
	for(int i = 1;i <= n;i ++)	sum[i] = sum[i - 1] + a[i];
	for(int i = 1,opt,l,r,x;i <= m;i ++)
	{
		scanf("%lld%lld%lld",&opt,&l,&r);
		if(opt == 2)	printf("%lld\n",((ask(1,1,n,l,r) + sum[r] - sum[l - 1]) % mod + mod) % mod);
		else
		{
//			scanf("%d",&x);
			change(1,1,n,l,r,0);
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}*/
signed main()
{
    scanf("%lld%lld",&n,&m);
    init();
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];//预处理前缀和

    while(m--)
    {
        int opt,l,r;
        scanf("%lld%lld%lld",&opt,&l,&r);
        if(opt==1)change(1,1,n,l,r);
        else printf("%lld\n",(ask(1,1,n,l,r)+sum[r]-sum[l-1]+mod)%mod);
//        for(int i = 1;i <= n * 4;i ++)	cout << t[i].f1 << " " << t[i].f2 << " " << t[i].v << endl;
    }

    return 0;
}
/*
5 3
1 2 3 4 5
1 1 5
2 1 5 2
1 1 5
*/
/*
5 3
1 2 3 4 5
1 1 5
2 1 1 2
1 1 5
*/


#include<cstdio>
using namespace std;
typedef long long ll;
const int N=300005;
const ll mod=1e9+9;
ll MOD(ll x){return (x%mod+mod)%mod;}
ll f[N],fs[N];
struct node
{
	int lc,rc;ll l,r,c,a,b;
}tr[N<<1];int trlen=0;
void bt(ll l,ll r)
{
	int now=++trlen;
	tr[now].l=l;tr[now].r=r;tr[now].c=0;
	tr[now].lc=tr[now].rc=-1;
	tr[now].a=tr[now].b=0;
	if(l<r)
	{
		ll mid=(l+r)/2;
		int lc=tr[now].lc=trlen+1;bt(l,mid);
		int rc=tr[now].rc=trlen+1;bt(mid+1,r);
		tr[now].c=tr[lc].c+tr[rc].c;
	}
	else scanf("%lld",&tr[now].c);
}
void lz(int now)
{
	int lc=tr[now].lc,rc=tr[now].rc;
	ll l=tr[lc].l,mid=tr[lc].r,r=tr[rc].r;

	ll la=MOD(tr[now].a);
	ll lb=MOD(tr[now].b);
	tr[lc].c=MOD(tr[lc].c+la*f[mid-l+1]+lb*f[mid-l+2]-lb);
	tr[lc].a=MOD(tr[lc].a+la);
	tr[lc].b=MOD(tr[lc].b+lb);

	ll ra=MOD(tr[now].a*f[mid-l]+tr[now].b*f[mid-l+1]);
	ll rb=MOD(tr[now].a*f[mid-l+1]+tr[now].b*f[mid-l+2]);
	tr[rc].c=MOD(tr[rc].c+ra*f[r-mid]+rb*f[r-mid+1]-rb);
	tr[rc].a=MOD(tr[rc].a+ra);
	tr[rc].b=MOD(tr[rc].b+rb);

	tr[now].a=tr[now].b=0;
}
void change(int now,ll l,ll r,ll L,ll R)
{
	if(tr[now].l==l&&tr[now].r==r)
	{
		tr[now].a=MOD(tr[now].a+f[l-L+1]);
		tr[now].b=MOD(tr[now].b+f[l-L+2]);
		tr[now].c=MOD(tr[now].c+MOD(fs[r-L+1]-fs[l-L]));
		return ;
	}
	ll mid=(tr[now].l+tr[now].r)>>1;
	int lc=tr[now].lc,rc=tr[now].rc;
	if(tr[now].a||tr[now].b)lz(now);
	if(r<=mid)change(lc,l,r,L,R);
	else if(mid+1<=l)change(rc,l,r,L,R);
	else change(lc,l,mid,L,R),change(rc,mid+1,r,L,R);
	tr[now].c=MOD(tr[lc].c+tr[rc].c);
}
int solve(int now,ll l,ll r)
{
	if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
	ll mid=(tr[now].l+tr[now].r)>>1;
	int lc=tr[now].lc,rc=tr[now].rc;
	if(tr[now].a||tr[now].b)lz(now);
	if(r<=mid)return solve(lc,l,r);
	else if(mid+1<=l)return solve(rc,l,r);
	else return MOD(solve(lc,l,mid)+solve(rc,mid+1,r));
}
int main()
{
	int n,m;scanf("%d%d",&n,&m);
	bt(1,n);
	f[1]=f[2]=1;for(int i=3;i<=n+1;i++)f[i]=MOD(f[i-1]+f[i-2]);
	fs[1]=1;for(int i=2;i<=n+1;i++)fs[i]=MOD(fs[i-1]+f[i]);
	while(m--)
	{
		int cz;ll l,r;scanf("%d%lld%lld",&cz,&l,&r);
		if(cz==1)change(1,l,r,l,r);
		else printf("%lld\n",solve(1,l,r));
	}
	return 0;
}


#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;
#define ls (now<<1)
#define rs (now<<1|1)
const int maxn = 1e6+10;
const int mod = 1e9+9;

long long n,m,x,y,op;
long long a[maxn],f[maxn];

struct tree {
	long long sum,c1,c2;
} t[maxn];

int read() {
	int x = 0,f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while('0' <= ch && ch <= '9') {
		x = (x<<3)+(x<<1) + ch-'0';
		ch = getchar();
	}
	return x * f;
}

long long getx(long long a1,long long a2,long long x) {
	if(x == 1) return a1;
	if(x == 2) return a2;
	return ( a1*f[x-2] + a2*f[x-1] ) % mod;
}

long long getsum(long long a1,long long a2,long long x) {
	if(x == 1) return a1;
	if(x == 2) return (a1+a2) % mod;
	return ( getx(a1,a2,x+2) - a2 + mod ) % mod;
}

void pushup(int now) {
	t[now].sum = (t[ls].sum + t[rs].sum) % mod;
}

void pushdown(int l,int r,int now) {
	if(!t[now].c1) return;
	int mid = (l+r)>>1;
	long long a1,a2;
	a1 = t[now].c1;
	a2 = t[now].c2;
	t[ls].c1 = (t[ls].c1 + a1) % mod;
	t[ls].c2 = (t[ls].c2 + a2) % mod;
	t[ls].sum = (t[ls].sum + getsum(a1,a2,mid-l+1)) % mod;
	a1 = getx(t[now].c1,t[now].c2,mid-l+2);
	a2 = getx(t[now].c1,t[now].c2,mid-l+3);
	t[rs].c1 = (t[rs].c1 + a1) % mod;
	t[rs].c2 = (t[rs].c2 + a2) % mod;
	t[rs].sum = (t[rs].sum + getsum(a1,a2,r-mid)) % mod;
	t[now].c1 = t[now].c2 = 0;
}

void modify(int L,int R,int l,int r,int now) {
	if(L <= l && r <= R) {
		t[now].c1 = (t[now].c1 + f[l-L+1]) % mod;
		t[now].c2 = (t[now].c2 + f[l-L+2]) % mod;
		t[now].sum = (t[now].sum + getsum(f[l-L+1],f[l-L+2],r-l+1)) % mod;
		return;
	}
	pushdown(l,r,now);
	int mid = (l+r)>>1;
	if(L <= mid) modify(L,R,l,mid,ls);
	if(R > mid) modify(L,R,mid+1,r,rs);
	pushup(now);
}

long long query(int L,int R,int l,int r,int now) {
	long long ans = 0;
	if(L <= l && r <= R) {
		ans = t[now].sum;
		return (ans + mod) % mod;
	}
	pushdown(l,r,now);
	int mid = (l+r)>>1;
	if(L <= mid) ans = (ans + query(L,R,l,mid,ls)) % mod;
	if(R > mid) ans = (ans + query(L,R,mid+1,r,rs)) % mod;
	return (ans+mod)%mod;
}

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

int main() {
	n = read(),m = read();
	for(int i = 1; i <= n; i++) {
		x = read();
		a[i] = (a[i-1] + x) % mod;
	}
	init();
	while(m--) {
		op = read();
		x = read(), y = read();
		if(op == 1) modify(x,y,1,n,1);
		if(op == 2) printf("%lld\n",((a[y]-a[x-1]+query(x,y,1,n,1))%mod+mod)%mod);
	}
	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);
}
#undef LEN
#define L max(now_left,left)
#define R min(now_right,right)
#define LEN (L-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;
	}
	tree[now].sum+=
	CalcSum(f[LEN],f[LEN+1],R-L+1);
	tree[now].sum=Mod(tree[now].sum);
	if(now_left<=left&&right<=now_right)
	{
		tree[now].first=Mod(tree[now].first+f[LEN]);
		tree[now].second=Mod(tree[now].second+f[LEN+1]);
		return;
	}
	Updata(NOW,LEFT);
	Updata(NOW,RIGHT);
}
#undef LEN
#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;
	}
	return Mod(CalcSum(CalcNext(TWO,L-left+1),CalcNext(TWO,L-left+2),R-L+1)+Mod(Query(NOW,LEFT)+Query(NOW,RIGHT)));
}
#undef L
#undef R
#undef TWO
#undef LSON
#undef RSON
#undef MIDDLE
#undef LEFT
#undef RIGHT
#undef NOW
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 <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define eps 1e-6
#define LL long long
using namespace std;
const int MAXN = 1500000;
const int MOD = 1e9 + 9;
LL bas = 276601605, q1 = 691504013, q2 = 308495997, mul1[MAXN] = {1}, mul2[MAXN] = {1}, s[MAXN];
int c[MAXN], n, k;
struct Node {
	LL a, b, sum;
} node[MAXN];
void build(int flag, int l, int r) {
	node[flag].a = node[flag].b = node[flag].sum = 0;
	if(l == r) return;
	int m = (l+r) >> 1;
	build(flag << 1, l, m);
	build((flag << 1) + 1, m + 1, r);
}
void push_down(int flag, int l, int r) {
	LL aa = node[flag].a, bb = node[flag].b;
	if(!aa && !bb) return;
	int lc = flag << 1, rc = (flag << 1) | 1, mid = (l + r) >> 1,len1 = mid - l + 1, len2 = r - mid;
	node[lc].a = (node[lc].a + aa) % MOD, node[lc].b = (node[lc].b + bb) % MOD;
	node[lc].sum = (node[lc].sum + aa * (mul1[len1 + 2] - mul1[2])) % MOD;
	node[lc].sum = (node[lc].sum - bb * (mul2[len1 + 2] - mul2[2])) % MOD;
	node[rc].a = (node[rc].a + aa * mul1[len1]) % MOD, node[rc].b = (node[rc].b + bb * mul2[len1]) % MOD;
	node[rc].sum = (node[rc].sum + aa * mul1[len1] % MOD * (mul1[len2 + 2] - mul1[2]) % MOD) % MOD;
	node[rc].sum = (node[rc].sum - bb * mul2[len1] % MOD * (mul2[len2 + 2] - mul2[2]) % MOD) % MOD;
	node[flag].a = node[flag].b = 0;
}
void push_up(int flag) {
	node[flag].sum = (node[flag << 1].sum + node[(flag << 1) | 1].sum) % MOD;
}
LL query(int flag, int l, int r, int ql, int qr) {
	if(l == ql && r == qr) return node[flag].sum;
	push_down(flag, l, r);
	int mid = (l + r) >> 1;
	if(qr <= mid) return query(flag << 1, l, mid, ql, qr);
	else if(ql > mid) return query((flag << 1) | 1, mid + 1, r, ql, qr);
	else return (query(flag << 1, l, mid, ql, mid) + query((flag << 1) | 1, mid + 1, r, mid + 1, qr)) % MOD;
}
void update(int flag, int l, int r, int ql, int qr, LL x, LL y) {
	if(l == ql && r == qr) {
		node[flag].a = (node[flag].a + x) % MOD, node[flag].b = (node[flag].b + y) % MOD;
		node[flag].sum = (node[flag].sum + x * (mul1[r - l + 3] - mul1[2])) % MOD;
		node[flag].sum = (node[flag].sum - y * (mul2[r - l + 3] - mul2[2])) % MOD;
		return;
	}
	push_down(flag, l, r);
	int mid = (l + r) >> 1;
	if(qr <= mid) update(flag << 1, l, mid, ql, qr, x, y);
	else if(ql > mid) update((flag << 1) | 1, mid + 1, r, ql, qr, x, y);
	else {
		int len = mid - ql + 1;
		update(flag << 1, l, mid, ql, mid, x, y);
		update((flag <<1 ) | 1, mid + 1, r, mid + 1, qr, x * mul1[len] % MOD, y * mul2[len] % MOD);
	}
	push_up(flag);
}
int main() {
// 	freopen("input.txt", "r", stdin);
	scanf("%d%d", &n, &k);
	for(int i = 1; i <= n; i++) scanf("%d", &c[i]), s[i] = s[i-1] + c[i];
	for(int i = 1; i <= 301000; i++) mul1[i] = mul1[i-1] * q1 % MOD, mul2[i] = mul2[i-1] * q2 % MOD;
	build(1, 1, n);
	for(int i = 1, op, l, r; i <= k; i++) {
		scanf("%d%d%d", &op, &l, &r);
		if(op == 1) update(1, 1, n, l, r, 1, 1);
		else {
			LL ans = (bas * query(1, 1, n, l, r) % MOD + s[r] - s[l - 1]) % MOD;
			if(ans < 0) ans += MOD;
			printf("%lld\n", ans);
		}
	}
	return 0;
}


#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 300500
#define mod 1000000007
using namespace std;

inline int read() {
	int x = 0,f = 1; char s = getchar();
	while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
	while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
	return x * f;
}

int n,m;
struct node {
	int f0,f1;
	node() {}
	node(int a,int b) {
		f0 = a; if(f0 >= mod) f0 -= mod;
		f1 = b; if(f1 >= mod) f1 -= mod;
	}
}F[N],S[N];
int val[N];
struct Tree {
	int Sum,laz[2];
}tr[N * 4];

inline node Puls(const node &a,const node &b) {
	return node((a.f0 + b.f0) % mod,(a.f1 + b.f1) % mod);
}

inline int Mul(const node &a,const node &b) {
	return ((1ll * a.f0 % mod * b.f0 % mod) % mod + (1ll * a.f1 % mod * b.f1 % mod) % mod) % mod;
}

inline void Update(int k) {
	tr[k].Sum = (tr[k << 1].Sum + tr[k << 1 | 1].Sum) % mod;
}

inline void Built(int k,int l,int r) {
	if(l == r) {
		tr[k].Sum = val[l];
		return ;
	}
	int mid = (l + r) >> 1;
	Built(k << 1,l,mid); Built(k << 1 | 1,mid + 1,r);
	Update(k);
}

inline void Pushup(int k,int l,int r,int a,int b) {
	tr[k].laz[0] = (tr[k].laz[0] + a) % mod;
	tr[k].laz[1] = (tr[k].laz[1] + b) % mod;
	tr[k].Sum = (tr[k].Sum % mod + Mul(node(a,b),S[r - l]) % mod) % mod;
}

inline void Pushdn(int k,int l,int r) {
	if(tr[k].laz[0] || tr[k].laz[1]) {
		int mid = (l + r) >> 1;
		Pushup(k << 1,l,mid,tr[k].laz[0],tr[k].laz[1]);
		int A = Mul(node(tr[k].laz[0],tr[k].laz[1]),F[mid - l + 1]);
		int B = Mul(node(tr[k].laz[0],tr[k].laz[1]),F[mid - l + 2]);
		Pushup(k << 1 | 1,mid + 1,r,A,B);
		tr[k].laz[0] = tr[k].laz[1] = 0;
	}
}

inline void Change(int k,int l,int r,int a,int b,int f0,int f1) {
	if(a <= l && r <= b) {
		int A = Mul(node(f0,f1),F[l - a]);
		int B = Mul(node(f0,f1),F[l - a + 1]);
		Pushup(k,l,r,A,B);
		return ;
	}
	Pushdn(k,l,r); int mid = (l + r) >> 1;
	if(a <= mid) Change(k << 1,l,mid,a,b,f0,f1);
	if(b > mid) Change(k << 1 | 1,mid + 1,r,a,b,f0,f1);
	Update(k);
}

inline int Qurry(int k,int l,int r,int a,int b) {
	if(a <= l && r <= b) return tr[k].Sum % mod;
	Pushdn(k,l,r); int mid = (l + r) >> 1,res = 0;
	if(a <= mid) res = (res + Qurry(k << 1,l,mid,a,b) % mod) % mod;
	if(b > mid) res = (res + Qurry(k << 1 | 1,mid + 1,r,a,b) % mod) % mod;
	return res % mod;
}

int main() {
//	freopen("d.in","r",stdin);
//	freopen("d.out","w",stdout);

	F[0] = node(1,0); F[1] = node(0,1);
	for(int i = 2;i <= N;i ++) F[i] = Puls(F[i - 1],F[i - 2]);
	S[0] = node(1,0);
	for(int i = 1;i <= N;i ++) S[i] = Puls(S[i - 1],F[i]);
	n = read(),m = read();
	for(int i = 1;i <= n;i ++) val[i] = read();
	Built(1,1,n);
	for(int i = 1;i <= m;i ++) {
		int opt = read();
		if(opt == 2) {
			int l = read(),r = read();
			printf("%d\n",Qurry(1,1,n,l,r) % mod);
		}
		else {
			int l = read(),r = read();
			Change(1,1,n,l,r,F[1].f1,F[1 + 1].f1);
		}
	}
	return 0;
}

/*
5 3
1 2 3 4 5
1 1 5
2 1 5 2
1 1 5
*/


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100000
#define MOD 1000000009
using namespace std;

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()
{
//	freopen("rd.in","r",stdin);
//	freopen("std.out","w",stdout);
	read(n),read(m);
	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>=sqrt(n)) rebuild();
		}
		else
			printf("%lld\n",getans(L,R));
	}
	return 0;
}


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

inline int read()
{
	char c=getchar(); int 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(int p)
{
	t[p]=(t[ls]+t[rs])%mod;
}

inline ll cal(ll x,ll y,int 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,int 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(int l,int r,int p)
{
	if(l==r) {
		t[p]=a[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls);
	build(mid+1,r,rs);
	push_up(p);
}

void push_down(int l,int r,int p)
{
	if(val[p]) {
		int 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(int l,int r,int ql,int qr,int x,int y,int 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 ;
	}
	int 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,qr,x,y,ls);
		T tp=fibcal((T){x,y},mid-l);
		update(mid+1,r,ql,qr,tp.x,tp.y,rs);
	}
	push_up(p);
}

int query(int l,int r,int ql,int qr,int p)
{
	if(ql<=l&&r<=qr) return t[p]; int ans=0;
	int 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(int i=3;i<mxn;++i) f[i]=(f[i-1]+f[i-2])%mod;
	for(int i=1;i<=n;++i) a[i]=read()%mod;
	build(1,n,1); int opt,l,r;
	for(int i=1;i<=m;++i) {
		opt=read(); l=read(); r=read();
		if(opt==1) update(1,n,l,r,1,1,1);
		else printf("%d\n",query(1,n,l,r,1));
	}
}


#include<bits/stdc++.h>
using namespace std;
#define MOD 1000000009
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<=300000;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;
		}
	}
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100000
#define MOD 1000000009
using namespace std;

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);
	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>=sqrt(n)) rebuild();
		}
		else
			printf("%lld\n",getans(L,R));
	}
	return 0;
}


#include<cstdio>
#include<iostream>
#define int long long
using namespace std;
const int mod = 1e9 + 9;
const int N = 300005;
int n,m;
long long f[N << 1],a[N],sum[N];
struct node{
	long long f1,f2,v;
	node(long long f1 = 0,long long f2 = 0,long long v = 0):f1(f1),f2(f2),v(v){};
}tr[N << 5];
void init()
{
	f[0] = 0;f[1] = 1;
	for(int i = 2;i <= 300000;i ++)	f[i] = (f[i - 1] + f[i - 2]) % mod;
}/*
void update(int k,int len)
{
	tr[k].f1 %= mod;	tr[k].f2 %= mod;
	tr[k].v = (((tr[k << 1].v + tr[k << 1 | 1].v) % mod + tr[k].f1 * f[len] % mod + tr[k].f2 * f[len + 1] % mod - tr[k].f2) % mod + mod) % mod;
}*/
void update(int rt,int pos)
{
	int ls = (rt << 1),rs = (rt << 1 | 1);
    tr[rt].f1%=mod,tr[rt].f2%=mod;
    tr[rt].v=tr[ls].v+tr[rs].v+(tr[rt].f1*f[pos]+tr[rt].f2*f[pos+1]-tr[rt].f2),tr[rt].v%=mod;
//    cout <<t[ls].v << " " << t[rs].v << endl;
}/*
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 | 1].f1 += (tr[k].f1 * f[mid - l] % mod + tr[k].f2 * f[mid - l + 1] % mod) % mod;
	tr[k << 1].f2 += tr[k].f2;
	tr[k << 1 | 1].f2 += (tr[k].f1 * f[mid - l + 1] % mod + tr[k].f2 * f[mid - l + 2] % mod) % mod;
	tr[k].f1 = tr[k].f2 = 0;
	update(k << 1,mid - l + 1);	update(k << 1 | 1,r - mid);
}*/
void down(int rt,int l,int r)
{
//	cout << rt << endl;
    if(tr[rt].f1==0&&tr[rt].f2==0)return ;
    int mid=(l+r)>>1,ls = (rt << 1),rs = (rt << 1 | 1);
    tr[ls].f1+=tr[rt].f1,tr[rs].f1+=tr[rt].f1*f[mid-l]+tr[rt].f2*f[mid-l+1];
    tr[ls].f2+=tr[rt].f2,tr[rs].f2+=tr[rt].f1*f[mid-l+1]+tr[rt].f2*f[mid-l+2];
    tr[rt].f1=tr[rt].f2=0;
//    cout << t[ls].f2 << " " << t[rs].f2 << endl;
    update(ls,mid-l+1),update(rs,r-mid);
}
long long ask(int k,int l,int r,int x,int y)
{
	if(x <= l && r <= y)	return tr[k].v %= mod;
	down(k,l,r);
	int mid = (l + r) >> 1;
	long long ans = 0;
	if(x <= mid)	ans = (ans + ask(k << 1,l,mid,x,y)) % mod;
	if(y > mid)		ans = (ans + ask(k << 1 | 1,mid + 1,r,x,y)) % mod;
	return ans;
}
void change(int k,int l,int r,int x,int y,int em)
{
	if(x <= l && r <= y)
	{
		tr[k].f1 = (tr[k].f1 + f[em + l - x + 1]) % mod;
		tr[k].f2 = (tr[k].f2 + f[em + l - x + 2]) % mod;
		update(k,r - l + 1);
		return;
	}
	down(k,l,r);
	int mid = (l + r) >> 1;
	if(x <= mid)	change(k << 1,l,mid,x,y,em);
	if(y > mid)		change(k << 1 | 1,mid + 1,r,x,y,em);/**/
	update(k,r - l + 1);
}/*
signed main()
{
//	freopen("d.in","r",stdin);
//	freopen("d.out","w",stdout);
	init();
	scanf("%lld%lld",&n,&m);
	for(int i = 1;i <= n;i ++)	scanf("%lld",&a[i]);
	for(int i = 1;i <= n;i ++)	sum[i] = sum[i - 1] + a[i];
	for(int i = 1,opt,l,r,x;i <= m;i ++)
	{
		scanf("%lld%lld%lld",&opt,&l,&r);
		if(opt == 2)	printf("%lld\n",((ask(1,1,n,l,r) + sum[r] - sum[l - 1]) % mod + mod) % mod);
		else
		{
//			scanf("%d",&x);
			change(1,1,n,l,r,0);
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}*/
signed main()
{
    scanf("%lld%lld",&n,&m);
    init();
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];//预处理前缀和

    while(m--)
    {
        int opt,l,r;
        scanf("%lld%lld%lld",&opt,&l,&r);
        if(opt==1)change(1,1,n,l,r,0);
        else printf("%lld\n",(ask(1,1,n,l,r)+sum[r]-sum[l-1]+mod)%mod);
//        for(int i = 1;i <= n * 4;i ++)	cout << t[i].f1 << " " << t[i].f2 << " " << t[i].v << endl;
    }

    return 0;
}
/*
5 3
1 2 3 4 5
1 1 5
2 1 5 2
1 1 5
*/
/*
5 3
1 2 3 4 5
1 1 5
2 1 1 2
1 1 5
*/


#include<cstdio>
#include<iostream>
#define int long long
using namespace std;
const int N = 300005;
int n,m;
struct T{
    int f1,f2,v;
}tr[N*20];
int a[N],f[N],sum[N];
const int mod=1e9+9;
void init()
{
	f[0] = 0;f[1] = 1;
	for(int i = 2;i <= 300001;i ++)	f[i] = (f[i - 1] + f[i - 2]) % mod;
}/*
void update(int k,int len)
{
	tr[k].f1 %= mod;	tr[k].f2 %= mod;
	tr[k].v = (((tr[k << 1].v + tr[k << 1 | 1].v) % mod + tr[k].f1 * f[len] % mod + tr[k].f2 * f[len + 1] % mod - tr[k].f2) % mod + mod) % mod;
}*/
void update(int rt,int pos)
{
	int ls = (rt << 1),rs = (rt << 1 | 1);
    tr[rt].f1%=mod,tr[rt].f2%=mod;
    tr[rt].v=tr[ls].v+tr[rs].v+(tr[rt].f1*f[pos]+tr[rt].f2*f[pos+1]-tr[rt].f2),tr[rt].v%=mod;
//    cout <<t[ls].v << " " << t[rs].v << endl;
}/*
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 | 1].f1 += (tr[k].f1 * f[mid - l] % mod + tr[k].f2 * f[mid - l + 1] % mod) % mod;
	tr[k << 1].f2 += tr[k].f2;
	tr[k << 1 | 1].f2 += (tr[k].f1 * f[mid - l + 1] % mod + tr[k].f2 * f[mid - l + 2] % mod) % mod;
	tr[k].f1 = tr[k].f2 = 0;
	update(k << 1,mid - l + 1);	update(k << 1 | 1,r - mid);
}*/
void down(int rt,int l,int r)
{
    if(tr[rt].f1==0&&tr[rt].f2==0)return ;
    int mid=(l+r)>>1,ls = (rt << 1),rs = (rt << 1 | 1);
    tr[ls].f1+=tr[rt].f1,tr[rs].f1+=tr[rt].f1*f[mid-l]+tr[rt].f2*f[mid-l+1];
    tr[ls].f2+=tr[rt].f2,tr[rs].f2+=tr[rt].f1*f[mid-l+1]+tr[rt].f2*f[mid-l+2];
    tr[rt].f1=tr[rt].f2=0;
    update(ls,mid-l+1),update(rs,r-mid);
}/*
long long ask(int k,int l,int r,int x,int y)
{
	if(x <= l && r <= y)	return tr[k].v %= mod;
	down(k,l,r);
	int mid = (l + r) >> 1;
	long long ans = 0;
	if(x <= mid)	ans = (ans + ask(k << 1,l,mid,x,y)) % mod;
	if(y > mid)		ans = (ans + ask(k << 1 | 1,mid + 1,r,x,y)) % mod;
	return ans;
}*//*
void change(int k,int l,int r,int x,int y,int em)
{
	if(x <= l && r <= y)
	{
		tr[k].f1 = (tr[k].f1 + f[em + l - x + 1]) % mod;
		tr[k].f2 = (tr[k].f2 + f[em + l - x + 2]) % mod;
		update(k,r - l + 1);
		return;
	}
	down(k,l,r);
	int mid = (l + r) >> 1;
	if(x <= mid)	change(k << 1,l,mid,x,y,em);
	if(y > mid)		change(k << 1 | 1,mid + 1,r,x,y,em);
	update(k,r - l + 1);
}*/
int ask(int rt,int l,int r,int L,int R)
{
    if(L<=l&&r<=R)return tr[rt].v;
    down(rt,l,r);
    int res=0;
    int mid=(l+r)>>1,ls = (rt << 1),rs = (rt << 1 | 1);
    if(L<=mid)res+=ask(ls,l,mid,L,R);
    if(mid<R)res+=ask(rs,mid+1,r,L,R);
    return res%mod;
}
void change(int rt,int l,int r,int L,int R)
{
    if(L<=l&&r<=R)//边界条件
    {
        tr[rt].f1+=f[l-L+1];
        tr[rt].f2+=f[l-L+2];
        tr[rt].f1%=mod,tr[rt].f2%=mod;
        update(rt,r-l+1);
        return ;
    }
    down(rt,l,r);
    int mid=(l+r)>>1,ls = (rt << 1),rs = (rt << 1 | 1);
    if(L<=mid)change(ls,l,mid,L,R);
    if(mid<R)change(rs,mid+1,r,L,R);
    update(rt,r-l+1);
}
/*
signed main()
{
//	freopen("d.in","r",stdin);
//	freopen("d.out","w",stdout);
	init();
	scanf("%lld%lld",&n,&m);
	for(int i = 1;i <= n;i ++)	scanf("%lld",&a[i]);
	for(int i = 1;i <= n;i ++)	sum[i] = sum[i - 1] + a[i];
	for(int i = 1,opt,l,r,x;i <= m;i ++)
	{
		scanf("%lld%lld%lld",&opt,&l,&r);
		if(opt == 2)	printf("%lld\n",((ask(1,1,n,l,r) + sum[r] - sum[l - 1]) % mod + mod) % mod);
		else
		{
//			scanf("%d",&x);
			change(1,1,n,l,r,0);
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}*/
signed main()
{
    scanf("%lld%lld",&n,&m);
    init();
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];//预处理前缀和

    while(m--)
    {
        int opt,l,r;
        scanf("%lld%lld%lld",&opt,&l,&r);
        if(opt==1)change(1,1,n,l,r);
        else printf("%lld\n",(ask(1,1,n,l,r)+sum[r]-sum[l-1]+mod)%mod);
//        for(int i = 1;i <= n * 4;i ++)	cout << t[i].f1 << " " << t[i].f2 << " " << t[i].v << endl;
    }

    return 0;
}
/*
5 3
1 2 3 4 5
1 1 5
2 1 5 2
1 1 5
*/
/*
5 3
1 2 3 4 5
1 1 5
2 1 1 2
1 1 5
*/


#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;
#define ls (now<<1)
#define rs (now<<1|1)
const int maxn = 3e5+10;
const int mod = 1e9+9;

long long n,m,x,y,op;
long long a[maxn],f[maxn];

struct tree {
	long long sum,c1,c2;
} t[maxn];

int read() {
	int x = 0,f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while('0' <= ch && ch <= '9') {
		x = (x<<3)+(x<<1) + ch-'0';
		ch = getchar();
	}
	return x * f;
}

long long getx(long long a1,long long a2,long long x) {
	if(x == 1) return a1;
	if(x == 2) return a2;
	return ( a1*f[x-2] + a2*f[x-1] ) % mod;
}

long long getsum(long long a1,long long a2,long long x) {
	if(x == 1) return a1;
	if(x == 2) return (a1+a2) % mod;
	return ( getx(a1,a2,x+2) - a2 + mod ) % mod;
}

void pushup(int now) {
	t[now].sum = (t[ls].sum + t[rs].sum) % mod;
}

void pushdown(int l,int r,int now) {
	if(!t[now].c1) return;
	int mid = (l+r)>>1;
	long long a1,a2;
	a1 = t[now].c1;
	a2 = t[now].c2;
	t[ls].c1 = (t[ls].c1 + a1) % mod;
	t[ls].c2 = (t[ls].c2 + a2) % mod;
	t[ls].sum = (t[ls].sum + getsum(a1,a2,mid-l+1)) % mod;
	a1 = getx(t[now].c1,t[now].c2,mid-l+2);
	a2 = getx(t[now].c1,t[now].c2,mid-l+3);
	t[rs].c1 = (t[rs].c1 + a1) % mod;
	t[rs].c2 = (t[rs].c2 + a2) % mod;
	t[rs].sum = (t[rs].sum + getsum(a1,a2,r-mid)) % mod;
	t[now].c1 = t[now].c2 = 0;
}

void modify(int L,int R,int l,int r,int now) {
	if(L <= l && r <= R) {
		t[now].c1 = (t[now].c1 + f[l-L+1]) % mod;
		t[now].c2 = (t[now].c2 + f[l-L+2]) % mod;
		t[now].sum = (t[now].sum + getsum(f[l-L+1],f[l-L+2],r-l+1)) % mod;
		return;
	}
	pushdown(l,r,now);
	int mid = (l+r)>>1;
	if(L <= mid) modify(L,R,l,mid,ls);
	if(R > mid) modify(L,R,mid+1,r,rs);
	pushup(now);
}

long long query(int L,int R,int l,int r,int now) {
	long long ans = 0;
	if(L <= l && r <= R) {
		ans = t[now].sum;
		return (ans + mod) % mod;
	}
	pushdown(l,r,now);
	int mid = (l+r)>>1;
	if(L <= mid) ans = (ans + query(L,R,l,mid,ls)) % mod;
	if(R > mid) ans = (ans + query(L,R,mid+1,r,rs)) % mod;
	return (ans+mod)%mod;
}

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

int main() {
	n = read(),m = read();
	for(int i = 1; i <= n; i++) {
		x = read();
		a[i] = (a[i-1] + x) % mod;
	}
	init();
	while(m--) {
		op = read();
		x = read(), y = read();
		if(op == 1) modify(x,y,1,n,1);
		if(op == 2) printf("%lld\n",((a[y]-a[x-1]+query(x,y,1,n,1))%mod+mod)%mod);
	}
	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
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]) 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],fibs[i]=fibs[i-1]+fib[i];
    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);
            for(int j=1;j<=n;j++) query(1,1,n,j,j);
		}
        else printf("%lld\n",query(1,1,n,y,z));
    }
    return 0;
}


#include <iostream>
#include <cctype>
#include <string>
#pragma GCC optimize("O3")
#define PROB_NAME "you"
#ifdef KKSK
namespace xszq {
class istream {
public:
	istream();
	istream& operator>>(int&);
private:
	char *ptr;
	char *begin;
	bool lastSuccess;
} cin;

istream::istream() {
#ifndef ONLINE_JUDGE
	int IN = open(PROB_NAME".in", O_RDONLY);
	ptr = (char *) mmap(NULL, lseek(IN, 0, SEEK_END), PROT_READ, MAP_PRIVATE, IN, 0);
#else
	ptr = (char *) mmap(NULL, lseek(0, 0, SEEK_END), PROT_READ, MAP_PRIVATE, 0, 0);
#endif
	begin = ptr;
	lastSuccess = true;
}
#define INTEGER_SIGNED_OPERATOR(type)							\
istream& istream::operator>>(type& var) {						\
	bool isNegative = false;									\
	var = 0;													\
	while (*ptr && !isdigit(*ptr)) {isNegative|=*ptr++=='-';}	\
	if (!(*ptr)) {lastSuccess = false; return *this;}			\
	while (*ptr &&  isdigit(*ptr)) {var=var*10+*ptr++-48;}		\
	if (isNegative) var = -var;									\
	return *this;												\
}

INTEGER_SIGNED_OPERATOR(int)
}
using namespace xszq;
#else
using std::cin;
#endif
#define MAXN 300005
#define LOWBIT(X) (X&-X)

const int MOD = 1e9+9;

long long a[MAXN];
int n, m;
int f, f1, f2;

void update(int x, long long w) {
	for (; x <= n; x += LOWBIT(x))
		a[x] += w;
}

int query(int x) {
	int ret = 0;
	for (; x; x -= LOWBIT(x))
		ret = (ret + a[x]) % MOD;
	return ret;
}

int main() {
#ifndef ONLINE_JUDGE
	dup2(open(PROB_NAME".out", O_WRONLY | O_CREAT | O_TRUNC, 0664),
	STDOUT_FILENO);
#endif

	cin >> n >> m;
	for (int i = 1, w; i <= n; ++ i) {
		cin >> w;
		update(i, w);
	}
	for (int i = 1, opt, l, r; i <= m; ++ i) {
		cin >> opt >> l >> r;
		if (opt == 1) {
			f = 0;
			f1 = 1;
			for (int j = l; j <= r; ++ j) {
				update(j, f1);
				f2 = (f + f1) % MOD;
				f = f1;
				f1 = f2;
			}
		} else {
			printf("%d\n", (query(r) - query(l-1) + MOD) % MOD);
		}
	}
	return 0;
}


#include<bits/stdc++.h>
#define LL long long
const LL mod=1e9+9;
using namespace std;
inline int lowbit(int i)
{
    return i&-i;
}
template<typename T>inline void read(T&x)
{
    T ll=1;
    T res=0;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
        ll=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    res=(res<<3)+(res<<1)+ch-'0',ch=getchar();
    x=res*ll;
}
template<typename T>void print(T x)
{
    if(x<0)putchar('-'),x=-x;
    if(x<10)
    putchar(x+'0');
    else
    {
        print(x/10);
        putchar(x%10+'0');
    }
}
int n;
int q;
LL a[500001],c[500001];
inline void change(LL i,LL delta)
{
    while(i<=n)
    {
        c[i]+=delta;
        i+=lowbit(i);
    }
}
inline LL get(LL i)
{
    LL sum=0;
    while(i>0)
    {
        sum+=c[i];
        i-=lowbit(i);
    }
    return sum;
}
inline LL get(LL l,LL r)
{
    return get(r)-get(l-1);
}
int main()
{
    read(n),read(q);
    LL f[n];
    f[1]=f[2]=1;
    for(int i=3;i<=n;i++)
    {
    	f[i]=f[i-1]+f[i-2];
	}
    for(int i=1;i<=n;i++)
    {
        read(a[i]);
        change(i,a[i]);
    }
    int opt,x,y;
    while(q--)
    {
        read(opt),read(x),read(y);
        if(opt==1)
        {
        	for(int i=x;i<=y;i++)
        	{
        		change(i,f[i-x+1]);
			}
		}
        else
        print(get(x,y)%mod),puts("");
    }
    return 0;
}


#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
const LL mod = 1e9 + 9;
const int maxn = 3e5 + 10;
int n, m;
LL f[maxn], rf[maxn], sum[maxn], a[maxn];
LL s[maxn << 2], tag1[maxn << 2], tag2[maxn << 2];
void pre() {
    f[1] = f[2] = 1;
    rf[1] = 1, rf[2] = mod - 1;
    sum[1] = 1, sum[2] = 2;
    for (int i = 3; i <= n + 1; i++) {
        f[i] = (f[i - 1] + f[i - 2]) % mod;
        rf[i] = (i & 1) ? f[i] : mod - f[i];
        sum[i] = (sum[i - 1] + f[i]) % mod;
    }
}
void pushup(int id) {
    s[id] = (s[id << 1] + s[id << 1 | 1]) % mod;
}
void build(int id, int l, int r) {
    if (l == r) {
        s[id] = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(id << 1, l, mid);
    build(id << 1 | 1, mid + 1, r);
    pushup(id);
}
void pushdown(int id, int l, int r, int mid) {
    int ls = (id << 1), rs = (id << 1 | 1);
    if (tag1[id]) {
        tag1[ls] = (tag1[ls] + tag1[id]) % mod;
        tag1[rs] = (tag1[rs] + tag1[id]) % mod;
        s[ls] = (s[ls] + (sum[mid + 1] - sum[l] + mod) % mod * tag1[id] % mod) % mod;
        s[rs] = (s[rs] + (sum[r + 1] - sum[mid + 1] + mod) % mod * tag1[id] % mod) % mod;
        tag1[id] = 0;
    }
    if (tag2[id]) {
        tag2[ls] = (tag2[ls] + tag2[id]) % mod;
        tag2[rs] = (tag2[rs] + tag2[id]) % mod;
        s[ls] = (s[ls] + (sum[mid] - sum[l - 1] + mod) % mod * tag2[id] % mod) % mod;
        s[rs] = (s[rs] + (sum[r] - sum[mid] + mod) % mod * tag2[id] % mod) % mod;
        tag2[id] = 0;
    }
}
void update(int id, int l, int r, int x, int y, LL v1, LL v2) {
    if (x <= l && r <= y) {
        tag1[id] = (tag1[id] + v1) % mod;
        tag2[id] = (tag2[id] + v2) % mod;
        s[id] = (s[id] + (sum[r + 1] - sum[l] + mod) % mod * v1 % mod) % mod;
        s[id] = (s[id] + (sum[r] - sum[l - 1] + mod) % mod * v2 % mod) % mod;
        return;
    }
    int mid = (l + r) >> 1;
    pushdown(id, l, r, mid);
    if (x <= mid) {
        update(id << 1, l, mid, x, y, v1, v2);
    }
    if (y > mid) {
        update(id << 1 | 1, mid + 1, r, x, y, v1, v2);
    }
    pushup(id);
}
LL query(int id, int l, int r, int x, int y) {
    if (x <= l && r <= y) {
        return s[id];
    }
    int mid = (l + r) >> 1;
    pushdown(id, l, r, mid);
	LL res = 0;
    if (x <= mid) {
        res = (res + query(id << 1, l, mid, x, y)) % mod;
    }
    if (y > mid) {
        res = (res + query(id << 1 | 1, mid + 1, r, x, y)) % mod;
    }
    return res;
}
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &a[i]);
    }
    pre();
    build(1, 1, n);
    int op, l, r;
    while (m--) {
        scanf("%d %d %d", &op, &l, &r);
        if (op == 1) {
            update(1, 1, n, l, r, rf[l - 1], rf[l]);
        } else {
            printf("%lld\n", query(1, 1, n, l, r));
        }
    }
    return 0;
}


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

#define GetSum(x) (f[x+2]-f[2])%mod
#define Int register int
#define mod 1000000009
#define int long long
#define MAXN 300105

struct Segment
{
	int l,r,sum;
	int lazys,lazyt;
}tree[MAXN << 2];

void Pushup (int i)
{
	tree[i].sum = (tree[i << 1].sum + tree[i << 1 | 1].sum) % mod;
}

int f[MAXN];

void Init (int n)
{
	f[0] = 0,f[1] = 1;
	for (Int i = 2;i <= n + 5;++ i)
		f[i] = (f[i - 1] + f[i - 2]) % mod;
}

void upgrade (int i)
{
	tree[i].sum = (tree[i].sum + GetSum (tree[i].lazyt) + mod - GetSum (tree[i].lazys - 1)) % mod;
}

void Pushdown (int i)
{
	if (!tree[i].lazys && !tree[i].lazyt) return ;
	int mid = (tree[i].lazys + tree[i].lazyt) >> 1;
	// << tree[i].l << " -> " << tree[i].r << " push to " << tree[i << 1].l  << " -> " << tree[i << 1].r << " and  " << tree[i << 1 | 1].l << " -> " << tree[i << 1 | 1].r << endl;
	tree[i << 1].lazys = tree[i].lazys,tree[i << 1].lazyt = mid;
	tree[i << 1 | 1].lazys = mid + 1,tree[i << 1 | 1].lazyt = tree[i].lazyt;
	//cout << tree[i << 1].sum << " add " << tree[i << 1].lazys << " -> " << tree[i << 1].lazyt << endl;
	upgrade (i << 1),upgrade (i << 1 | 1);
	tree[i].lazys = tree[i].lazyt = 0;
	return ;
}

int a[MAXN];

void build (int i,int l,int r)
{
	tree[i].l = l,tree[i].r = r;
	if (l == r) return tree[i].sum = a[l],void ();
	int mid = (l + r) >> 1;
	build (i << 1,l,mid);
	build (i << 1 | 1,mid + 1,r);
	Pushup (i);
}

void update (int i,int l,int r)
{
	if (tree[i].l > r || l > tree[i].r) return ;
	Pushdown (i);
	if (tree[i].l >= l && tree[i].r <= r)
	{
		tree[i].lazys = tree[i].l - l + 1;
		tree[i].lazyt = tree[i].lazys + tree[i].r - tree[i].l;
		upgrade (i);
		return ;
	}
	Pushdown (i);
	update (i << 1,l,r);
	update (i << 1 | 1,l,r);
	Pushup (i);
	//cout << tree[i].l << " -> " << tree[i].r << ": " << tree[i].sum << endl;
}

int query (int i,int l,int r)
{
	if(tree[i].l > r || l > tree[i].r) return 0;
	if (tree[i].l >= l && tree[i].r <= r) return tree[i].sum;
	Pushdown (i);
	return (query (i << 1,l,r) + query (i << 1 | 1,l,r)) % mod;
}

int n,m;

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

void write (int x)
{
	if (x < 0){x = -x;putchar ('-');}
	if (x > 9) write (x / 10);
	putchar (x % 10 + '0');
}

signed main()
{
	n = read (),m = read ();
	Init (n);
	for (Int i = 1;i <= n;++ i) a[i] = read ();
	build (1,1,n);
	for (Int i = 1;i <= m;++ i)
	{
		int type = read (),l = read (),r = read ();
		if (type == 1) update (1,l,r);
		else
		{
			int Ans = query (1,l,r);
			write ((Ans % mod + mod) % mod),putchar ('\n');
		}
	}
	return 0;
}


#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int mod=1e9+9;
const int N=300000;
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].f1*f[len]%mod+tr[k].f2*f[len+1]%mod-tr[k].f2);}
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].f2+=tr[k].f2;
	tr[k<<1|1].f1+=tr[k].f1*f[mid-l]+tr[k].f2*f[mid-l+1];
	tr[k<<1|1].f2+=tr[k].f1*f[mid-l+1]+tr[k].f2*f[mid-l+2];
	tr[k].f1=0;tr[k].f2=0;
	up(k,mid-l+1);up(k,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==qr&&r==qr) return tr[k].sum;
	down(k,l,r);
	int mid=(l+r)>>1;
	if(qr<=mid) return query(k<<1,l,mid,ql,qr);
	else if(ql>mid) return query(k<<1|1,mid+1,r,ql,qr);
	else return query(k<<1,l,mid,ql,mid)+query(k<<1|1,mid+1,r,mid+1,qr);
}
int main()
{
	scanf("%d%d",&n,&m);
	init();
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
	for(int i=1;i<=m;i++)
    {
        int opt,l,r;
        scanf("%d%d%d",&opt,&l,&r);
        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);
    }
}


//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 + 7);
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<bits/stdc++.h>
using namespace std;
const long long N = 3e5 + 10, Mod = 1e9 + 9;
long long n, m, a[N], b[N], d[N << 2];
map<long long, long long> lazy[N << 2];
void build(long long rt, long long l, long long r){
    if(l == r){
        d[rt] = a[l];
        return;
    }
    long long mid = l + r >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);
    d[rt] = (d[rt << 1] + d[rt << 1 | 1]) % Mod;
}
void lazydown(long long rt, long long len){
    long long len1 = (len + 1) / 2, len2 = len / 2;
    map<long long, long long>::iterator it;
    for(it = lazy[rt].begin(); it != lazy[rt].end(); it++){
        long long s = it->first;
        long long t = it->second;
        d[rt << 1] = (d[rt << 1] + (b[s + len1 - 1] - b[s - 1]) * t) % Mod;
        d[rt << 1 | 1] = (d[rt << 1 | 1] + (b[s + len1 + len2 - 1] - b[s + len1 - 1]) * t) % Mod;
        if(lazy[rt << 1].find(s) == lazy[rt << 1].end()) lazy[rt << 1][s] = t;
        else lazy[rt << 1][s] = (lazy[rt << 1][s] + t) % Mod;
        if(lazy[rt << 1 | 1].find(s + len1) == lazy[rt << 1 | 1].end()) lazy[rt << 1 | 1][s + len1] = t;
        else lazy[rt << 1 | 1][s + len1] = (lazy[rt << 1 | 1][s + len1] + t) % Mod;
    }
    lazy[rt].clear();
}
void update(long long rt, long long l, long long r, long long L, long long R, long long s){
    if(L <= l && R >= r){
        d[rt] = (d[rt] + b[s + r - l] - b[s - 1]) % Mod;
        if(lazy[rt].find(s) == lazy[rt].end()) lazy[rt][s] = 1;
        else lazy[rt][s]++;
        return;
    }
    if(!lazy[rt].empty()) lazydown(rt, r - l + 1);
    long long mid = l + r >> 1;
    if(L <= mid) update(rt << 1, l, mid, L, R, s);
    if(R > mid) update(rt << 1 | 1, mid + 1, r, L, R, s + max(mid - L + 1, 0ll));
    d[rt] = (d[rt << 1] + d[rt << 1 | 1]) % Mod;
}
long long query(long long rt, long long l, long long r, long long L, long long R){
    if(L <= l && R >= r) return d[rt];
    if(!lazy[rt].empty()) lazydown(rt, r - l + 1);
    long long mid = l + r >> 1, res = 0;
    if(L <= mid) res = (res + query(rt << 1, l, mid, L, R)) % Mod;
    if(R > mid) res = (res + query(rt << 1 | 1, mid + 1, r, L, R)) % Mod;
    return res;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(long long i = 1; i <= n; i++) cin>>a[i];
    b[1] = b[2] = 1;
    for(long long i = 3; i <= n; i++) b[i] = (b[i - 2] + b[i - 1]) % Mod;
    for(long long i = 1; i <= n; i++) b[i] = (b[i - 1] + b[i]) % Mod;
    build(1, 1, n);
    long long t, x, y;
    for(long long i = 1; i <= m; i++){
        cin>>t>>x>>y;
        if(t == 1) update(1, 1, n, x, y, 1);
        else cout<<query(1, 1, n, x, y)<<endl;
    }
    return 0;
}


#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;
#define ls (now<<1)
#define rs (now<<1|1)
const int maxn = 2e6+10;
const int mod = 1e9+9;

long long n,m,x,y,op;
long long a[maxn],f[maxn];

struct tree {
	long long sum,c1,c2;
} t[maxn];

int read() {
	int x = 0,f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while('0' <= ch && ch <= '9') {
		x = (x<<3)+(x<<1) + ch-'0';
		ch = getchar();
	}
	return x * f;
}

long long getx(long long a1,long long a2,long long x) {
	if(x == 1) return a1;
	if(x == 2) return a2;
	return ( a1*f[x-2] + a2*f[x-1] ) % mod;
}

long long getsum(long long a1,long long a2,long long x) {
	if(x == 1) return a1;
	if(x == 2) return (a1+a2) % mod;
	return ( getx(a1,a2,x+2) - a2 + mod ) % mod;
}

void pushup(int now) {
	t[now].sum = (t[ls].sum + t[rs].sum) % mod;
}

void pushdown(int l,int r,int now) {
	if(!t[now].c1) return;
	int mid = (l+r)>>1;
	long long a1,a2;
	a1 = t[now].c1;
	a2 = t[now].c2;
	t[ls].c1 = (t[ls].c1 + a1) % mod;
	t[ls].c2 = (t[ls].c2 + a2) % mod;
	t[ls].sum = (t[ls].sum + getsum(a1,a2,mid-l+1)) % mod;
	a1 = getx(t[now].c1,t[now].c2,mid-l+2);
	a2 = getx(t[now].c1,t[now].c2,mid-l+3);
	t[rs].c1 = (t[rs].c1 + a1) % mod;
	t[rs].c2 = (t[rs].c2 + a2) % mod;
	t[rs].sum = (t[rs].sum + getsum(a1,a2,r-mid)) % mod;
	t[now].c1 = t[now].c2 = 0;
}

void modify(int L,int R,int l,int r,int now) {
	if(L <= l && r <= R) {
		t[now].c1 = (t[now].c1 + f[l-L+1]) % mod;
		t[now].c2 = (t[now].c2 + f[l-L+2]) % mod;
		t[now].sum = (t[now].sum + getsum(f[l-L+1],f[l-L+2],r-l+1)) % mod;
		return;
	}
	pushdown(l,r,now);
	int mid = (l+r)>>1;
	if(L <= mid) modify(L,R,l,mid,ls);
	if(R > mid) modify(L,R,mid+1,r,rs);
	pushup(now);
}

long long query(int L,int R,int l,int r,int now) {
	long long ans = 0;
	if(L <= l && r <= R) {
		ans = t[now].sum;
		return (ans + mod) % mod;
	}
	pushdown(l,r,now);
	int mid = (l+r)>>1;
	if(L <= mid) ans = (ans + query(L,R,l,mid,ls)) % mod;
	if(R > mid) ans = (ans + query(L,R,mid+1,r,rs)) % mod;
	return (ans+mod)%mod;
}

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

int main() {
	n = read(),m = read();
	for(int i = 1; i <= n; i++) {
		x = read();
		a[i] = (a[i-1] + x) % mod;
	}
	init();
	while(m--) {
		op = read();
		x = read(), y = read();
		if(op == 1) modify(x,y,1,n,1);
		if(op == 2) printf("%lld\n",((a[y]-a[x-1]+query(x,y,1,n,1))%mod+mod)%mod);
	}
	return 0;
}


#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 + 7);
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];
            (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() {

    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>
#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) %= 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;
}