

#ifndef _INC_GENERATOR_
#define _INC_GENERATOR_

typedef long GenType;
typedef long GenSeed;

typedef struct _int_generator_struct_ {
  long current;
  long (*next)(struct _int_generator_struct_ *gen);
  GenType type;
  double place_holder;
} *IntGen;

typedef struct _float_generator_struct_ {
  double current;
  double (*next)(struct _float_generator_struct_ *gen);
  GenType type;
} *FloatGen;

typedef struct {long a, b;}             UniformIntParams;
typedef struct {double a, b;}         UniformFloatParams;
typedef struct {double mean, sigma;}      GaussianParams;
typedef struct {double lambda;}        ExponentialParams;

#define UNIFORM_INT_GEN          ((GenType) 1)
#define UNIFORM_FLOAT_GEN        ((GenType) 2)
#define GAUSSIAN_GEN             ((GenType) 3)
#define EXPONENTIAL_GEN          ((GenType) 4)

#define UNIFORM_INT_GEN_TYPE            IntGen
#define UNIFORM_FLOAT_GEN_TYPE        FloatGen
#define GAUSSIAN_GEN_TYPE             FloatGen
#define EXPONENTIAL_GEN_TYPE          FloatGen

#define UNIFORM_INT_GEN_PTYPE           UniformIntParams
#define UNIFORM_FLOAT_GEN_PTYPE       UniformFloatParams
#define GAUSSIAN_GEN_PTYPE                GaussianParams
#define EXPONENTIAL_GEN_PTYPE          ExponentialParams

#define NULLGEN   ((void *) NULL)

#define GEN_RAND_SEED         ((GenSeed) 0)


extern void *genNew_(GenType type, GenSeed seed, void *params);
extern void  genFree_(GenType type, void *gen);
extern void  genReset_(GenType type, void *gen, GenSeed seed);



#define genType(g)                 ((g) ? (g)->type : 0)  
#define genNew(t, s, p)            ({ t ## _PTYPE _p_ = p;    \
				      ((t ## _TYPE) genNew_((t), (s), (void *) &_p_));})
#define genFree(g)                 (genFree_(genType(g), (void *) (g)))
#define genNext(g)                 ((g)->next(g))
#define genCurr(g)                 ((g)->current)
#define genReset(g, s)             (genReset_(genType(g), (void *) (g), (s)))

#endif 



