// $Source: /usr/local/SimSoft/Sfx3D/src/gts/gtsvert.cpp,v $
// $Revision: 1.2 $
// $Author: baum $
// $Date: 2001/11/29 15:18:10 $
//
// Login name of the user who locked the revision
// $Locker:  $
// Tag name used to checkout the file
// $Name: Release-14 $
// State assigned to revision
// $State: Exp $
//
//
// $Log: gtsvert.cpp,v $
// Revision 1.2  2001/11/29 15:18:10  baum
// -Realzeitsteuerung eingebaut
// -Handsteuerung eingebaut
//

#define _ZUFX01_CPP

#include <limits.h>
#include <float.h>
#include <stdio.h>

#include "MathDefs.h"

#include "Token.h"
#include "Messager.h"

#include "gtsio.h"
#define  _ZUFX01_CPP
#include "gtsvert.h"

//---------------------------------------------------------
// Klasse Verteilung 
//---------------------------------------------------------

Verteilung* Verteilung::erzeugen (unsigned Art) {
  switch (Art) {
    case 6   :
    case 100 : return new RealExplizit;
    case 5   :
    case 110 : return new IntExplizit;
    case 1   :
    case 200 : return new RealGleich;
    case 4   :
    case 210 : return new IntGleich;
    case 3   :
    case 300 : return new RealExp;
    case 2   :
    case 301 : return new RealExpMitGrenze;
    case 302 : return new RealExpMitGrenzeNeuziehen;
    case 310 : return new IntExp;
    case 311 : return new IntExpMitGrenze;
    case 312 : return new IntExpMitGrenzeNeuziehen;
    case 400 : return new RealGauss;
    case 8   :
    case 401 : return new RealGaussMitGrenze;
    case 402 : return new RealGaussMitGrenzeNeuziehen;
    case 410 : return new IntGauss;
    case 7   :
    case 411 : return new IntGaussMitGrenze;
    case 412 : return new IntGaussMitGrenzeNeuziehen;
    case 500 : return new RealErlang;
    case 10  :
    case 501 : return new RealErlangMitGrenze;
    case 502 : return new RealErlangMitGrenzeNeuziehen;
    case 510 : return new IntErlang;
    case 9   :
    case 511 : return new IntErlangMitGrenze;
    case 512 : return new IntErlangMitGrenzeNeuziehen;
    case 610 : return new IntPoisson;
    case 11  :
    case 611 : return new IntPoissonMitGrenze;
    case 612 : return new IntPoissonMitGrenzeNeuziehen;
    default  : Msg.Warning ("Verteilung::erzeugen()",
                            "Verteilung %d nicht implementiert", Art);
  }
  return NULL;
}

Verteilung::~Verteilung () { }

double Verteilung::ranreal (unsigned& startzahl) {
//  Diese Generatoren wurden untersucht
//  return ((double)((startzahl *= 4101) + 1) / UINT_MAX);
//  return ((double)((startzahl *= 4097) + 1) / UINT_MAX);
//  return ((double)(startzahl *= 4101) / UINT_MAX);
//  Dieser ist der Beste in der Gleichverteilung
  return ((double)(startzahl *= 4097) / UINT_MAX);
}

int Verteilung::round (double wert) {
  return ((wert > 0) ? ((int) (wert + 0.5)) : ((int) (wert - 0.5)));
}


Ustring Verteilung::bereinigeString (Ustring inp)
{
   unsigned i;
   if (inp.findLeftPos('.') < 0) return inp;

   for (i = inp.len()-1; i; i--)
   {
     if (inp[i] != '0') break;
   }
   if (inp[i] == '.') i++;
   inp.delPart (i+1,inp.len() - i);
   return inp;
}  //  ENDE  ZahlInString

unsigned Verteilung::getVerteilTyp () {
   return ObjTyp;
}

//---------------------------------------------------------
// Klasse RealExplizit
//---------------------------------------------------------

RealExplizit::RealExplizit () { ObjTyp = 100; };

RealExplizit::~RealExplizit () { };

double RealExplizit::NeueZahl () {return ObjWert;}

void RealExplizit::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file);
  tok.nextToken (file);
  ObjWert = atof (tok ());

  file.jump (200); //EOL

//  if (initprog) dprintf ("TLM: RealExplizit gelesen: %7.5lf\n", ObjWert);
}

void RealExplizit::schreiben (ostream& ostrm) {
  double dummy  = -1.00000;
  double udummy =  0.00000;

  Write (ostrm, "%12.5lf ", dummy);
  Write (ostrm, "%12.5lf ", ObjWert);
  Write (ostrm, "%12.5lf ", dummy);
  Write (ostrm, "%7u",      udummy);

//  fprintf (fin, "%12.5lf %12.5lf %12.5lf %7u", dummy, ObjWert, dummy, udummy);
}

