// 逆量子化→逆ＤＣＴ
// 高速版（アルゴリズムはidct2.tec）

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

void IDCT2(short *suv,short *sxy,unchar const *Qtable)
{
int i;
short *svxp,svx[JWV*JWX];
long a,b,c,d,f;
R68 S;
	// svxの計算
	svxp=svx;
	for (i=0;i<JWX;i++) {
		long u1,u2,u3,u5,u6,u7;
		// ↑配列にしてないのはレジスタ変数になるのを期待しているから
		S.w[HW]=*suv++; S.w[LW]=0; c=S.l; // u0
		u1=*suv++; u2=*suv++; u3=*suv++;
		S.w[HW]=*suv++; S.w[LW]=0; f=S.l; // u4
		u5=*suv++; u6=*suv++; u7=*suv++;
		// 量子化によって全てが０になった所は計算するまでもないので飛ばす
		// 高次では結構多い
		// ifの判定順は、０でないことが多いものが先
		// 全て０なら高速処理されるので判定が遅くても良い。
		if (f==0 && u5==0 && u6==0 && u7==0) {
			if (c==0 && u1==0 && u2==0 && u3==0) {
				// 全部０
				int j=JWX;
				while (j--) *svxp++=0;
				continue;
			}
			// f〜u7のみ０
			// 逆量子化
			c *=*Qtable++; // ここはif (c!=0) ... で処理を分けると帰って遅くなる
			u1*=*Qtable++; // ここではQtableアクセスが連続化してある
			u2*=*Qtable++;
			u3*=*Qtable;
			Qtable+=5; // f〜u7は０なので逆量子化不要
			//
			c>>=2;	// u0*COS0
			//
			f=u2*COS2;
			a=c+f;
			b=u1*COS1+u3*COS3;
			S.l=a+b; svxp[0]=S.w[HW];
			S.l=a-b; svxp[7]=S.w[HW];
			//
			a=c-f;
			b=u1*COS7-u3*COS5;
			S.l=a+b; svxp[3]=S.w[HW];
			S.l=a-b; svxp[4]=S.w[HW];
			////////
			f=u2*COS6;
			a=c+f;
			b=u1*COS3-u3*COS7;
			S.l=a+b; svxp[1]=S.w[HW];
			S.l=a-b; svxp[6]=S.w[HW];
			//
			a=c-f;
			b=u1*COS5-u3*COS1;
		} else { // 全部０でない
			// 逆量子化
			c *=*Qtable++; // ここはif (c!=0) ... で処理を分けると帰って遅くなる
			u1*=*Qtable++; // ここではQtableアクセスが連続化してある
			u2*=*Qtable++;
			u3*=*Qtable++;
			f *=*Qtable++;
			u5*=*Qtable++;
			u6*=*Qtable++;
			u7*=*Qtable++;
			//
			f>>=2;	// u4*COS4
			c>>=2;	// u0*COS0
			d=c-f;	// u0*COS0-u4*COS4
			c+=f;	// u0*COS0+u4*COS4
			//
			f=u2*COS2+u6*COS6;
			a=c+f;
			b=u1*COS1+u3*COS3+u5*COS5+u7*COS7;
			S.l=a+b; svxp[0]=S.w[HW];
			S.l=a-b; svxp[7]=S.w[HW];
			//
			a=c-f;
			b=u1*COS7-u3*COS5+u5*COS3-u7*COS1;
			S.l=a+b; svxp[3]=S.w[HW];
			S.l=a-b; svxp[4]=S.w[HW];
			////////
			f=u2*COS6-u6*COS2;
			a=d+f;
			b=u1*COS3-u3*COS7-u5*COS1-u7*COS5;
			S.l=a+b; svxp[1]=S.w[HW];
			S.l=a-b; svxp[6]=S.w[HW];
			//
			a=d-f;
			b=u1*COS5-u3*COS1+u5*COS7+u7*COS3;
		}
		S.l=a+b; svxp[2]=S.w[HW];
		S.l=a-b; svxp[5]=S.w[HW];
		svxp+=JWX;
	}
	// s(x,y)の計算
	svxp=svx;
	for (i=0;i<JWY;i++) {
		long u1,u2,u3,u5,u6,u7;
		// ↑配列にしてないのはレジスタ変数になるのを期待しているから
		S.w[HW]=svxp[0*JWX]; S.w[LW]=0; c=S.l; c>>=2; // u0*COS0
		u1=svxp[1*JWX]; u2=svxp[2*JWX];	u3=svxp[3*JWX];
		S.w[HW]=svxp[4*JWX]; S.w[LW]=0; f=S.l; f>>=2; // u4*COS4
		u5=svxp[5*JWX]; u6=svxp[6*JWX]; u7=svxp[7*JWX];
		d=c-f; // u0*COS0-u4*COS4
		c+=f;  // u0*COS0+u4*COS4
		svxp++;
		//
		f=u2*COS2+u6*COS6;
		a=c+f;
		b=u1*COS1+u3*COS3+u5*COS5+u7*COS7;
		S.l=(a+b)*2; sxy[0*JWX]=S.w[HW];
		S.l=(a-b)*2; sxy[7*JWX]=S.w[HW];
		//
		a=c-f;
		b=u1*COS7-u3*COS5+u5*COS3-u7*COS1;
		S.l=(a+b)*2; sxy[3*JWX]=S.w[HW];
		S.l=(a-b)*2; sxy[4*JWX]=S.w[HW];
		////////
		f=u2*COS6-u6*COS2;
		a=d+f;
		b=u1*COS3-u3*COS7-u5*COS1-u7*COS5;
		S.l=(a+b)*2; sxy[1*JWX]=S.w[HW];
		S.l=(a-b)*2; sxy[6*JWX]=S.w[HW];
		//
		a=d-f;
		b=u1*COS5-u3*COS1+u5*COS7+u7*COS3;
		S.l=(a+b)*2; sxy[2*JWX]=S.w[HW];
		S.l=(a-b)*2; sxy[5*JWX]=S.w[HW];
		//
		sxy++;
	}
}
