//
// Gaussian
//
// Copyright (C) 1992 Contemporary Design Studios. All rights reserved.
//


#import "Gaussian.h"
#import <math.h>
#import <stdio.h>


@implementation Gaussian


//
// init
//

- initEngineInstance:anObject
{
    [super initEngineInstance:anObject];		
    
    iset = 0;				// No saved gaussian yet.
    gset = 0.0;
    
    gscale = 1.0;
    gorigin = 0.0;

    return self;
}


//
// gScale
//

- (double)gScale
{
    return gscale;
}


//
// setGScale:
//

- setGScale:(double)aScale
{
    gscale = aScale;
    
    return self;
}


//
// gOrigin
//

- (double)gOrigin
{
    return gorigin;
}


//
// setGOrigin:
//

- setGOrigin:(double)anOrigin
{
    gorigin = anOrigin;
    
    return self;
}


//
// gaussian
//

- (double)gaussian
{
    double		fac, r, temp;
    volatile double	v1, v2;			// Prevent compiler warning about un-init.
    
    if(iset == 0) {				// If none stored, calculate a pair.
        do {					// Find a pair which are inside unit circle.
	    v1 = 2.0 * [self percent] - 1.0;
	    v2 = 2.0 * [self percent] - 1.0;
	    r = (v1 * v1) + (v2 * v2);
	} while((r >= 1.0) || (r == 0.0));
	
	fac = sqrt(-2.0 * log(r) / r);		// Do Box-Muller transformation.
	gset = v1 * fac;
	iset = 1;
	
	temp = v2 * fac;			// Return one of the pair.
	
//	printf("Gaussian: New value = %f, new stored value = %f\n", temp, gset);
    }
    else {					// Otherwise return stored one.
        iset = 0;
	temp = gset;
    }
    
    return ((temp * gscale) + gorigin);		// Modify the variable.
}


//
// read:
//

- read:(NXTypedStream *)stream
{
    [super read:stream];
    
    NXReadTypes(stream, "iddd", &iset, &gset, &gscale, &gorigin);
    
    return self;
}


//
// write:
//

- write:(NXTypedStream *)stream
{
    [super write:stream];
    
    NXWriteTypes(stream, "iddd", &iset, &gset, &gscale, &gorigin);

    return self;
}


@end


//
// End of file.
//