/*	
 *	clipffa.h
 *
 *	有限体演算 (Finite Field Arithmetic)
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2015 Naoyuki Sawa
 *
 *	* Sun Aug 16 19:57:01 JST 2015 Naoyuki Sawa
 *	- 作成開始。
 *	* Sat Aug 22 15:44:43 JST 2015 Naoyuki Sawa
 *	- Polynomial_Parse()を追加しました。
 *	* Tue Aug 25 00:57:49 JST 2015 Naoyuki Sawa
 *	- Polynomial_ParseF(),Polynomial_ParseV()を追加しました。
 *	* Wed Aug 26 23:08:45 JST 2015 Naoyuki Sawa
 *	- BCH符号の関数を作成開始しました。
 *	* Fri Aug 28 20:48:55 JST 2015 Naoyuki Sawa
 *	- GaloisField_Det(),GaloisField_Cof(),GaloisField_Solve()を追加しました。
 *	* Sat Aug 29 00:01:08 JST 2015 Naoyuki Sawa
 *	- BCH_Decode()を追加しました。
 *	* Sun Aug 30 13:35:11 JST 2015 Naoyuki Sawa
 *	- GaloisField_Deg()を追加しました。
 *	* Sun Aug 30 18:40:22 JST 2015 Naoyuki Sawa
 *	- リードソロモン符号の関数を作成開始しました。
 *	* Mon Aug 31 21:31:32 JST 2015 Naoyuki Sawa
 *	- GaloisField_NewDeg()を追加しました。
 *	* Mon Oct 19 22:47:19 JST 2015 Naoyuki Sawa
 *	- BCH_EncodeN(),BCH_DecodeN(),ReedSolomon_EncodeN(),ReedSolomon_DecodeN()にコメントを追記しました。
 *	  まだ処理は変更していません。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 */
#ifndef __CLIP_FFA_H__
#define __CLIP_FFA_H__
#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus
/****************************************************************************
 *	ガロア体
 ****************************************************************************/
typedef struct _ST_GaloisField {
	uint8_t		max;		//(2^deg)-1	(2^deg)-1=1〜255	ビット列表現の最大値
	uint8_t		deg;		//   deg	   deg=1〜8		拡大次数
	uint8_t		exp[256];	//exp[i]=a^i	i=0〜max-1,a^i=1〜max	指数表現⇒ビット列表現
	uint8_t		log[256];	//log[a^i]=i	a^i=1〜max,i=0〜max-1	ビット列表現⇒指数表現
} ST_GaloisField;
/*--------------------------------------------------------------------------*/
ST_GaloisField* GaloisField_New(int Gx);
ST_GaloisField* GaloisField_NewDeg(int deg);
void GaloisField_Free(ST_GaloisField* pGF);
int GaloisField_Max(ST_GaloisField* pGF);
int GaloisField_Deg(ST_GaloisField* pGF);
int GaloisField_Exp(ST_GaloisField* pGF, int i);
int GaloisField_Log(ST_GaloisField* pGF, int c);
int GaloisField_Add(ST_GaloisField* pGF, int x, int y);
int GaloisField_Sub(ST_GaloisField* pGF, int x, int y);
int GaloisField_Mul(ST_GaloisField* pGF, int x, int y);
int GaloisField_Div(ST_GaloisField* pGF, int x, int y);
int GaloisField_Det(ST_GaloisField* pGF, const uint8_t* A/*[n][n]*/, int n);
int GaloisField_Cof(ST_GaloisField* pGF, const uint8_t* A/*[n][n]*/, int n, int i, int j);
int GaloisField_Solve(ST_GaloisField* pGF, const uint8_t* A/*[n][n]*/, const uint8_t* b/*[n]*/, uint8_t* x/*[n]*/, int n);
/****************************************************************************
 *	多項式
 ****************************************************************************/
