//  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:            RandomNumberGenerator.m
Description:     Common superclass for all random number generators
Library:         random
Original Author: Sven Thommesen
Date:            1997-01-15
*/

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

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

@implementation RandomNumberGenerator

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

-initState {

   // This method must be overridden by each generator.

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

   return self;
}

-resetState {

   // This method must be overridden by each generator.

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

   return self;
}

// ----- protocol RandomNumberGenerator: -----

+create: (id) aZone setStateFromSeed: (unsigned) seed {
  RandomNumberGenerator * aGenerator;

  // printf(" RandomNumberGenerator: create:setStateFromSeed called \n");

// Allocate space for the object:

  aGenerator = [super createBegin: aZone];
  
// initialize instance variables:

  aGenerator->unsignedMax = 0;
  aGenerator->stateSize = 0;

  aGenerator->initialSeed = 0;
  aGenerator->currentCount = TESTVALUE;

// initialize fixed parts of state:

  [aGenerator initState];	// must be called before setStateFromSeed

// initialize seed dependent part of state:

  [aGenerator setStateFromSeed: seed];

  return [ aGenerator createEnd ];

}

+createBegin: aZone {
  RandomNumberGenerator * aGenerator;

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

// Allocate space for the object:

  aGenerator = [super createBegin: aZone];

// initialize instance variables:

  aGenerator->unsignedMax = 0;
  aGenerator->stateSize = 0;

  aGenerator->initialSeed = 0;
  aGenerator->currentCount = TESTVALUE;

// initialize fixed parts of state:

  [aGenerator initState];	// must be called before setStateFromSeed

  return aGenerator;
}

-setStateFromSeed: (unsigned) seed {

   // printf(" RandomNumberGenerator: setStateFromSeed %u called\n", seed);

   currentCount = 0;
   initialSeed = seed;
   [self resetState];

   return self;
}

-createEnd {

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

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

  if (currentCount == TESTVALUE) // no instantiation chosen:
  [InvalidCombination raiseEvent:
  "Random Generator not Initialized with a Seed!\n"];
 
  return [super createEnd];
}

-(unsigned) getUnsignedMax {
   return unsignedMax;
}

-(unsigned) getUnsignedSample {
   unsigned u;

   // This method must be overridden by each generator.

   [InvalidCombination raiseEvent:
   "RandomNumberGenerator getUnsignedSample called! Yell at Sven ...\n"];

   return u; // keep compiler happy
}

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

-(unsigned) getStateSize {
   return stateSize;		// set initState in subclasses
}

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

   // This method must be overridden by each generator.

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

}

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

   // This method must be overridden by each generator.

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

}

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

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

  // This method may be extended by the subclasses
  // through a call to [super printSelf].

  (void)sprintf(buffer,"RandomNumberGenerator printSelf:\n");
  (void)sprintf(buffer,"  unsignedMax = %u\n", unsignedMax);
  (void)sprintf(buffer,"    stateSize = %u\n", stateSize);
  (void)sprintf(buffer," currentCount = %u\n", currentCount);
  (void)sprintf(buffer,"  initialSeed = %u\n", initialSeed);
  (void)sprintf(buffer,"\n");

  [super describe: outStream];
  [outStream catC: buffer];
  [outStream catC: "\n"];

  //  return self;
}

-(int) verifySelf {

   // This method must be overridden by each generator.

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

   return 0;
}

@end