void RealExplizit::setVerteilung (Ustring str) {
  sscanf ((char*)str.str(), "%lf", &ObjWert);
}

Ustring RealExplizit::getVerteilung () {
  return bereinigeString(Ustring(ObjWert));
}

//---------------------------------------------------------
// Klasse IntExplizit
//---------------------------------------------------------

IntExplizit::IntExplizit () { ObjTyp = 110; };

IntExplizit::~IntExplizit () { };

double IntExplizit::NeueZahl () {return round (ObjWert);}

//---------------------------------------------------------
// Klasse RealGleich
//---------------------------------------------------------

RealGleich::RealGleich () { ObjTyp = 200; }

RealGleich::~RealGleich () { }

double RealGleich::NeueZahl () {
  return (ObjMin + (ObjMax - ObjMin) * ranreal (ObjStartzahl));
}

void RealGleich::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file);
  ObjMin = atof (tok ());
  tok.nextToken (file);
  tok.nextToken (file);
  ObjMax = atof (tok ());
  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) dprintf ("TLM: RealGleich gelesen: %7.5lf %7.5lf %d\n",
//                          ObjMin, ObjMax, ObjStartzahl);
}

void RealGleich::schreiben (ostream& ostrm) {
  double dummy = -1.00000;

  Write (ostrm, "%12.5lf ", ObjMin);
  Write (ostrm, "%12.5lf ", dummy);
  Write (ostrm, "%12.5lf ", ObjMax);
  Write (ostrm, "%7u",     ObjStartzahl);
//  fprintf (fin, "%12.5lf %12.5lf %12.5lf %7u", ObjMin, dummy, ObjMax, ObjStartzahl);
}

void RealGleich::setVerteilung (Ustring str) {
  sscanf ((char*)str.str(), "%lf %lf %u", &ObjMin, &ObjMax, &ObjStartzahl);
}

Ustring RealGleich::getVerteilung () {
  return bereinigeString(Ustring(ObjMin)) + '\t' +
         bereinigeString(Ustring(ObjMax)) + '\t' +
         bereinigeString(Ustring (ObjStartzahl));
}

//---------------------------------------------------------
// Klasse IntGleich
//---------------------------------------------------------

IntGleich::IntGleich () { ObjTyp = 210; }

IntGleich::~IntGleich () { }

double IntGleich::NeueZahl () {
  return (int) (round (ObjMin) + ((round (ObjMax) - round (ObjMin)) + 0.999) * 
                ranreal (ObjStartzahl));
}

void IntGleich::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file);
  ObjMin = atof (tok ());
  ObjMin = Round (ObjMin);

  tok.nextToken (file);
  tok.nextToken (file);
  ObjMax = atof (tok ());
  ObjMax = Round (ObjMax);

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) dprintf ("TLM: IntGleich gelesen: %7.5f %7.5f %d\n",
//                         ObjMin, ObjMax, ObjStartzahl);
}

void IntGleich::schreiben (ostream& ostrm) {
  double dummy = -1.00000;
  Write (ostrm, "%12.5lf ", ObjMin);
  Write (ostrm, "%12.5lf ", dummy);
  Write (ostrm, "%12.5lf ", ObjMax);
  Write (ostrm, "%7u",      ObjStartzahl);

//  fprintf (fin, "%12.5lf %12.5lf %12.5lf %7u", ObjMin, dummy, ObjMax, ObjStartzahl);
}

void IntGleich::setVerteilung (Ustring str) {
  double min, max;
  sscanf ((char*)str.str(), "%lf %lf %u", &min, &max, &ObjStartzahl);
  ObjMin = round (min);
  ObjMax = round (max);
}

Ustring IntGleich::getVerteilung () {
  return bereinigeString(Ustring(ObjMin)) + '\t' +
         bereinigeString(Ustring(ObjMax)) + '\t' +
         bereinigeString(Ustring(ObjStartzahl));
}

//---------------------------------------------------------
// Klasse RealExp
//---------------------------------------------------------

RealExp::RealExp () { ObjTyp = 300; }

RealExp::~RealExp () { }

double RealExp::NeueZahl () {
  return (-ObjErwartungswert) * log(ranreal (ObjStartzahl));
}

void RealExp::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file); // Min

  tok.nextToken (file);
  ObjErwartungswert = atof (tok ());

  tok.nextToken (file); // Max

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) dprintf ("TLM: RealExp gelesen: %7.5lf %d\n",
//                ObjErwartungswert, ObjStartzahl);
}

void RealExp::schreiben (ostream& ostrm) {
  double dummy = -1.00000;

  Write (ostrm, "%12.5lf ", dummy);
  Write (ostrm, "%12.5lf ", ObjErwartungswert);
  Write (ostrm, "%12.5lf ", dummy);
  Write (ostrm, "%7u",      ObjStartzahl);

//  fprintf (fin, "%12.5lf %12.5lf %12.5lf %7u",
//                dummy, ObjErwartungswert, dummy, ObjStartzahl);
}

