/*	
 *	clipjkis.h
 *
 *	JKISS32擬似乱数
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2012 Naoyuki Sawa
 *
 *	* Thu Dec 06 17:08:54 JST 2012 Naoyuki Sawa
 *	- 1st リリース。
 *	- JKISS32擬似乱数の資料を、keep/JKISS32擬似乱数.7zに保存しました。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 */
#ifndef __CLIP_JKIS_H__
#define __CLIP_JKIS_H__

#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus

/****************************************************************************
 *	JKISS32擬似乱数
 ****************************************************************************/

typedef struct _JKISS32 {
	unsigned x;	/* + 0,4 0〜0xFFFFFFFF */
	unsigned y;	/* + 4,4 1〜0xFFFFFFFF */
	unsigned z;	/* + 8,4 0〜0x7FFFFFFF */	//ドキュメントには明記されていませんが、処理内容を追うと、ビット31=0固定であることが判ります。
	unsigned w:31;	/* +12,4 0〜0x7FFFFFFF */	//ドキュメントには明記されていませんが、処理内容を追うと、ビット31=0固定であることが判ります。
	unsigned c: 1;	/*       0〜1 */
} JKISS32;		/* =16 */

/* 擬似乱数生成器を初期化します。
 * [in]
 *	self		擬似乱数生成器。
 *	s		シード。
 */
void JKISS32_init(JKISS32* self, unsigned s);

/* 32ビット符号無し乱数を生成します。
 * [in]
 *	self		擬似乱数生成器。
 * [out]
 *	戻り値		32ビット符号無し乱数。
 * [note]
 *	- 周期は 約 2^121 (=2.6×10^36) です。
 */
unsigned JKISS32_next(JKISS32* self);

//	オリジナルコードの処理順序を入れ替えて、最適化しました。
//	処理順序を入れ替えましたが、処理結果は変わっていません。
//	処理結果が一致していることを、以下の方法で確認しました。
//	
//	#define JKISS32 JKISS32_original_code
//	//{{--- 原文「http://www.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf」より ---
//	/* Implementation of a 32-bit KISS generator which uses no multiply instructions */
//	static unsigned int x=123456789,y=234567891,z=345678912,w=456789123,c=0;
//	unsigned int JKISS32()
//	{
//	int t;
//	y ^= (y<<5); y ^= (y>>7); y ^= (y<<22);
//	t = z+w+c; z = w; c = t < 0; w = t&2147483647;
//	x += 1411392427;
//	return x + y + w;
//	}
//	//}}--- 原文「http://www.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf」より ---
//	#undef JKISS32
//	
//	void test() {
//		int i, a, b;
//		//最適化したコードで100000回目の乱数値を取得
//		JKISS32 j = {x,y,z,w,c};//オリジナルコードと同じ初期状態から開始
//		for(i = 0; i < 100000; i++) {
//			a = JKISS32_next(&j);
//		}
//		//オリジナルコードで100000回目の乱数値を取得
//		for(i = 0; i < 100000; i++) {
//			b = JKISS32_original_code();
//		}
//		//最適化したコードとオリジナルコードの乱数値が一致することを確認
//		die("最適化ｺｰﾄﾞ:%d\n"		//⇒結果:-431900388
//		    "ｵﾘｼﾞﾅﾙｺｰﾄﾞ:%d", a, b);	//⇒結果:-431900388
//	}

#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus

#endif /*__CLIP_JKIS_H__*/
