#include "shared_peel.h"
#include "bin_tree.h"

#define OP_SAMPLING 128

#define SAMPLED_MAT 128
#define SAMPLED_PAT 256

#define LOCUS_SAMPLED 128
#define RFMASK_OK 256
#define TL_UNLINKED 1
#define TL_LINKED 2
#define TL_UPDATING 4

struct R_Func
{
	int n_ind;
	int n_terms;
	lk_ulong mask[2];
	int mask1[2];
	int *id_list;
	lk_ulong *index;
	double *p;
	int flag;
};

struct hash_data
{
	lk_ulong index;
	double p;
};

struct hash_block
{
	struct hash_block *next;
	struct bin_node *elements;
	struct hash_data *hd;
	int size,ptr;
};

struct peel_mem_block
{
	struct peel_mem_block *next;
	lk_ulong *index;
	double *val;
	size_t size,ptr;
};

struct fset
{
	int pat_gene[2];
	int mat_gene[2];
	double p;
};

typedef void pen_func(double *,int,int,int,int);
typedef void trait_pen_func(double *,int,int);

extern pen_func penetrance;
extern trait_pen_func s_penetrance,s_penetrance1;
double q_penetrance(int,int,int);

/* Peeling output level - controlled by lower 3 bits in peel_trace */
#define TRACE_LEVEL_0 0
#define TRACE_LEVEL_1 1
#define TRACE_LEVEL_2 2
#define TRACE_LEVEL_3 3
#define TRACE_LEVEL_4 4
#define TRACE_MASK 7

#define CHK_PEEL(x) (((*peel_trace)&TRACE_MASK)>=(x))

#define MRK_MBLOCK 0
#define TRT_MBLOCK 1
#define MB_SIZE 4096

extern struct peel_mem_block *first_mem_block[2],*mem_block[2];

extern struct R_Func ***r_func;
extern int ***allele_trans;
extern lk_ulong ***all_set,**req_set[2];
extern struct Peelseq_Head **peelseq_head;
extern int max_peel_off;

extern double peel_locus(const int *,int,int,int,struct peel_mem *,int);
extern void free_complex_mem(void);
extern int cmp_loci_pos(const void *,const void *);
extern void set_sort_sex(const int);
extern void peel_alloc(struct peel_mem *);
extern void peel_dealloc(struct peel_mem *);
extern void get_locuslist(int *,const int,int *,int);
extern double loki_complex_peelop(const struct Complex_Element *,const int,const int,pen_func,const int,struct R_Func *,double **);
extern double loki_trait_complex_peelop(const struct Complex_Element *,const int,const int,struct R_Func *,trait_pen_func *,double **);
extern void get_rf_memory(struct R_Func *,size_t,int);
extern lk_ulong get_index1(int,int *,const int);
struct peel_mem_block *get_new_memblock(size_t,int);