void RealExp::setVerteilung (Ustring str) {
  sscanf ((char*)str.str(), "%lf %u", &ObjErwartungswert, &ObjStartzahl);
}

Ustring RealExp::getVerteilung () {
  return bereinigeString(Ustring(ObjErwartungswert)) + '\t' +
         bereinigeString(Ustring(ObjStartzahl));
}

//---------------------------------------------------------
// Klasse RealExpMitGrenze
//---------------------------------------------------------

RealExpMitGrenze::RealExpMitGrenze () { ObjTyp = 301; }

RealExpMitGrenze::~RealExpMitGrenze () { }

double RealExpMitGrenze::NeueZahl () {
  double Akt_Wert;
  
  Akt_Wert = RealExp::NeueZahl ();
  if (Akt_Wert < ObjMin) Akt_Wert = ObjMin;
  else if (Akt_Wert > ObjMax) Akt_Wert = ObjMax;
  return Akt_Wert;        
}

void RealExpMitGrenze::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file); // Min
  ObjMin = atof (tok ());

  tok.nextToken (file);
  ObjErwartungswert = atof (tok ());

  tok.nextToken (file); // Max
  ObjMax = atof (tok ());

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) 
//    dprintf ("TLM: RealExpMitGrenze gelesen: %7.5lf %7.5lf %7.5lf %d\n",
//              ObjMin, ObjErwartungswert, ObjMax, ObjStartzahl);
}

void RealExpMitGrenze::schreiben (ostream& ostrm) {
  Write (ostrm, "%12.5lf ", ObjMin);
  Write (ostrm, "%12.5lf ", ObjErwartungswert);
  Write (ostrm, "%12.5lf ", ObjMax);
  Write (ostrm, "%7u",      ObjStartzahl);
//  fprintf (fin, "%12.5lf %12.5lf %12.5lf %7u",
//                ObjMin, ObjErwartungswert, ObjMax, ObjStartzahl);
}

void RealExpMitGrenze::setVerteilung (Ustring str) {
  sscanf ((char*)str.str(), "%lf %lf %lf %u", 
                     &ObjMin, &ObjErwartungswert, &ObjMax, &ObjStartzahl);
}

Ustring RealExpMitGrenze::getVerteilung () {
  return bereinigeString(Ustring(ObjMin)) + '\t' +
         bereinigeString(Ustring(ObjErwartungswert)) + '\t' +
         bereinigeString(Ustring(ObjMax)) + '\t' +
         bereinigeString(Ustring(ObjStartzahl));
}

//---------------------------------------------------------
// Klasse RealExpMitGrenzeNeuziehen
//---------------------------------------------------------

RealExpMitGrenzeNeuziehen::RealExpMitGrenzeNeuziehen () { ObjTyp = 302; }

RealExpMitGrenzeNeuziehen::~RealExpMitGrenzeNeuziehen () { }

double RealExpMitGrenzeNeuziehen::NeueZahl () {
  double Akt_Wert;

  Akt_Wert = RealExp::NeueZahl ();
  while((Akt_Wert < ObjMin) || (Akt_Wert > ObjMax))
    Akt_Wert = RealExp::NeueZahl ();
  
  return Akt_Wert;
}

//---------------------------------------------------------
// Klasse IntExp
//---------------------------------------------------------

IntExp::IntExp () { ObjTyp = 310; }

IntExp::~IntExp () { }

double IntExp::NeueZahl () {
  return round (RealExp::NeueZahl ());
}

//---------------------------------------------------------
// Klasse IntExpMitGrenze
//---------------------------------------------------------

IntExpMitGrenze::IntExpMitGrenze () { ObjTyp = 311; }

IntExpMitGrenze::~IntExpMitGrenze () { }

double IntExpMitGrenze::NeueZahl () {
  double Akt_Wert;
  
  Akt_Wert = IntExp::NeueZahl ();
  if (Akt_Wert < ObjMin) Akt_Wert = ObjMin;
  else if (Akt_Wert > ObjMax) Akt_Wert = ObjMax;
  return Akt_Wert;        
}

void IntExpMitGrenze::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file);
  ObjMin = (int) Round (atof (tok ()));

  tok.nextToken (file);
  ObjErwartungswert = atof (tok ());
  ObjErwartungswert = Round (ObjErwartungswert);

  tok.nextToken (file);
  ObjMax = (int) Round (atof (tok ()));

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) dprintf ("TLM: IntExpMitGrenze gelesen: %d %7.5lf %d %d\n",
//                ObjMin, ObjErwartungswert, ObjMax, ObjStartzahl);
}


