//  Swarm library. Copyright (C) 1996 Santa Fe Institute.
// This library is distributed without any warranty; 
// without even the implied warranty of merchantability 
// or fitness for a particular purpose.
// See file LICENSE for details and terms of copying.

/*
Name:            ProbabilityDistribution.m
Description:     Common superclass for random distributions
Library:         random
Original Author: Sven Thommesen
Date:            1997-01-15
*/

/*
123456789|123456789|123456789|123456789|123456789|123456789|123456789|123456789|
*/


#import <collections.h>
#import <random/ProbabilityDistribution.h>


@implementation ProbabilityDistribution

// ----- private methods -----

-initState {

   // This method must be overridden by each distribution.

   [InvalidCombination raiseEvent:
   "ProbabilityDistribution initState called! Yell at Sven ...\n"];

   return self;
}


-resetState {

   // This method must be overridden by each distribution.

   [InvalidCombination raiseEvent:
   "ProbabilityDistribution resetState called! Yell at Sven ...\n"];

   return self;
}



// ----- protocol ProbabilityDistribution -----

+create: (id) aZone setGenerator: (id) generator {
   ProbabilityDistribution * aDistribution;

//   printf(" ProbabilityDistribution: create:setGenerator: called \n");

// Allocate space for the object:

   aDistribution = [super createBegin: aZone];

// Initialize instance variables:

   aDistribution->randomGenerator = NULL;
   aDistribution->generatorMax = 0;
   aDistribution->maxDivisor = 0.0;

   aDistribution->currentCount = 0;
   aDistribution->stateSize = 0;
   aDistribution->optionsInitialized = NO;

// Initialize fixed parts of state:

   [aDistribution initState];

// Connect the supplied random generator:

   [aDistribution setGenerator: generator];

   return [ aDistribution createEnd ];

}


+createBegin: aZone {
   ProbabilityDistribution * aDistribution;

//   printf(" ProbabilityDistribution: createBegin called \n");

// Allocate space for the object:

   aDistribution = [super createBegin: aZone];

// Initialize instance variables:

   aDistribution->randomGenerator = NULL;
   aDistribution->generatorMax = 0;
   aDistribution->maxDivisor = 0.0;

   aDistribution->currentCount = 0;
   aDistribution->stateSize = 0;
   aDistribution->optionsInitialized = NO;

// Initialize subclass instance variables:

   [aDistribution initState];

   return aDistribution;
}


-(void) setGenerator: (id) generator {

   if (randomGenerator) {

   [InvalidCombination raiseEvent:
   "ProbabilityDistribution: setting the generator more than once not allowed\n"];

   } else {

   randomGenerator = generator;
   generatorMax = [randomGenerator getUnsignedMax];
   maxDivisor = 1.0 + (double) generatorMax;
   [self resetState];

   }

   //   return self;
}


-createEnd {

//   printf(" ProbabilityDistribution: createEnd called \n");

// 1. If no generator has been allocated, abort:

// (This test will disallow use of [aGenerator create: aZone];
// user must call createBegin, setGenerator, createEnd.)

   if (!randomGenerator)   // no generator set
   [InvalidCombination raiseEvent:
   "Random Distribution initialized without a generator!\n"];

   return [super createEnd];
}


-(id) getGenerator {
   return randomGenerator;
}


-(BOOL) getOptionsInitialized {
   return optionsInitialized;
}


// ----- protocol InternalState -----

-(void) setState: (void *) state {

   // This method must be overridden by each distribution.

   [InvalidCombination raiseEvent:
   "ProbabilityDistribution setState called! Yell at Sven ...\n"];

   // nothing returned from a (void) function
}

-(void) getState: (void *) state {

   // This method must be overridden by each distribution.

   [InvalidCombination raiseEvent:
   "ProbabilityDistribution getState called! Yell at Sven ...\n"];

   // nothing returned from a (void) function
}

-(unsigned) getStateSize {
   return stateSize;
}


// ----- temporary methods -----

- (void) describe: outStream {
  char buffer[200];

  // This method should be extended by the subclass
  // through a call to [super describe: outStream].

  (void)sprintf(buffer,"ProbabilityDistribution describe: outStream: \n");
  (void)sprintf(buffer,"         *Generator = %p\n", randomGenerator);
  (void)sprintf(buffer,"       generatorMax = %u\n", generatorMax);
  (void)sprintf(buffer,"         maxDivisor = %f\n", maxDivisor);
  (void)sprintf(buffer,"            duuMask = %f\n", duuMask.d);
  (void)sprintf(buffer,"          stateSize = %u\n", stateSize);
  (void)sprintf(buffer,"       currentCount = %u\n", currentCount);
  (void)sprintf(buffer," optionsInitialized = %d\n", optionsInitialized);

  // Next have the generator print itself:
  [ randomGenerator describe: outStream ];
  [outStream catC: buffer];
  [outStream catC: "\n"];

  //  return self;
}

-(int) verifySelf {

   // This method must be overridden by each distribution.

   [InvalidCombination raiseEvent:
   "ProbabilityDistribution verifySelf called! Yell at Sven ...\n"];

   return 0;
}

@end
