/*************************************************************************
	imath.h
	
	固定小数演算に関する宣言
		math2.h, decimal.h, vector.h をまとめたもの
*************************************************************************/

extern int isqrt(int);	// 固定小数の平方根（メチャ速い）  by MAT (TSG)

/*--------------------------------------------------------*/
/*                        math2.h                         */
/*--------------------------------------------------------*/
/*
*			math.h の補助			ver 0.3
*/

#define sign( a )		(  ( (a)>0 ) ? (1) : ( ((a)<0)?(-1):(0) )  )
#define max( a, b )		( ( (a) > (b) ) ? (a) : (b) )
#define min( a, b )		( ( (a) < (b) ) ? (a) : (b) )
#undef ads
// #define abs( a )		( ( (a) >  0  ) ? (a) : (-(a)) )

#define DECIMAL 10		/*	これは下位の 10bit shift の意味｡ したがって本当の単位は 2^10｡ 整数部 2^22｡		*/
#define DUNIT 	1024	/* = 2^10 */

/* 整数固定少数変換 */
#define IntToDeci( i )	( (i) << DECIMAL )
#define DeciToInt( d )	( (d) >> DECIMAL )
/* 固定少数の演算の補正 Macro｡ (まとてやったほうが速いから別にしておく) */
#define AdjMulDeci( d )	( (d) >> DECIMAL )
#define AdjDivDeci( d )	( (d) << DECIMAL )
#define MulDeci( a, b ) ( (a)*(b) >> DECIMAL )
#define DivDeci( a, b ) ( ((a) << DECIMAL) /(b) )

/*--------------------------------------------------------*/
/*                       decimal.h                        */
/*--------------------------------------------------------*/
/*
*	10bit固定小数演算		v. 1.0
*	math.h を仮定する｡
*/

/*
*	x, y は固定少数に限定するよう, 注意して使う｡
*	足し算, 引き算はそのまま｡ dummy で作ってもいいかもしれない｡
*/ 
#define multi( x, y )  ( (x) * (y) >> DECIMAL )
#define div( x, y )    ( (x) / (y) << DECIMAL )

/*
*	int multi( int x, int y ) { return x*y >> DECIMAL ;}	
*	int div (int x,int y)     { return x/y << DECIMAL ;}
*/

extern int powd( int, int )			;

/*
*	小さい変数のための三角関数( 小さくﾏｸﾛｰﾘﾝ展開しただけ｡ べきの展開の大きさは個別に tune せよ｡)
*	返り値も固定少数表現の整数である｡ (COS for Small Decimal)
*/
#define cossd( x )  ( DUNIT - powd( (x), 2 )/2 + powd( (x), 4 )/24 - powd( (x), 6 )/720 )
#define sinsd( x )  ( (x) - powd( (x), 3 )/6 + powd( (x), 5 )/120 - powd( (x), 7)/5040 )

/*
*	三角数列｡ そのまま cos, sin の関数とみなす｡
*/
#if 0
extern int cos512[1024];
extern int sin512[1024];
extern int acos512[2048+1];
extern int asin512[2048+1];
#define  cos512( x )	(cos512[x])
#define  sin512( x )	(sin512[x])
#define acos512( x )	(acos512[(x)+DUNIT])
#define asin512( x )	(asin512[(x)+DUNIT])
#endif
/* -DUNIT は負に対応するため, 数列は原点をずらして持っている｡ */

/*--------------------------------------------------------*/
/*                        vector.h                        */
/*--------------------------------------------------------*/
/*
*				Vector演算関数				ver 1.12
*
*	math.h, math2.h を仮定する｡
*/

/*
*		型宣言
*/
struct vect2i { int x ; int y };				/* 二次元整数vector */ 
struct vect3i { int x ; int y ; int z };		/* 三次元整数vector */ 
struct vect3p { int x; int y ; int z }; 		/* 三次元固定少数vector */
struct vect3f { float x ; float y ; float z };	/* 三次元浮動少数vector */
struct matrix3i	{ int xx ; int xy ; int xz ;
                  int yx ; int yy ; int yz ;
                  int zx ; int zy ; int zz ; };	/* ３×３整数行列 */
struct matrix3p	{ int xx ; int xy ; int xz ;
                  int yx ; int yy ; int yz ;
                  int zx ; int zy ; int zz ; };	/* ３×３固定少数行列 */
struct surfi {
	struct vect3i norl;							/* 法線 (NORmal Line) */
	struct vect3i s0;							/* 面上の一点 */
	int c;										/* 定数 */
};
struct surfp {
	struct vect3p norl;							/* 法線 (NORmal Line) */
	struct vect3p s0;							/* 面上の一点 */
	int c;										/* 固定少数の定数 */
};



