C/C++ create random noise (gaussian noise/white noise)

I was amazed when use randn command at Matlab. randn command will generate random data every we call that command. After I search at google, I found how to make this happen. I get this code at seismic unix source code. This code will generate random noise or white noise with Gaussian method. Code for main.c is :

#include <stdio.h>
#include <stdlib.h>
#include "frannor.h"

int main(int argc, char **argv)
{
	double *noise=NULL;
	int i;
	int ndata;
	unsigned int seed;

	if(argc!=2)
	{
		fprintf(stderr, "usage : random 5");
		exit(0);
	}

	ndata = atoi(argv[1]);

	if (-1 == (seed = (unsigned int) time((time_t *) NULL)))
	{
		fprintf(stderr, "time() failed to set seed");
		exit(0);
	}

	srannor(seed);  //seed random number generator
	noise = (double*) calloc (ndata, sizeof(double));
	for(i=0; i<ndata; i++)  //create random data
	{
		/* Compute noise vector elements in [-1, 1] */
		/* GAUSS METHOD. frannor gives elements in N(0,1)--ie. pos & negs */
		noise[i] = (double) frannor();
	}

	for(i=0; i<ndata; i++)
		printf("%3.2f   ", noise[i]);
	printf("\n");

	free(noise);  //free allocated memory
	return(1);
}

This is code for frannor.h :

#ifndef FRANNOR_H_
#define FRANNOR_H_

#include <math.h>
#define ABS(x) ((x) < 0 ? -(x) : (x))
#define AA 12.37586
#define Bsu 0.4878992
#define Csu 12.67706
#define C1 0.9689279
#define C2 1.301198
#define PC 0.01958303
#define XN 2.776994
#define OXN 0.3601016
#define NBITS 24

/* macro to generate a random number uni uniform on [0,1) */
#define UNI(uni) \
	uni = u[i]-u[j]; if (uni<0.0) uni += 1.0; u[i] = uni; \
	if (--i<0) i = 16;  if (--j<0) j = 16

float frannor(void);
void srannor (int seed);

#endif /* FRANNOR_H_ */

This is code for frannor.c :

/* Copyright (c) Colorado School of Mines, 2010.*/
/* All rights reserved.                       */

/*********************** self documentation **********************/
/*****************************************************************************
FRANNOR - functions to generate a pseudo-random float normally distributed
		with N(0,1); i.e., with zero mean and unit variance.

frannor		return a normally distributed random float
srannor		seed random number generator for normal distribution

******************************************************************************
Function Prototypes:
float frannor (void);
void srannor (int seed);

******************************************************************************
frannor:
Input:		(none)
Returned:	normally distributed random float

srannor:
Input:
seed		different seeds yield different sequences of random numbers.

******************************************************************************
Notes:
Adapted from subroutine rnor in Kahaner,  Moler and Nash (1988)
which in turn was based on  an algorithm by
Marsaglia and Tsang (1984).

******************************************************************************
References:
"Numerical Methods and Software", D.
Kahaner, C. Moler, S. Nash, Prentice Hall, 1988.

Marsaglia G. and Tsang, W. W., 1984,
A fast, easily implemented method for sampling from decreasing or symmetric
unimodal density functions:  SIAM J. Sci. Stat. Comput., v. 5, no. 2,
p. 349-359.

*****************************************************************************
Author:  Dave Hale, Colorado School of Mines, 01/21/89
*****************************************************************************/
/**************** end self doc ********************************/

#include "frannor.h"

