/////////////////////////////////////////////////////////////////////////////
// random2.cc
//
// SIMLIB version: 2.18
// Date: 2004-01-25
//
// Copyright (c) 1991-2004 Petr Peringer 
//
// This library is licensed under GNU Library GPL. See the file COPYING.
//

//
//  random number generators (dependent on Random())
//

////////////////////////////////////////////////////////////////////////////
// interface
//

#include "simlib.h"
#include "internal.h"

#include <cmath>  // exp() floor() log() pow() sqrt()


////////////////////////////////////////////////////////////////////////////
// implementation
//

SIMLIB_IMPLEMENTATION

////////////////////////////////////////////////////////////////////////////
//  _gam
//
static double _gam(double AK)
{
  int K,i;
  double FK,PROD,DG,G,W;

  FK = K = (int) floor(AK);
  G = 0.0;
  if (K>0)
  {
    PROD = 1.0;
    for(i=1; i<=K; i++)  PROD *= Random();
    G = -log(PROD);
  }

  DG = AK-FK;
  if (DG <= 0.015)  return (G);
  if (DG >=0.935)   W=1.0;
  else
  {
    double A,B,X,Y;
    A = 1.0/DG;
    B = 1.0/(1.0-DG);
    do{
      X = pow(Random(),A);
      Y = pow(Random(),B+X);
    }while (Y>1.0);
    W = X/Y;
  }
  G += W*(-log(Random()));
  return (G);
}

////////////////////////////////////////////////////////////////////////////
//  Uniform - uniform random number generator
//
double Uniform(double l, double h)
{
  if( l >= h ) SIMLIB_error(BadUniformParam);
  return(l+(h-l)*Random());
}

////////////////////////////////////////////////////////////////////////////
//  Normal(mi,sigma)
//  mi    = mean value
//  sigma = std deviation? (smerodatna odchylka) ###
//
double Normal(double mi, double sigma)
{
  int i;
  double SUM = 0.0;
  for (i=0; i<12; i++)  SUM += Random();
  return (SUM-6.0)*sigma + mi;
}

////////////////////////////////////////////////////////////////////////////
//  Weibul
//
double Weibul(double lambda, double alfa)
{
  double R,W;

  if (lambda<=0.0 || alfa<=1.0)  SIMLIB_error(WeibullError);

  while ((R=Random()) == 0 || R == 1);
  W= pow (-1.0/lambda*log(1.0-R), 1.0/alfa);
  return (W);
}

////////////////////////////////////////////////////////////////////////////
//  Erlang
//
double Erlang(double alfa, int beta)
{
  double ER = 1.0;
  int i;
  if (beta<1)  SIMLIB_error(ErlangError);
  for (i=0; i<beta; i++)  ER *= Random();
  return -alfa*log(ER);
}

////////////////////////////////////////////////////////////////////////////
//  NegBin
//
int NegBin(double q, int k)
{
  double IS,XLOGQ,R;
  int i;

  if (k<=0 || q<=0)  SIMLIB_error(NegBinError);

  IS = 0;
  XLOGQ = log(q);
  for (i=1; i<=k; i++)
  {
    while ((R=Random()) == 0);
    IS += log(R)/XLOGQ;
  }
  return int(IS);
}

////////////////////////////////////////////////////////////////////////////
//  Gama
//
double Gama(double alfa, double beta)
{
  double G;

  G = _gam(alfa)*beta;
  return (G);
}

////////////////////////////////////////////////////////////////////////////
//  Exponential(mv)
//
double Exponential(double mv)
{
  return -mv*log(Random());
}



////////////////////////////////////////////////////////////////////////////
//
//
int NegBinM(double p, int m)
{
  int i,ix;

  if (m<=0)        SIMLIB_error(NegBinMError1);
  if (p<0 || p>1)  SIMLIB_error(NegBinMError2);
  ix = i = 0;
  do{
    if (Random() <= p)  ix++;
    i++;
  }while (i <= m);
  return (ix);
}

////////////////////////////////////////////////////////////////////////////
//  Beta
//
double Beta(double th, double fi, double min, double max)
{
  double X;
  X = _gam(th);
  X = X/(X+_gam(fi));
  X = X*(max-min)+min;
  return (X);
}

////////////////////////////////////////////////////////////////////////////
//  Triag(mod,min,max)
//
double Triag(double mod, double min, double max)
{
  double RN,BMA,CMA,TR;

  RN=Random();
  BMA=mod-min;
  CMA=max-min;
  if  (RN<BMA/CMA)
    TR=min+sqrt(BMA*CMA*RN);
  else
    TR=max-sqrt(CMA*(1.0-RN)*(max-mod));
  return (TR);
}

////////////////////////////////////////////////////////////////////////////
//  Log
//
double Logar(double mi, double delta)
{
  double VA = Normal(mi, delta);
  return exp(VA);
}

////////////////////////////////////////////////////////////////////////////
//  Rayle(delta)
//
double Rayle(double delta)
{
  double R;
  while ((R=Random()) == 0);
  return  delta * sqrt(-log(R));
}

////////////////////////////////////////////////////////////////////////////
//  Poisson(double lambda)
//
int Poisson(double lambda)
{
  double Y,X;
  int PSSN = 0;
  if (lambda<=0) SIMLIB_error(PoissonError);
  if (lambda <= 9.0)
  {
    Y=exp(-lambda);
    X=1.0;
    do{
      X *= Random();
      if (X<Y) break;
      PSSN++;
    }while(1);
  }
  else
  {
    double sl=sqrt(lambda);
    do
      PSSN = (int) (Normal(lambda, sl) + 0.5);  /* round ???### */
    while (PSSN<0);
  }
  return PSSN;
}

////////////////////////////////////////////////////////////////////////////
//  Geom(q)
//
int Geom(double q)
{
  double X,R;

  if (q<=0)  SIMLIB_error(GeomError);
  while ((R=Random()) == 0);
  X = log(R)/log(q);
  return int(X);
}

////////////////////////////////////////////////////////////////////////////
//  HyperGeometric
//
int HyperGeom(double p, int n, int m)
{
  int IX,i;
  if (m <= 0)           SIMLIB_error(HyperGeomError1);
  if (p<0 || p>1)       SIMLIB_error(HyperGeomError2);
  IX=0;
  for (i=1; i<=n; i++)
  {
    if (Random() > p)
      p =m*p/(m-1);
    else
    {
      IX++;
      p=(m*p-1.0)/(m-1);
    }
    m--;
  }
  return (IX);
}

////////////////////////////////////////////////////////////////////////////
//  Binom(n,theta)
//  n     = # of experiments (pocet pokusu)
//  theta = probability
//
/*
int Binom(unsigned n, double theta)
{
  int BNM;
  double SUM,R,TT,x;
  if (theta<0 || theta>1) SIMLIB_error(BinomError);
  SUM = R = pow(1-theta,n);
  TT = theta/(1-theta);
  BNM = 0;
  x = Random();
  while(x-SUM > 0)
  {
    R *= (n-BNM)/(BNM+1)*TT;
    SUM += R;
    BNM++;
  }
  return (BNM);
}
*/

////////////////////////////////////////////////////////////////////////////
// end of RANDOM2.CPP
////////////////////////////////////////////////////////////////////////////



syntax highlighted by Code2HTML, v. 0.9.1