void IntExpMitGrenze::schreiben (ostream& ostrm) {
  Write (ostrm, "%12.5lf ", ObjMin);
  Write (ostrm, "%12.5lf ", ObjErwartungswert);
  Write (ostrm, "%12.5lf ", ObjMax);
  Write (ostrm, "%7u",      ObjStartzahl);
//  fprintf (fin, "%12d %12.5lf %12d %7u",
//                ObjMin, ObjErwartungswert, ObjMax, ObjStartzahl);
}

void IntExpMitGrenze::setVerteilung (Ustring str) {
  double min, max;
  sscanf ((char*)str.str(), "%lf %lf %lf %u", 
                            &min, &ObjErwartungswert, &max, &ObjStartzahl);
  ObjMin = round (min);
  ObjMax = round (max);
}

Ustring IntExpMitGrenze::getVerteilung () {
  return bereinigeString(Ustring(ObjMin)) + '\t' +
         bereinigeString(Ustring(ObjErwartungswert)) + '\t' +
         bereinigeString(Ustring(ObjMax)) + '\t' +
         bereinigeString(Ustring(ObjStartzahl));
}

//---------------------------------------------------------
// Klasse IntExpMitGrenzeNeuziehen
//---------------------------------------------------------

IntExpMitGrenzeNeuziehen::IntExpMitGrenzeNeuziehen () { ObjTyp = 312; }

IntExpMitGrenzeNeuziehen::~IntExpMitGrenzeNeuziehen () { }

double IntExpMitGrenzeNeuziehen::NeueZahl () {
  double Akt_Wert;

  Akt_Wert = IntExp::NeueZahl ();
  while((Akt_Wert < ObjMin) || (Akt_Wert > ObjMax))
    Akt_Wert = IntExp::NeueZahl ();
  
  return Akt_Wert;
}

//---------------------------------------------------------
// Klasse RealGauss
//---------------------------------------------------------

RealGauss::RealGauss () { ObjTyp = 400; }

RealGauss::~RealGauss () { }

double RealGauss::NeueZahl () {
  const double a0 = 2.30753;
  const double a1 = 0.27061;
  const double b1 = 0.99229;
  const double b2 = 0.04481;
  double t,u;
  double Akt_Wert;

  t = sqrt (log (1 / (pow (ranreal (ObjStartzahl), 2))));
  u = t - ((a0 + (a1 * t)) / (1 + (b1 * t) + (b2 * (pow (t, 2)))));
  Akt_Wert = (u * ObjAbweichung) + ObjMittel;
  return Akt_Wert;
}

void RealGauss::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file); // Min

  tok.nextToken (file);
  ObjMittel = atof (tok ());

  tok.nextToken (file); // Max

  tok.nextToken (file);
  ObjAbweichung = atof (tok ());

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) dprintf ("TLM: RealGauss gelesen: %7.5lf %7.5lf %d\n",
//                ObjMittel, ObjAbweichung, ObjStartzahl);
}

void RealGauss::schreiben (ostream& ostrm) {
  double dummy = -1.00000;
  Write (ostrm, "%12.5lf ", dummy);
  Write (ostrm, "%12.5lf ", ObjMittel);
  Write (ostrm, "%12.5lf ", dummy);
  Write (ostrm, "%12.5lf ", ObjAbweichung);
  Write (ostrm, "%7u",      ObjStartzahl);

//  fprintf (fin, "%12.5lf %12.5lf %12.5lf %12.5lf %7u",
//                dummy, ObjMittel, dummy, ObjAbweichung, ObjStartzahl);
}

void RealGauss::setVerteilung (Ustring str) {
  sscanf ((char*)str.str(), "%lf %lf %u", 
                             &ObjMittel, &ObjAbweichung, &ObjStartzahl);
}

Ustring RealGauss::getVerteilung () {
  return bereinigeString(Ustring(ObjMittel)) + '\t' +
         bereinigeString(Ustring(ObjAbweichung)) +  '\t' +
         bereinigeString(Ustring (ObjStartzahl));
}

//---------------------------------------------------------
// Klasse RealGaussMitGrenze
//---------------------------------------------------------

RealGaussMitGrenze::RealGaussMitGrenze () { ObjTyp = 401; }

RealGaussMitGrenze::~RealGaussMitGrenze () { }

double RealGaussMitGrenze::NeueZahl () {
  double Akt_Wert;
  
  Akt_Wert = RealGauss::NeueZahl ();
  if (Akt_Wert < ObjMin) Akt_Wert = ObjMin;
  else if (Akt_Wert > ObjMax) Akt_Wert = ObjMax;
  return Akt_Wert;        
}

void RealGaussMitGrenze::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file); // Min
  ObjMin = atof (tok ());

  tok.nextToken (file);
  ObjMittel = atof (tok ());

  tok.nextToken (file); // Max
  ObjMax = atof (tok ());

  tok.nextToken (file);
  ObjAbweichung = atof (tok ());

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) 
//    dprintf ("TLM: RealGaussMitGrenze gelesen: %7.5lf %7.5lf %7.5lf %7.5lf %d\n",
//             ObjMin, ObjMittel, ObjMax, ObjAbweichung, ObjStartzahl);
}

