#include <stdio.h>
#include <math.h>

#include "NombreAleatoireMersenneTwister.h"

unsigned long NombreAleatoireMersenneTwister::genrand(void) {
  unsigned long y;
  if ( first == 1 ) {
   	mag01[0] = 0x0;
	  mag01[1] = MATRIX_A;
  	first = 0; }
  if ( mti >= N ) {
    int kk;
    if ( mti == N+1 )
      init(4357);
    for ( kk = 0 ; kk < N-M ; kk++ ) {
      y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
      mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1]; }
    for ( ; kk < N-1 ; kk++ ) {
      y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
      mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1]; }
    y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
    mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
    mti = 0; }
  y = mt[mti++];
  y ^= TEMPERING_SHIFT_U(y);
  y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
  y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
  y ^= TEMPERING_SHIFT_L(y);
  return(y);
}

NombreAleatoireMersenneTwister::NombreAleatoireMersenneTwister(void) {
  init(111);
}

NombreAleatoireMersenneTwister::NombreAleatoireMersenneTwister(unsigned long seed) {
  init(seed);
}

void NombreAleatoireMersenneTwister::init(unsigned long sseed) {
  if ( sseed == 0 )
    sseed = 111111111;
  first = 1;
  mt[0] = sseed & 0xffffffffU;
  for ( mti = 1 ; mti < N ; mti++ )
    mt[mti] = (69069 * mt[mti-1]) & 0xffffffffU;
}

int NombreAleatoireMersenneTwister::rand(int limite) {
  unsigned long v = genrand();
  return(v%limite);
}

long NombreAleatoireMersenneTwister::rand(long limite) {
  unsigned long v = genrand();
  return(v%limite);
}

float NombreAleatoireMersenneTwister::rand(float limite) {
  return(rand(1000000001)/1000000000.0F * limite);
}

double NombreAleatoireMersenneTwister::rand(double limite) {
  return(rand(1000000001)/1000000000.0 * limite);
}

float NombreAleatoireMersenneTwister::rand(float limite,unsigned long sseed) {
  init(sseed);
  return(rand(limite));
}

double NombreAleatoireMersenneTwister::rand(double limite,unsigned long sseed) {
  init(sseed);
  return(rand(limite));
}

double NombreAleatoireMersenneTwister::rand(double limite,double sseed) {
  int((unsigned long) (sseed*11259.5));
  return(rand(limite));
}

double NombreAleatoireMersenneTwister::rand_0_1(void) {
  double a = genrand()/30000001.0 ;
  return(a-floor(a)) ;
}

NombreAleatoireMersenneTwister::~NombreAleatoireMersenneTwister(void) {
}