static float v[]={
	0.3409450, 0.4573146, 0.5397793, 0.6062427, 0.6631691,
	0.7136975, 0.7596125, 0.8020356, 0.8417227, 0.8792102, 0.9148948,
	0.9490791, 0.9820005, 1.0138492, 1.0447810, 1.0749254, 1.1043917,
	1.1332738, 1.1616530, 1.1896010, 1.2171815, 1.2444516, 1.2714635,
	1.2982650, 1.3249008, 1.3514125, 1.3778399, 1.4042211, 1.4305929,
	1.4569915, 1.4834526, 1.5100121, 1.5367061, 1.5635712, 1.5906454,
	1.6179680, 1.6455802, 1.6735255, 1.7018503, 1.7306045, 1.7598422,
	1.7896223, 1.8200099, 1.8510770, 1.8829044, 1.9155830, 1.9492166,
	1.9839239, 2.0198430, 2.0571356, 2.0959930, 2.1366450, 2.1793713,
	2.2245175, 2.2725185, 2.3239338, 2.3795007, 2.4402218, 2.5075117,
	2.5834658, 2.6713916, 2.7769943, 2.7769943, 2.7769943, 2.7769943
};

/* internal state variables for uniform random number generator */
static  int i=16,j=4;
static  float u[]={
	0.8668672834288,  0.3697986366357,  0.8008968294805,
	0.4173889774680,  0.8254561579836,  0.9640965269077,
	0.4508667414265,  0.6451309529668,  0.1645456024730,
	0.2787901807898,  0.06761531340295, 0.9663226330820,
	0.01963343943798, 0.02947398211399, 0.1636231515294,
	0.3976343250467,  0.2631008574685
};

float frannor(void)
/**************************************************************************
return a normally distributed random float
 ***************************************************************************
Returned:	normally distributed random float
 **************************************************************************/
{
	int k;
	float uni,vni,rnor,x,y,s,bmbx,xnmx;

	/* uni is uniform on [0,1) */
	UNI(uni);

	/* vni is uniform on [-1,1) */
	vni = uni+uni-1.0;

	/* k is in range [0,63] */
	k = ((int)(u[i]*128))%64;

	/* fast part */
	rnor = vni*v[k+1];
	if (ABS(rnor)<=v[k]) return rnor;

	/* slow part */
	x = (ABS(rnor)-v[k])/(v[k+1]-v[k]);
	UNI(y);
	s = x+y;
	if (s<=C2) {
		if (s<=C1) return rnor;
		bmbx = Bsu-Bsu*x;
		if (y<=Csu-AA*exp(-0.5*bmbx*bmbx)) {
			if (exp(-0.5*v[k+1]*v[k+1])+y*PC/v[k+1] <=
					exp(-0.5*rnor*rnor)) return rnor;
			do {
				UNI(y);
				x = OXN*log(y);
				UNI(y);
			} while (-2.0*log(y)<=x*x);
			xnmx = XN-x;
			return (rnor>=0.0 ? ABS(xnmx) : -ABS(xnmx));
		}
	}
	bmbx = Bsu-Bsu*x;
	return (rnor>=0.0 ? ABS(bmbx) : -ABS(bmbx));
}

void srannor (int seed)
/*****************************************************************************
seed random number generator
 ******************************************************************************
Input:
seed		different seeds yield different sequences of random numbers.
 *****************************************************************************/
{
	int ii,jj,ia,ib,ic,id;
	float s,t;

	i = 16;
	j = 4;
	ia=ABS(seed)%32707;
	ib=1111;
	ic=1947;
	for (ii=0; ii<17; ii++) {
		s = 0.0;
		t = 0.5;
		for (jj=0; jj<64; jj++) {
			id = ic-ia;
			if (id<0) {
				id += 32707;
				s += t;
			}
			ia = ib;
			ib = ic;
			ic = id;
			t *= 0.5;
		}
		u[ii] = s;
	}
}

To compile this source code, use command :

gcc main.c frannor.c -lm -o random

This is output from program :

toto@toto-laptop:/home/toto/$ ./random 6
0.08   1.78   -1.35   -1.03   1.62   0.07
toto@toto-laptop:/home/toto/$ ./random 6
1.12   1.32   0.73   -0.34   0.25   -0.58

Source : http://www.cwp.mines.edu/cwpcodes/index.html

One Comment

Add a Comment

Your email address will not be published. Required fields are marked *

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.