void RealGaussMitGrenze::schreiben (ostream& ostrm) {
  Write (ostrm, "%12.5lf ", ObjMin);
  Write (ostrm, "%12.5lf ", ObjMittel);
  Write (ostrm, "%12.5lf ", ObjMax);
  Write (ostrm, "%12.5lf ", ObjAbweichung);
  Write (ostrm, "%7u",      ObjStartzahl);
//  fprintf (fin, "%12.5lf %12.5lf %12.5lf %12.5lf %7u",
//                ObjMin, ObjMittel, ObjMax, ObjAbweichung, ObjStartzahl);
}

void RealGaussMitGrenze::setVerteilung (Ustring str) {
  sscanf ((char*)str.str(), "%lf %lf %lf %lf %u", 
                 &ObjMin, &ObjMittel, &ObjMax, &ObjAbweichung, &ObjStartzahl);
}

Ustring RealGaussMitGrenze::getVerteilung () {
  return bereinigeString(Ustring(ObjMin)) + '\t' +
         bereinigeString(Ustring(ObjMittel)) + '\t' +
         bereinigeString(Ustring(ObjMax)) + '\t' +
         bereinigeString(Ustring(ObjAbweichung)) + '\t' +
         bereinigeString(Ustring (ObjStartzahl));
}

//---------------------------------------------------------
// Klasse RealGaussMitGrenzeNeuziehen
//---------------------------------------------------------

RealGaussMitGrenzeNeuziehen::RealGaussMitGrenzeNeuziehen () { ObjTyp = 402; }

RealGaussMitGrenzeNeuziehen::~RealGaussMitGrenzeNeuziehen () { }

double RealGaussMitGrenzeNeuziehen::NeueZahl () {
  double Akt_Wert;

  Akt_Wert = RealGauss::NeueZahl ();
  while((Akt_Wert < ObjMin) || (Akt_Wert > ObjMax))
    Akt_Wert = RealGauss::NeueZahl ();
  
  return Akt_Wert;
}

//---------------------------------------------------------
// Klasse IntGauss
//---------------------------------------------------------

IntGauss::IntGauss () { ObjTyp = 410; }

IntGauss::~IntGauss () { }

double IntGauss::NeueZahl () {
  return round (RealGauss::NeueZahl ());
}

//---------------------------------------------------------
// Klasse IntGaussMitGrenze
//---------------------------------------------------------

IntGaussMitGrenze::IntGaussMitGrenze () { ObjTyp = 411; }

IntGaussMitGrenze::~IntGaussMitGrenze () { }

double IntGaussMitGrenze::NeueZahl () {
  double Akt_Wert;
  
  Akt_Wert = IntGauss::NeueZahl ();
  if (Akt_Wert < ObjMin) Akt_Wert = ObjMin;
  else if (Akt_Wert > ObjMax) Akt_Wert = ObjMax;
  return Akt_Wert;        
}

void IntGaussMitGrenze::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file); // Min
  ObjMin = (int) Round (atof (tok ()));

  tok.nextToken (file);
  ObjMittel = atof (tok ());

  tok.nextToken (file); // Max
  ObjMax = (int) Round (atof (tok ()));

  tok.nextToken (file);
  ObjAbweichung = atof (tok ());

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) 
//    dprintf ("TLM: IntGaussMitGrenze gelesen: %d %7.5lf %d %7.5f %d\n",
//             ObjMin, ObjMittel, ObjMax, ObjAbweichung, ObjStartzahl);
}

void IntGaussMitGrenze::schreiben (ostream& ostrm) {
  Write (ostrm, "%12d ",    ObjMin);
  Write (ostrm, "%12.5lf ", ObjMittel);
  Write (ostrm, "%12d ",    ObjMax);
  Write (ostrm, "%12.5lf ", ObjAbweichung);
  Write (ostrm, "%7u",     ObjStartzahl);
//  fprintf (fin, "%12d %12.5lf %12d %12.5lf %7u",
//                ObjMin, ObjMittel, ObjMax, ObjAbweichung, ObjStartzahl);
}

void IntGaussMitGrenze::setVerteilung (Ustring str) {
  double min, max;
  sscanf ((char*)str.str(), "%lf %lf %lf %lf %u", 
                 &min, &ObjMittel, &max, &ObjAbweichung, &ObjStartzahl);
  ObjMin = round (min);
  ObjMax = round (max);
}

Ustring IntGaussMitGrenze::getVerteilung () {
  return bereinigeString(Ustring(ObjMin)) + '\t' +
         bereinigeString(Ustring(ObjMittel)) + '\t' +
         bereinigeString(Ustring(ObjMax)) + '\t' +
         bereinigeString(Ustring(ObjAbweichung)) + '\t' +
         bereinigeString(Ustring(ObjStartzahl));
}

