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

#ifndef __ZCODE_H
#define __ZCODE_H

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

#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__MINGW32__)
 #define __int64 long long
#endif

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

/*+----------------+
 |テーブルの大きさ|
 +----------------+*/
#ifndef CODE_TABLE_SIZE
 #if INT_MAX <= 32767
  #define CODE_TABLE_SIZE 2048
 #else
  #define CODE_TABLE_SIZE 10240
 #endif
#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