typedef struct _ST_Polynomial {
	ST_GaloisField*		pGF;		//ガロア体のポインタ	ガロア体の作成と開放は、呼び出し側の処理でおこなってください。
	uint8_t			coef[256];	//係数テーブル		coef[0]*(x^0) + coef[1]*(x^1) + ... + coef[255]*(x^255)
} ST_Polynomial;
/*--------------------------------------------------------------------------*/
ST_Polynomial* Polynomial_New(ST_GaloisField* pGF);
void Polynomial_Free(ST_Polynomial* pP);
int Polynomial_Deg(ST_Polynomial* pP);
int Polynomial_GetCoef(ST_Polynomial* pP, int i);
void Polynomial_SetCoef(ST_Polynomial* pP, int i, int c);
void Polynomial_AddCoef(ST_Polynomial* pP, int i, int c);
void Polynomial_SubCoef(ST_Polynomial* pP, int i, int c);
void Polynomial_MulCoef(ST_Polynomial* pP, int i, int c);
void Polynomial_DivCoef(ST_Polynomial* pP, int i, int c);
ST_Polynomial* Polynomial_Add(ST_Polynomial* pP1, ST_Polynomial* pP2);
ST_Polynomial* Polynomial_Sub(ST_Polynomial* pP1, ST_Polynomial* pP2);
ST_Polynomial* Polynomial_Mul(ST_Polynomial* pP1, ST_Polynomial* pP2);
ST_Polynomial* Polynomial_Div(ST_Polynomial* pP1, ST_Polynomial* pP2);
ST_Polynomial* Polynomial_Mod(ST_Polynomial* pP1, ST_Polynomial* pP2);
int Polynomial_Assign(ST_Polynomial* pP, int x);
char* Polynomial_Str(ST_Polynomial* pP);
ST_Polynomial* Polynomial_Parse(ST_GaloisField* pGF, const char* str);
ST_Polynomial* Polynomial_ParseF(ST_GaloisField* pGF, const char* fmt, ...);
ST_Polynomial* Polynomial_ParseV(ST_GaloisField* pGF, const char* fmt, va_list ap);
/****************************************************************************
 *	BCH符号
 ****************************************************************************/
typedef struct _ST_BCH {
	ST_GaloisField*		pGF;	//ガロア体のポインタ	ガロア体の作成と開放は、呼び出し側の処理でおこなってください。
	ST_Polynomial*		pGP;	//生成多項式
	uint8_t			q;	//訂正可能符号語数
	uint8_t			d;	//符号間距離=訂正可能符号語数*2+1
	uint8_t			n;	//総符号語数
	uint8_t			k;	//情報符号語数
	uint8_t			m;	//検査符号語数=総符号語数-情報符号語数
} ST_BCH;
/*--------------------------------------------------------------------------*/
ST_BCH* BCH_New(ST_GaloisField* pGF, int q);
void BCH_Free(ST_BCH* pBCH);
void BCH_Encode( ST_BCH* pBCH, const void* aInfo/*int[(k+31)/32]*/, void* aSend/*int[(n+31)/32]*/);
void BCH_EncodeN(ST_BCH* pBCH, const void* aInfK/*int[(K+31)/32]*/, void* aSenN/*int[(N+31)/32]*/, int N);	//短縮BCH符号
int  BCH_Decode( ST_BCH* pBCH, const void* aRecv/*int[(n+31)/32]*/, void* aInfo/*int[(k+31)/32]*/);
int  BCH_DecodeN(ST_BCH* pBCH, const void* aRecN/*int[(N+31)/32]*/, void* aInfK/*int[(K+31)/32]*/, int N);	//短縮BCH符号
/****************************************************************************
 *	リードソロモン符号
 ****************************************************************************/
typedef struct _ST_ReedSolomon {
	ST_GaloisField*		pGF;	//ガロア体のポインタ	ガロア体の作成と開放は、呼び出し側の処理でおこなってください。
	ST_Polynomial*		pGP;	//生成多項式
	uint8_t			q;	//訂正可能符号語数
	uint8_t			d;	//符号間距離=訂正可能符号語数*2+1
	uint8_t			n;	//総符号語数
	uint8_t			k;	//情報符号語数
	uint8_t			m;	//検査符号語数=総符号語数-情報符号語数
} ST_ReedSolomon;
/*--------------------------------------------------------------------------*/
ST_ReedSolomon* ReedSolomon_New(ST_GaloisField* pGF, int q);
ST_ReedSolomon* ReedSolomon_NewM(ST_GaloisField* pGF, int m);	//QRコード用
void ReedSolomon_Free(ST_ReedSolomon* pRS);
void ReedSolomon_Encode( ST_ReedSolomon* pRS, const void* aInfo/*int[(r*k+31)/32]*/, void* aSend/*int[(r*n+31)/32]*/);		//r=pGF->deg
void ReedSolomon_EncodeN(ST_ReedSolomon* pRS, const void* aInfK/*int[(r*K+31)/32]*/, void* aSenN/*int[(r*N+31)/32]*/, int N);	//r=pGF->deg	//短縮RS符号
int  ReedSolomon_Decode( ST_ReedSolomon* pRS, const void* aRecv/*int[(r*n+31)/32]*/, void* aInfo/*int[(r*k+31)/32]*/);		//r=pGF->deg
int  ReedSolomon_DecodeN(ST_ReedSolomon* pRS, const void* aRecN/*int[(r*N+31)/32]*/, void* aInfK/*int[(r*K+31)/32]*/, int N);	//r=pGF->deg	//短縮RS符号
#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus
#endif//__CLIP_FFA_H__