//---------------------------------------------------------
// Klasse IntGaussMitGrenzeNeuziehen
//---------------------------------------------------------

IntGaussMitGrenzeNeuziehen::IntGaussMitGrenzeNeuziehen () { ObjTyp = 412; }

IntGaussMitGrenzeNeuziehen::~IntGaussMitGrenzeNeuziehen () { }

double IntGaussMitGrenzeNeuziehen::NeueZahl () {
  double Akt_Wert;

  Akt_Wert = IntGauss::NeueZahl ();
  while((Akt_Wert < ObjMin) || (Akt_Wert > ObjMax))
    Akt_Wert = IntGauss::NeueZahl ();
  
  return Akt_Wert;
}

//---------------------------------------------------------
// Klasse RealErlang
//---------------------------------------------------------

RealErlang::RealErlang () { ObjTyp = 500; }

RealErlang::~RealErlang () { }

double RealErlang::NeueZahl () {
  double Akt_Wert, r1;
  int i, r2;

  if (ObjK < 1) ObjK = 1;
  r1 = 1.0;
  r2 = round (ObjErwartungswert / ObjK);
  i = 1;
  Akt_Wert = ObjErwartungswert;
  while (i <= ObjK) {
    i++;
    r1 = r1 * ranreal (ObjStartzahl);
  }
  if (r1 != 0.0) Akt_Wert = -r2 * log(r1);
  return (Akt_Wert);
}

void RealErlang::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file); // Min

  tok.nextToken (file);
  ObjErwartungswert = atof (tok ());

  tok.nextToken (file); // Max

  tok.nextToken (file);
  ObjK = (int) Round (atof (tok ()));

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) dprintf ("TLM: RealErlang gelesen: %7.5lf %d %d\n",
//                ObjErwartungswert, ObjK, ObjStartzahl);
}

void RealErlang::schreiben (ostream& ostrm) {
  double dummy = -1.00000;
  Write (ostrm, "%12.5lf ", dummy);
  Write (ostrm, "%12.5lf ", ObjErwartungswert);
  Write (ostrm, "%12.5lf ", dummy);
  Write (ostrm, "%12d ",    ObjK);
  Write (ostrm, "%7u",      ObjStartzahl);

//  fprintf (fin, "%12.5lf %12.5lf %12.5lf %12d %7u",
//                dummy, ObjErwartungswert, dummy, ObjK, ObjStartzahl);
}

void RealErlang::setVerteilung (Ustring str) {
  double k;
  sscanf ((char*)str.str(), "%lf %lf %u", &ObjErwartungswert, &k, &ObjStartzahl);
  ObjK = round (k);
}

Ustring RealErlang::getVerteilung () {
  return bereinigeString(Ustring(ObjErwartungswert)) + '\t' +
         bereinigeString(Ustring(ObjK)) + '\t' +
         bereinigeString(Ustring(ObjStartzahl));
}

//---------------------------------------------------------
// Klasse RealErlangMitGrenze
//---------------------------------------------------------

RealErlangMitGrenze::RealErlangMitGrenze () { ObjTyp = 501; }

RealErlangMitGrenze::~RealErlangMitGrenze () { }

double RealErlangMitGrenze::NeueZahl () {
  double Akt_Wert;
  
  Akt_Wert = RealErlang::NeueZahl ();
  if (Akt_Wert < ObjMin) Akt_Wert = ObjMin;
  else if (Akt_Wert > ObjMax) Akt_Wert = ObjMax;
  return Akt_Wert;        
}

void RealErlangMitGrenze::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file); // Min
  ObjMin = atof (tok ());

  tok.nextToken (file);
  ObjErwartungswert = atof (tok ());

  tok.nextToken (file); // Max
  ObjMax = atof (tok ());

  tok.nextToken (file);
  ObjK = (int) Round (atof (tok ()));

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) 
//    dprintf ("TLM: RealErlangMitGrenze gelesen: %7.5lf %7.5lf %7.5lf %d %d\n",
//             ObjMin, ObjErwartungswert, ObjMax, ObjK, ObjStartzahl);
}

void RealErlangMitGrenze::schreiben (ostream& ostrm) {
  Write (ostrm, "%12.5lf ", ObjMin);
  Write (ostrm, "%12.5lf ", ObjErwartungswert);
  Write (ostrm, "%12.5lf ", ObjMax);
  Write (ostrm, "%12d ",    ObjK);
  Write (ostrm, "%7u",      ObjStartzahl);
//  fprintf (fin, "%12.5lf %12.5lf %12.5lf %12d %7u",
//                ObjMin, ObjErwartungswert, ObjMax, ObjK, ObjStartzahl);
}

void RealErlangMitGrenze::setVerteilung (Ustring str) {
  double k;
  sscanf ((char*)str.str(), "%lf %lf %lf %lf %u", 
          &ObjMin, &ObjErwartungswert, &ObjMax, &k, &ObjStartzahl);
  ObjK   = round (k);
}

