/*
 * $Id: macro.h,v 1.1 2003/02/07 18:15:44 wheeler Exp $
 *
 * スタンドアローンなマクロ
 *
 * $Log: macro.h,v $
 * Revision 1.1  2003/02/07 18:15:44  wheeler
 * Fox's version of libultra and friends.
 *
 * Revision 1.14  1997/01/29  12:11:35  hayakawa
 * WRAP,CLAMPを追加
 *
 * Revision 1.13  1996/11/26  10:17:13  hayakawa
 * 度 ←→ ラジアン変換をmath64.hに移動させた
 *
 * Revision 1.12  1996/11/21  06:31:45  hayakawa
 * TRUE,True,true,FALSE,False,falseを定義
 * 一部マクロをmath64.hに移動
 *
 * Revision 1.11  1996/11/07  02:38:44  hayakawa
 * 配列、ポインタ高速化マクロの追加
 *
 * Revision 1.10  1996/11/07  02:37:30  hayakawa
 * 型定義関連をu64types.hに移動した
 *
 * Revision 1.9  1996/10/20  09:22:57  hayakawa
 * _LANGUAGE_C_PLUS_PLUS を __cplusplus に変更
 *
 * Revision 1.8  1996/10/01  05:28:08  hayakawa
 * UPBOUND／DOWNBOUNDの追加
 *
 */

#ifndef __MACRO_H_
#define __MACRO_H_

/*
 * Misc constants
 */

#ifndef TRUE
#define TRUE			(0 == 0)
#endif
#ifndef FALSE
#define FALSE			(!TRUE)
#endif
#ifndef true
#define true TRUE
#endif
#ifndef True
#define True TRUE
#endif
#ifndef false
#define false FALSE
#endif
#ifndef False
#define False FALSE
#endif

/*
 * 高速化のためのマクロ
 */

/*
 * typeのサイズを２の対数にする
 * サイズが２のべき乗でなければならない
 * サイズは1,2,4,8,16,32,64,128,256のいずれかでなければならない
 * それ以外の場合は -1 を返す
 * 帰り値は int である
 */
#define SIZE2LOG2(type) \
	((sizeof(type) == 1) ? 0 : \
	 ((sizeof(type) == 2) ? 1 : \
	  ((sizeof(type) == 4) ? 2 : \
	   ((sizeof(type) == 8) ? 3 : \
	    ((sizeof(type) == 16) ? 4 : \
	     ((sizeof(type) == 32) ? 5 : \
	      ((sizeof(type) == 64) ? 6 : \
	       ((sizeof(type) == 128) ? 6 : \
		((sizeof(type) == 256) ? 6 : \
		 -1)))))))))
//
/*
 * char*でないポインタとintの足し算を高速化する
 * t:ポインタがさす型(例:int *p なら int)
 * p:ポインタ値
 * i:加算する値
 */
#define XPOINTER(t, p, i) \
	((1 << -(sizeof(t) != sizeof(*(p)))), \
	 ((t *)((char *)(p) + ((i) << SIZE2LOG2(*(p))))))
//
/*
 * char*でないポインタとintの足し算を高速化する
 * t:ポインタ型(例:typedef int *(int_p) なら int_p)
 * p:ポインタ値
 * i:加算する値
 */
#define XPOINTER_P(t, p, i) \
	((1 << (sizeof(t) != sizeof(p))), \
	 ((t)((char *)(p) + ((i) << SIZE2LOG2(*(p))))))
//
/*
 * charでない１次元配列を高速化する
 * t:配列の型(例:int)
 * a:配列
 * i:添字
 */
#define XARRAY1(t, a, i) \
	((1 << (sizeof(t) != sizeof((a)[0]))), \
	 (*(t *)((char *)(a) + \
		 ((i) << SIZE2LOG2((a)[0])))))
//
/*
 * charでない２次元配列を高速化する
 * t:配列の型(例:int)
 * a:配列
 * i:添字1
 * j:添字2
 */
#define XARRAY2(t, a, i, j) \
	((1 << (sizeof(t) != sizeof((a)[0][0]))), \
	 (*(t *)((char *)(a) + \
		 ((i) << SIZE2LOG2((a)[0])) + \
		 ((j) << SIZE2LOG2((a)[0][0])))))
//
/*
 * charでない３次元配列を高速化する
 * t:配列の型(例:int)
 * a:配列
 * i:添字1
 * j:添字2
 * k:添字3
 */
#define XARRAY3(t, a, i, j, k) \
	((1 << (sizeof(t) != sizeof((a)[0][0][0]))), \
	 (*(t *)((char *)(a) + \
		 ((i) << SIZE2LOG2((a)[0])) + \
		 ((j) << SIZE2LOG2((a)[0][0])) + \
		 ((k) << SIZE2LOG2((a)[0][0][0])))))
//}

/*
 * 汎用のマクロなどの定義
 */
#define Max(a, b) (((a) > (b)) ? (a) : (b))
#define Min(a, b) (((a) < (b)) ? (a) : (b))
#define SGN(X) ((X > 0) ? 1 : ((X == 0) ? 0 : -1))

#define SSizeof(a) ((signed)sizeof(a))
#define number(a) (sizeof(a) / sizeof(a[0])) /* 配列の要素数を返す */
#define Number(a) (SSizeof(a) / SSizeof(a[0])) /* 配列の要素数を返す */
#define SNumber(a) (SSizeof(a) / SSizeof(a[0])) /* 配列の要素数を返す */

#define UPBOUND(n, b) DOWNBOUND((n) + (b) - 1, b) /* バウンダリ切り上げ調整 */
#define DOWNBOUND(n, b) ((n) & ~((b) - 1)) /* バウンダリ切り捨て調整 */

#define WRAP(no, min, max) (((no) - (min) + ((max) - (min))) % ((max) - (min)))
#define CLAMP(no, min, max) (((no) < (min)) ? (min) : (((no) > (max)) ? (max) : (no)))

#endif
