// ＤＣＴ→量子化（縦倍対応）
// 高速版（アルゴリズムはdct2.tec）

// 縦倍化は#define TATEBAI

#include "_jpeglib.h"
#include "jpeg.h"

#define	Ryousi(p)	{		/* 量子化を行ってから格納するマクロ：pは定数のみ */\
	short q,r=0;			/* rは量子化したら０になる時のため */\
	long x;				\
	x=(long)S.w[HW];		/* 整数位だけの取り出し(xが0である可能性は低い) */\
	q=(short)Qtable[p*JWU];		\
	if (x>=0) {			\
		x+=q/2;			/* 四捨五入のため */\
		if (x>=q) r=x/q;	/* xが量子化数より大きくなければ量子化結果は０に決まっているので計算を省く */\
	} else {			\
		x-=q/2;			/* 四捨五入のため */\
		if (x<=-q) r=x/q;	/* xが量子化数より小さいなければ量子化結果は０に決まっているので計算を省く */\
	}				\
	suv[p*JWU]=r;			/* 量子化：ここで０が出る */\
}

void
#ifdef TATEBAI
 DCT2b(short *sxy,short *suv,unchar const *Qtable)
#else
 DCT2(short *sxy,short *suv,unchar const *Qtable)
#endif
{
int i;
R68 S;
long a,b,c,d;
long *syup,syu[JWY*JWU];
	// Syuの計算
	syup=syu;
	for (i=0;
		#ifdef TATEBAI
		i<JWY/2 // 縦倍時は一度に使うのは半分のみ
		#else
		i<JWY
		#endif
			;i++) {
		// １つの式は全xの加算であり、これを１回で全u分作り、それをループで全y分作る。
		short x0,x1,x2,x3,x4,x5,x6,x7;
		// ↑配列にしてないのはレジスタ変数になるのを期待しているから
		x0=*sxy++; x1=*sxy++; x2=*sxy++; x3=*sxy++;
		x4=*sxy++; x5=*sxy++; x6=*sxy++; x7=*sxy++;
		//
		a=x0+x3+x4+x7;
		b=x1+x2+x5+x6;
		S.w[HW]=a+b; S.w[LW]=0;
		#ifdef TATEBAI
		syup[0+JWU]=
		#endif
			syup[0]=S.l>>2;
		S.w[HW]=a-b; S.w[LW]=0;
		#ifdef TATEBAI
		syup[4+JWU]=
		#endif
			 syup[4]=S.l>>2;
		//
		a=x0-x3-x4+x7;
		b=x1-x2-x5+x6;
		#ifdef TATEBAI
		syup[2+JWU]=
		#endif
			syup[2]=a*COS2+b*COS6;
		#ifdef TATEBAI
		syup[6+JWU]=
		#endif
			syup[6]=a*COS6-b*COS2;
		//
		a=x0-x7;
		b=x1-x6;
		c=x2-x5;
		d=x3-x4;
		#ifdef TATEBAI
		syup[1+JWU]=
		#endif
			syup[1]=a*COS1+b*COS3+c*COS5+d*COS7;
		#ifdef TATEBAI
		syup[3+JWU]=
		#endif
			syup[3]=a*COS3-b*COS7-c*COS1-d*COS5;
		#ifdef TATEBAI
		syup[5+JWU]=
		#endif
			syup[5]=a*COS5-b*COS1+c*COS7+d*COS3;
		#ifdef TATEBAI
		syup[7+JWU]=
		#endif
			syup[7]=a*COS7-b*COS5+c*COS3-d*COS1;
		//
		#ifdef TATEBAI
		syup+=JWU*2;
		#else
		syup+=JWU;
		#endif
	}
	// S(u,v)の計算 : 一気に量子化も行う
	syup=syu;
	for (i=0;i<JWV;i++) {
		long x0,x1,x2,x3,x4,x5,x6,x7;
		// ↑配列にしてないのはレジスタ変数になるのを期待しているから
		x0=syup[0*JWU]; x1=syup[1*JWU]; x2=syup[2*JWU]; x3=syup[3*JWU];
		x4=syup[4*JWU]; x5=syup[5*JWU]; x6=syup[6*JWU]; x7=syup[7*JWU];
		syup++;
		//
		a=x0+x3+x4+x7;
		b=x1+x2+x5+x6;
		S.l=(a+b)>>(2-1); // >>2するが全体に*2するので
		Ryousi(0);
		S.l=(a-b)>>(2-1);
		Ryousi(4);
		//
		S.l=x0-x3-x4+x7; a=S.w[HW];
		S.l=x1-x2-x5+x6; b=S.w[HW];
		S.l=(a*COS2+b*COS6)*2;
		Ryousi(2);
		S.l=(a*COS6-b*COS2)*2;
		Ryousi(6);
		//
		S.l=x0-x7; a=S.w[HW];
		S.l=x1-x6; b=S.w[HW];
		S.l=x2-x5; c=S.w[HW];
		S.l=x3-x4; d=S.w[HW];
		S.l=(a*COS1+b*COS3+c*COS5+d*COS7)*2;
		Ryousi(1);
		S.l=(a*COS3-b*COS7-c*COS1-d*COS5)*2;
		Ryousi(3);
		S.l=(a*COS5-b*COS1+c*COS7+d*COS3)*2;
		Ryousi(5);
		S.l=(a*COS7-b*COS5+c*COS3-d*COS1)*2;
		Ryousi(7);
		//
		suv++;
		Qtable++;
	}
}