Ustring RealErlangMitGrenze::getVerteilung () {
  return bereinigeString(Ustring(ObjMin)) + '\t' +
         bereinigeString(Ustring(ObjErwartungswert)) + '\t' +
         bereinigeString(Ustring(ObjMax)) + '\t' +
         bereinigeString(Ustring(ObjK)) + '\t' +
         bereinigeString(Ustring(ObjStartzahl));
}

//---------------------------------------------------------
// Klasse RealErlangMitGrenzeNeuziehen
//---------------------------------------------------------

RealErlangMitGrenzeNeuziehen::RealErlangMitGrenzeNeuziehen () { ObjTyp = 502; }

RealErlangMitGrenzeNeuziehen::~RealErlangMitGrenzeNeuziehen () { }

double RealErlangMitGrenzeNeuziehen::NeueZahl () {
  double Akt_Wert;

  Akt_Wert = RealErlang::NeueZahl ();
  while((Akt_Wert < ObjMin) || (Akt_Wert > ObjMax))
    Akt_Wert = RealErlang::NeueZahl ();
  
  return Akt_Wert;
}


//---------------------------------------------------------
// Klasse IntErlang
//---------------------------------------------------------

IntErlang::IntErlang () { ObjTyp = 510; }

IntErlang::~IntErlang () { }

double IntErlang::NeueZahl () {
  return round (RealErlang::NeueZahl ());
}

//---------------------------------------------------------
// Klasse IntErlangMitGrenze
//---------------------------------------------------------

IntErlangMitGrenze::IntErlangMitGrenze () { ObjTyp = 511; }

IntErlangMitGrenze::~IntErlangMitGrenze () { }

double IntErlangMitGrenze::NeueZahl () {
  double Akt_Wert;
  
  Akt_Wert = IntErlang::NeueZahl ();
  if (Akt_Wert < ObjMin) Akt_Wert = ObjMin;
  else if (Akt_Wert > ObjMax) Akt_Wert = ObjMax;
  return Akt_Wert;        
}

void IntErlangMitGrenze::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file); // Min
  ObjMin = (int) Round (atof (tok ()));

  tok.nextToken (file);
  ObjErwartungswert = atof (tok ());

  tok.nextToken (file); // Max
  ObjMax = (int) Round (atof (tok ()));

  tok.nextToken (file);
  ObjK = (int) Round (atof (tok ()));

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) 
//    dprintf ("TLM: IntErlangMitGrenze gelesen: %d %7.5lf %d %d %d\n",
//             ObjMin, ObjErwartungswert, ObjMax, ObjK, ObjStartzahl);
}

void IntErlangMitGrenze::schreiben (ostream& ostrm) {
  Write (ostrm, "%12d ",    ObjMin);
  Write (ostrm, "%12.5lf ", ObjErwartungswert);
  Write (ostrm, "%12d ",    ObjMax);
  Write (ostrm, "%12d ",    ObjK);
  Write (ostrm, "%7u",      ObjStartzahl);
//  fprintf (fin, "%12d %12.5lf %12d %12d %7u",
//                ObjMin, ObjErwartungswert, ObjMax, ObjK, ObjStartzahl);
}

void IntErlangMitGrenze::setVerteilung (Ustring str) {
  double min, max, k;
  sscanf ((char*)str.str(), "%lf %lf %lf %lf %u", &min, &ObjErwartungswert, 
                            &max, &k, &ObjStartzahl);
  ObjMin = round (min);	  
  ObjMax = round (max);	  
  ObjK   = round (k);
}

Ustring IntErlangMitGrenze::getVerteilung () {
  return bereinigeString(Ustring(ObjMin)) + '\t' +
         bereinigeString(Ustring(ObjErwartungswert)) + '\t' +
         bereinigeString(Ustring(ObjMax)) + '\t' +
         bereinigeString(Ustring(ObjK)) + '\t' +
         bereinigeString(Ustring (ObjStartzahl));
}

//---------------------------------------------------------
// Klasse IntErlangMitGrenzeNeuziehen
//---------------------------------------------------------

IntErlangMitGrenzeNeuziehen::IntErlangMitGrenzeNeuziehen () { ObjTyp = 512; }

IntErlangMitGrenzeNeuziehen::~IntErlangMitGrenzeNeuziehen () { }

double IntErlangMitGrenzeNeuziehen::NeueZahl () {
  double Akt_Wert;

  Akt_Wert = IntErlang::NeueZahl ();
  while((Akt_Wert < ObjMin) || (Akt_Wert > ObjMax))
    Akt_Wert = IntErlang::NeueZahl ();
  
  return Akt_Wert;
}

//---------------------------------------------------------
// Klasse IntPoisson
//---------------------------------------------------------

IntPoisson::IntPoisson () { ObjTyp = 610; }