/*
*		固定少数整数変換関数
*/
extern struct vect3i DeciToInt3V( struct vect3p p );
extern struct vect3p IntToDeci3V( struct vect3i p );
extern struct matrix3i DeciToInt3M( struct matrix3p A );
extern struct matrix3p IntToDeci3M( struct matrix3i A );
/*
*		vector 演算関数
*/
#define MakeZero2i( p )			{ (p).x=0; (p).y=0; }
#define MakeZero2p( p )			{ (p).x=0; (p).y=0; }
extern struct vect2i scalar2i( int, struct vect2i )	;
extern struct vect2i inscalar2i( int, struct vect2i );
extern struct vect2i scalar2p( int, struct vect2i );
extern struct vect2i add2i( struct vect2i, struct vect2i );
extern struct vect2i subtr2i( struct vect2i, struct vect2i );
extern struct vect2i rshift2i( struct vect2i, int );
extern struct vect2i lshift2i( struct vect2i, int );
#define iszero2( p )			( (p).x==0 && (p).y==0 )
#define abs2i( p )				( (int)sqrt( (p).x*(p).x + (p).y*(p).y ) )
#define innerpro2i( p, q )		( (p).x*(q).x + (p).y*(q).y )
#define innerpro2p( p, q )		AdjMulDeci( (p).x*(q).x + (p).y*(q).y )
#define issame2v( p, q )		( (p).x==(q).x && (p).y==(q).y )

#define MakeZero3i( p )			{ (p).x=0; (p).y=0; (p).z=0; }
#define MakeZero3p( p )			{ (p).x=0; (p).y=0; (p).z=0; }
extern struct vect3i scalar3i( int, struct vect3i );
extern struct vect3i scalar3p( int, struct vect3i );
extern struct vect3i inscalar3i( int, struct vect3i );
extern struct vect3i add3i( struct vect3i, struct vect3i );
extern struct vect3p add3p( struct vect3p x1, struct vect3p x2 );
extern struct vect3i subtr3i( struct vect3i, struct vect3i );
extern struct vect3p subtr3p( struct vect3p x1, struct vect3p x2 );
extern struct vect3i outerpro3i( struct vect3i, struct vect3i );
extern struct vect3p outerpro3p( struct vect3p x1, struct vect3p x2 );
extern struct vect3i rshift3i( struct vect3i p, int i );
extern struct vect3i lshift3i( struct vect3i p, int i );
extern struct vect3p rshift3p( struct vect3p p, int i );
extern struct vect3p lshift3p( struct vect3p p, int i );
#define issame3v( p, q )		( (p).x==(q).x && (p).y==(q).y && (p).z==(q).z )
#define ispara3( p, q )			( ( (p).x*(q).y - (p).y*(q).x )==0 && ( (p).x*(q).z - (p).z*(q).x )==0 && ( (p).y*(q).z - (p).z*(q).y )==0 )
#define iszero3( p )			( (p).x==0 && (p).y==0 && (p).z==0 )
#define det3( p, q, r )			( (p).x*(q).y*(r).z + (q).x*(r).y*(p).z + (r).x*(p).y*(q).z - (p).x*(r).y*(q).z - (q).x*(p).y*(r).z - (r).x*(q).y*(p).z )
#define innerpro3i( p, q )		( (p).x*(q).x + (p).y*(q).y + (p).z*(q).z )
#define innerpro3p( p, q )		AdjMulDeci( (p).x*(q).x + (p).y*(q).y + (p).z*(q).z )
#define abs3i( p )				( (int)sqrt( (p).x*(p).x + (p).y*(p).y + (p).z*(p).z ) )
#define Normalize3i( p )		{ if( abs3i(p)>0 ) (p)=inscalar3i( abs3i(p) ,scalar3i( DUNIT, (p) ) );}
/* p の大きさをdunitにする */
#define cos3i( p, q )			( (innerpro3i( p, q ) << DECIMAL) / abs3i(p) / abs3i(q) )
/* p, q のなす角の cos を固定少数で返す */
#define Init3V( p )				{ (p).x=0 ; (p).y=0 ; (p).z=0 ;}

/*
*		行列演算関数
*/
extern struct matrix3i addm3i( struct matrix3i A, struct matrix3i B );
#define addm3p( A, B )			( addm3i( (A), (B) ) )
extern struct matrix3i subm3i( struct matrix3i A, struct matrix3i B );
#define subm3p( A, B )			( subm3i( (A), (B) ) )
extern struct matrix3i mulmm3i( struct matrix3i A, struct matrix3i B );
extern struct matrix3p mulmm3p( struct matrix3p A, struct matrix3p B );
extern struct vect3i mulmv3i( struct matrix3i A, struct vect3i p );
extern struct vect3p mulmv3p( struct matrix3p A, struct vect3p p );
extern struct vect3i mulmv3pi( struct matrix3p A, struct vect3i p );
/* ３次元vectorの回転 */
extern struct vect3i RotXi( int a, struct vect3i p );
extern struct vect3p RotXp( int a, struct vect3p p );
extern struct vect3i RotYi( int a, struct vect3i p );
extern struct vect3p RotYp( int a, struct vect3p p );
extern struct vect3i RotZi( int a, struct vect3i p );
extern struct vect3p RotZp( int a, struct vect3p p );
extern struct matrix3p RotX( int a );
extern struct matrix3p RotY( int a );
extern struct matrix3p RotZ( int a );
#define Init3M( A )				{ (A).xx=0 ; (A).xy=0 ; (A).xz=0 ; (A).yx=0 ; (A).yy=0 ; (A).yz=0 ; (A).zx=0 ; (A).zy=0 ; (A).zz=0 ; }
/* 平面を表す関数 */
#define surffi( s, p )	( innerpro3i( (s).norl, (p) ) - (s).c )
#define surffp( s, p )	( innerpro3p( (s).norl, (p) ) - (s).c )

/* end of imath.h */
