/*===========================================================================
  Copyright (C) 1995-2009 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY

.VERSION
 090826         last modif

===========================================================================*/


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

#ifndef PI   
#define PI 3.141592654  /* as in stroustrup */
#endif

/* -------------------------------------------------------------------
float	random_local()

purpose: draw random numbers between 0 and 1 under an uniform law
-------------------------------------------------------------------*/

#define M1 259200
#define IA1 7141
#define IC1 54773
#define RM1 (1.0/M1)
#define M2 134456
#define IA2 8121
#define IC2 28841
#define RM2 (1.0/M2)
#define M3 243000
#define IA3 4561
#define IC3 51349

float random_local(idum)
int *idum;

{
	static long ix1,ix2,ix3;
	static float r[98];
	float temp;
	static int iff=0;
	int j;
	void nrerror();

	if (*idum<0 || iff==0)
	{
		iff=1;
		ix1=(IC1-(*idum)) % M1;
		ix1=(IA1*ix1+IC1) % M1;
		ix2=ix1%M2;
		ix1=(IA1*ix1+IC1) % M1;
		ix3=ix1%M3;
		for(j=1;j<=97;j++)
		{
			ix1=(IA1*ix1+IC1) % M1;
			ix2=(IA2*ix2+IC2) % M2;
			r[j]=(ix1+ix2*RM2)*RM1;	
		}
	*idum=1;
	}
	ix1=(IA1*ix1+IC1) % M1;
	ix2=(IA2*ix2+IC2) % M2;
	ix3=(IA3*ix3+IC3) % M3;
	j=1+((97*ix3)/M3);
	if(j>97 || j<1) {printf("je me suis plantee\n"); j=abs(*idum);};
	temp=r[j];
	r[j]=(ix1+ix2*RM2)*RM1;
	return temp;
}

/* -------------------------------------------------------------------
float	poisson()

purpose: draw numbers under an poisson law
-------------------------------------------------------------------*/

float poisson(xm,idum)

float xm;
int *idum;

{
static float sq,alxm,g,oldm=(-1.0);
float em,t ,y;
float random_local(),lngam();

if(xm<12.0)
	{
	if(xm!=oldm)
		{
		oldm=xm;
		g=exp(-1.*xm);
		};
	em=(-1);
	t=1.0;
	do
		{
		em+=1.0;
		t*=random_local(idum);
		}while(t>g);
	}
else
	{
	if(xm!=oldm)
                {
                oldm=xm;
                sq=sqrt(2.0*xm);
		alxm=log(xm);
		g=xm*alxm-lngam(xm+1.0);
		};
	do
		{
		do
			{
			y=tan(PI*random_local(idum));
			em=sq*y+xm;
			}while(em<0.0);
		em=floor(em);
		t=.9*(1.0+y*y)*exp(em*alxm-lngam(em+1.0)-g);
		}while(random_local(idum)>t);
	};
return (em);
}

/******************************************************/

float lngam(a)

float a;

{
double cof[6],stp,half=.5,one=1.,fpf=5.5,x,tmp,ser;
double pi;
double atemp;
float gama,gama1;
int i;

pi=3.141592654;
atemp=10.;
stp=2.50662827465;
cof[0]=76.18009173;
cof[1]=(-86.50532033);
cof[2]=24.01409822;
cof[3]=(-1.231739516);
cof[4]=0.120858003e-2;
cof[5]=(-0.536382e-5);
 
if(a==1)
	gama=1.;
else
	{
	if(a<1.)
		{
		atemp=1.;
		a=2.-a;	
		};
	x=a-one;
	tmp=x+fpf;
	tmp=(x+half)*log(tmp)-tmp;
	ser=one;
	for(i=0;i<6;i++)
		{
		x+=one;
		ser+=cof[i]/x;
		};
	gama1=tmp+log(stp*ser);
	gama=gama1;
	if(atemp<1.)
		{
		pi=pi*(a-1.);
		gama=log(pi/sin(pi))-gama;
		a=atemp;
		};
	};
return(gama);
}

/* -------------------------------------------------------------------
float	gauss()

purpose: draw numbers under an gaussian law
-------------------------------------------------------------------*/

float gauss(sig,idum)

float sig;
int *idum;

{
float x,z,r;
float random_local();

while( (z = pow(x=random_local(idum)-0.5,2.0) + pow(random_local(idum)-0.5,2.0) ) > 0.25 );
while ((r=random_local(idum))<=0.0);

return  sig*sqrt(-2.0*log(r)/z)*x;

}