IntPoisson::~IntPoisson () { }

double IntPoisson::NeueZahl () {
  double Akt_Wert = 0.0;
  double sum, fac = 1.0, facMalE = fac;
  double e = exp (-ObjMittel), d = ranreal (ObjStartzahl);
  
  for (sum = e; (d > sum) && (facMalE > DBL_EPSILON); sum += facMalE)
    facMalE = (fac *= ObjMittel / ++Akt_Wert) * e;
  return Akt_Wert;
}

void IntPoisson::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file); // Min

  tok.nextToken (file);
  ObjMittel = (int) Round (atof (tok ()));

  tok.nextToken (file); // Max

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) dprintf ("TLM: IntPoisson gelesen: %d %d\n",
//                ObjMittel, ObjStartzahl);
}

void IntPoisson::schreiben (ostream& ostrm) {
  double dummy = -1.00000;
  Write (ostrm, "%12.5lf ", dummy);
  Write (ostrm, "%12d ",    ObjMittel);
  Write (ostrm, "%12.5lf",  dummy);
  Write (ostrm, "%7u",      ObjStartzahl);

//  fprintf (fin, "%12.5lf %12d %12.5lf %7u",
//                dummy, ObjMittel, dummy, ObjStartzahl);
}

void IntPoisson::setVerteilung (Ustring str) {
  double mittel;
  sscanf ((char*)str.str(), "%lf %u", &mittel, &ObjStartzahl);
  ObjMittel = round (mittel);
}

Ustring IntPoisson::getVerteilung () {
  return bereinigeString(Ustring(ObjMittel)) + '\t' +
         bereinigeString(Ustring(ObjStartzahl));
}

//---------------------------------------------------------
// Klasse IntPoissonMitGrenze
//---------------------------------------------------------

IntPoissonMitGrenze::IntPoissonMitGrenze () { ObjTyp = 611; }

IntPoissonMitGrenze::~IntPoissonMitGrenze () { }

double IntPoissonMitGrenze::NeueZahl () {
  double Akt_Wert;
  
  Akt_Wert = IntPoisson::NeueZahl ();
  if (Akt_Wert < ObjMin) Akt_Wert = ObjMin;
  else if (Akt_Wert > ObjMax) Akt_Wert = ObjMax;
  return Akt_Wert;        
}

void IntPoissonMitGrenze::lesen (InputFile& file) {
  STDToken tok;

  tok.nextToken (file); // Min
  ObjMin = (int) Round (atof (tok ()));

  tok.nextToken (file);
  ObjMittel = (int) Round (atof (tok ()));

  tok.nextToken (file); // Max
  ObjMax = (int) Round (atof (tok ()));

  tok.nextToken (file);
  ObjStartzahl = atoi (tok ());

  file.jump (100); //EOL

//  if (initprog) 
//    dprintf ("TLM: IntPoissonMitGrenze gelesen: %d %d %d %d\n",
//             ObjMin, ObjMittel, ObjMax, ObjStartzahl);
}

void IntPoissonMitGrenze::schreiben (ostream& ostrm) {
  Write (ostrm, "%12d ", ObjMin);
  Write (ostrm, "%12d ", ObjMittel);
  Write (ostrm, "%12d ", ObjMax);
  Write (ostrm, "%7u",   ObjStartzahl);
//  fprintf (fin, "%12d %12d %12d %7u", ObjMin, ObjMittel, ObjMax, ObjStartzahl);
}

void IntPoissonMitGrenze::setVerteilung (Ustring str) {
  double min, mittel, max;
  sscanf ((char*)str.str(), "%lf %lf %lf %u", 
                 &min, &mittel, &max, &ObjStartzahl);
  ObjMin    = round (min);	  
  ObjMittel = round (mittel);
  ObjMax    = round (max);	  
}

Ustring IntPoissonMitGrenze::getVerteilung () {
  return bereinigeString(Ustring(ObjMin)) + '\t' +
         bereinigeString(Ustring(ObjMittel)) + '\t' +
         bereinigeString(Ustring(ObjMax)) + '\t' +
         bereinigeString(Ustring(ObjStartzahl));
}

//---------------------------------------------------------
// Klasse IntPoissonMitGrenzeNeuziehen
//---------------------------------------------------------

IntPoissonMitGrenzeNeuziehen::IntPoissonMitGrenzeNeuziehen () { ObjTyp = 612; }

IntPoissonMitGrenzeNeuziehen::~IntPoissonMitGrenzeNeuziehen () { }

double IntPoissonMitGrenzeNeuziehen::NeueZahl () {
  double Akt_Wert;

  Akt_Wert = IntPoisson::NeueZahl ();
  while((Akt_Wert < ObjMin) || (Akt_Wert > ObjMax))
    Akt_Wert = IntPoisson::NeueZahl ();
  
  return Akt_Wert;
}
// ZUFX01.CPP
