/*
zcode.h 組合せに対応する整数への変換とその逆変換のヘッダファイル
   programmed by Isaku WADA 2009 isaku@pb4.so-net.ne.jp
 */

#ifndef __ZCODE_H
#define __ZCODE_H

#include <limits.h>
#include <stdlib.h>

/*+------------------------+
 |基本数値型 INDEX  の定義|
 +------------------------+*/
#ifndef INDEX
#define INDEX unsigned
#endif

/*+----------------+
 |テーブルの大きさ|
 +----------------+*/
#ifndef CODE_TABLE_SIZE
#define CODE_TABLE_SIZE (sizeof(INDEX)*sizeof(INDEX)*640)
#endif

/*+------------------------------------------+
 |RepeToNum , CombToNum で並べ替えを行う時に|
  |スタックに取る作業領域の最大値      |
 +------------------------------------------+*/
#ifndef CODE_SORT_R_MAX
#define CODE_SORT_R_MAX 64
#endif

/*+------------------------------------------+
 |NumToPerm でスタックに取る作業領域の最大値|
 +------------------------------------------+*/
#ifndef PERM_N_MAX
#define PERM_N_MAX 256
#endif

/*+------------+
 |エラーコード|
 +------------+*/
enum { CEC_MEMORY=1, CEC_OVERFLOW, CEC_PARAMETER };

/*+--------------------+
 |テーブル構造体の定義|
 +--------------------+*/
typedef struct _code_t {
    int ErrorCode,n,r,type;
    INDEX**a,**b,size;
#ifdef __cplusplus
    char*table;
    _code_t() { type=0; table=0; size=0; }
    ~_code_t() { delete[]table; }
#else
    char table[CODE_TABLE_SIZE];
#endif
} code_t;

#ifdef __cplusplus
#define  code0_t  code_t
#else
typedef struct {
    int ErrorCode,n,r,type;
    INDEX**a,**b,size;
    char*table;
} code0_t;
#endif

extern code0_t DefaultCodeTable[1];
extern volatile unsigned long MaxCodeTableSize;
extern INDEX InitCode_r(code_t*,int,int);
extern INDEX InitPerm_r(code_t*,int,int);
extern INDEX RepeToNum_r(code_t*,int*);
extern INDEX CombToNum_r(code_t*,int*);
extern INDEX PartToNum_r(code_t*,int*);
extern INDEX PermToNum_r(code_t*,int*);
extern void NumToRepe_r(code_t*,int*,INDEX);
extern void NumToComb_r(code_t*,int*,INDEX);
extern void NumToPart_r(code_t*,int*,INDEX);
extern void NumToPerm_r(code_t*,int*,INDEX);
#define InitRepe_r(T,N,R) InitCode_r(T,N,R)
#define InitComb_r(T,N,R) InitCode_r(T,(N)-(R)+1,R)
#define InitPart_r(T,N,R) InitCode_r(T,(N)+1,(R)-1)
#define InitRepe(N,R)  InitRepe_r((code_t*)DefaultCodeTable,N,R)
#define InitComb(N,R)  InitComb_r((code_t*)DefaultCodeTable,N,R)
#define InitPart(N,R)  InitPart_r((code_t*)DefaultCodeTable,N,R)
#define InitPerm(N,R)  InitPerm_r((code_t*)DefaultCodeTable,N,R)
#define RepeToNum(V)   RepeToNum_r((code_t*)DefaultCodeTable,V)
#define CombToNum(V)   CombToNum_r((code_t*)DefaultCodeTable,V)
#define PartToNum(V)   PartToNum_r((code_t*)DefaultCodeTable,V)
#define PermToNum(V)   PermToNum_r((code_t*)DefaultCodeTable,V)
#define NumToRepe(V,N) NumToRepe_r((code_t*)DefaultCodeTable,V,N)
#define NumToComb(V,N) NumToComb_r((code_t*)DefaultCodeTable,V,N)
#define NumToPart(V,N) NumToPart_r((code_t*)DefaultCodeTable,V,N)
#define NumToPerm(V,N) NumToPerm_r((code_t*)DefaultCodeTable,V,N)
#define CodeErrorCode DefaultCodeTable->ErrorCode

#endif