/////////////////////////////////////////////////////////////////////////////
// simlib.h --- main SIMLIB/C++ interface description
//
// SIMLIB version: 2.18
// Date: 2004-01-25
//
// -------------------------------------------------------------------------
// SIMLIB/C++ (SIMulation LIBrary for C++)
// -------------------------------------------------------------------------
// Copyright (c) 1991-2004 Petr Peringer
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
// -------------------------------------------------------------------------
//
// This is main interface for SIMLIB/C++
//
// Supported platforms:
//    Linux: GNU C++ compiler, arch i386+
// Portable to:
//    FreeBSD: GNU C++, i386+
//    MSDOS: DJGPP v2.0 = GNU C++ compiler for MSDOS (DPMI)
//    WIN95: Borland C++ (v5.0, console application)
//
// WARNING: this is debugging version!
//
// Send bug reports to: peringer AT fit.vutbr.cz
//

// EXPERIMENTAL:
#define NEW_WULIST


#ifndef __SIMLIB_H
#define __SIMLIB_H

#define __SIMLIB__      0x0218 // version of SIMLIB
#define SIMLIB_VERSION  "2.18"

#ifndef __cplusplus
# error  Use C++ compiler, please.
#endif

// system and compiler dependent part
#if defined(__MSDOS__)

# define SIMLIB_SYSTEM "MSDOS"
# if defined(__BCPLUSPLUS__)
#   error  Borland C++ for DOS no longer supported (use DJGPP)
# elif defined(__GNUG__)
#   define SIMLIB_COMPILER "GNU C++"
# else
#   error  This compiler is not supported (under MSDOS)
# endif

#elif defined(__linux__)

# define SIMLIB_SYSTEM    "Linux"
# define SIMLIB_COMPILER  "GNU C++"

#elif defined(__WIN32__) && defined(__BCPLUSPLUS__)  // check###!!!

# define SIMLIB_SYSTEM    "WIN32"
# define SIMLIB_COMPILER  "Borland C++"

#elif defined(__FreeBSD__)

# define SIMLIB_SYSTEM    "FreeBSD"
# define SIMLIB_COMPILER  "GNU C++"

#elif defined(__unix__) // ?????????????????#########

# define SIMLIB_SYSTEM    "Unixware?"
# define SIMLIB_COMPILER  "GNU C++"

#else
# error  "SIMLIB is not implemented for this system/compiler"
#endif

////////////////////////////////////////////////////////////////////////////
// what we expect:
//   type bool,
//   standard ISO C++ containers and iterators (for implementation)
//

////////////////////////////////////////////////////////////////////////////
// DEBUGGING: print debug info ON/OFF/mode
//
void DebugON();
void DebugOFF();
unsigned long Debug(unsigned long mode=~0UL); // start/stop partial debugging
// experimental code for start/stop debugging at global level
#ifdef SIMLIB_DEBUG
static unsigned long SIMLIB_old_debug_flags = Debug(SIMLIB_DEBUG);
#endif


////////////////////////////////////////////////////////////////////////////
// ATEXIT: special internal class for atexit, etc...
//
class SIMLIB_module { // internal class for SIMLIB cleanup (atexit)
  const char *string; // module identification string
  SIMLIB_module(const SIMLIB_module&); // disable copy-ctr
  SIMLIB_module &operator= (const SIMLIB_module&); // disable op=
 public:
  SIMLIB_module();
  int Init(const char *s);
  ~SIMLIB_module();
};

// create single global registration object in each module
static SIMLIB_module SIMLIB_module_id;


////////////////////////////////////////////////////////////////////////////
// includes ...
//
// remove it !!! ###
#include <csetjmp> // will be removed

// Leska:
// try this instead the above if you have class list
// and don't forget to link g++ library!
#include <list>
#define dlist std::list


////////////////////////////////////////////////////////////////////////////
// overwiew of basic SIMLIB classes (abstractions)
//

class SimObject;                // base abstract class

// discrete:
class  Link;                    // list item base class (Simula-like)
class   Entity;                 // discrete model entity
class    Process;               // process base
class    Event;                 // event base
class     Sampler;              // periodic calls of global function
class  List;                    // list of objects of class Link descendants
class   Queue;                  // priority queue
class  Stat;                    // statistics
class  TStat;                   // time dependent statistics
class  Histogram;               // histogram
class  Facility;                // SOL-like facility
class  Store;                   // SOL-like store
class  Barrier;                 // barrier
class  Semaphore;               // semaphore

// continuous:
class  aBlock;                  // abstract block
class   aContiBlock;            // blocks with continuous output
class    Integrator;            // integrator
class    Status;                // status variables
class     Hyst;                 // hysteresis
class     Blash;                // backlash
class     Relay;                // general relay
class    Function;              // general function
class    Constant;              // constant
class    Variable;              // variable
class    Parameter;             // parameter (simulation run constant)
//class   aBoolBlock;             // Boolean blocks

// combined:
class   aCondition;             // state condition base class
class    Condition;             // state event detector (Boolean version)
class     ConditionUp;          // action by FALSE-->TRUE change
class     ConditionDown;        // action by TRUE-->FALSE


////////////////////////////////////////////////////////////////////////////
// CATEGORY: global constants
////////////////////////////////////////////////////////////////////////////
// simulation time limits
//
const double SIMLIB_MINTIME = 0.0;
const double SIMLIB_MAXTIME = 1.0e30;

////////////////////////////////////////////////////////////////////////////
// CATEGORY: global variables ...

extern Entity *const &Current;    // active (now running) entity

//  step limits of numerical integration method
extern const double &MinStep;     // minimal step size
extern const double &StepSize;    // actual step size
extern const double &OptStep;     // optimal step size
extern const double &MaxStep;     // max. step size

//  error params
extern const double &AbsoluteError; // max. abs. error of num. integration
extern const double &RelativeError; // max. rel. error    ...

// Phase type --- indicates current phase of experiment
enum SIMLIB_Phase_t {
    START, INITIALIZATION, SIMULATION, TERMINATION, ERROREXIT
};
// phase of experiment
extern const SIMLIB_Phase_t &Phase; // for user checking  ### remove?


////////////////////////////////////////////////////////////////////////////
// CATEGORY: global functions ...

inline void Init(double t0, double t1=SIMLIB_MAXTIME)   // initialization
{
  extern void SIMLIB_Init(double t0, double t1, unsigned version);
  SIMLIB_Init(t0,t1,__SIMLIB__); // consistency check...
}

void SetStep(double dtmin, double dtmax);        // set integration step
void SetAccuracy(double abserr, double relerr);  // max. error
void SetAccuracy(double relerr);                 // rel. error

void Run();                       // simulation run (experiment)
void Stop();                      // stops the simulation run
void Abort();                     // end of program

void Error(const char *fmt, ...); // print message & end of program
int  _Print(const char *fmt, ...);// non-fatal error messages (stdout)
int  Print(const char *fmt, ...); // for Output methods, can be redirected
int  Print(const double x);       // output double
int  Print(const double x, const double y);
int  Print(const double x, const double y, const double x);
void SetOutput(const char *name); // redirection of Output(), Print()

void ContractStep();              // request for shorter step of num. integ.
void ContractStep(double time);   // request for step end at given time


////////////////////////////////////////////////////////////////////////////
// CATEGORY: pseudorandom generators
//
void   RandomSeed(long seed=1537L);// initialize random number seed
double Random();                  // base uniform generator 0-0.999999...
// default Random can be replaced by user-defined base generator:
void   SetBaseRandomGenerator(double (*new_gen)());

// all following generators depend on Random()
double Beta(double th, double fi, double min, double max);
double Erlang(double alfa, int beta);
double Exponential(double mv);
double Gama(double alfa, double beta);
int    Geom(double q);
int    HyperGeom(double p, int n, int m);
double Logar(double mi, double delta);
int    NegBinM(double p,int m);
int    NegBin(double q, int k);
double Normal(double mi, double sigma);
int    Poisson(double lambda);
double Rayle(double delta);
double Triag(double mod, double min, double max);
double Uniform(double l, double h);
double Weibul(double lambda, double alfa);


////////////////////////////////////////////////////////////////////////////
// CATEGORY: basics

////////////////////////////////////////////////////////////////////////////
//! base of class hierarchy in SIMLIB
//
class SimObject {
  enum _Flags { _ALLOCATED = 1 };      // internal flags
 protected:
  const char * _name;
  unsigned     _flags;
 public:
  SimObject();
  virtual ~SimObject();
  void *operator new(unsigned size);   // allocate object, set _flags
  void operator delete(void *ptr);     // deallocate
  virtual void Output();               // print object to default output
  virtual const char *Name();          // object name
  bool HasName() const { return _name !=0; }
  void SetName(const char *name);      // assign the name
  bool IsAllocated() const { return _flags & _ALLOCATED; }
 private:
  SimObject(SimObject&);               // disable operation
  void operator= (SimObject&);         // disable operation
};

////////////////////////////////////////////////////////////////////////////
//! base class for all double-linked list items
//
class Link : public SimObject {
  Link(Link&);                         // disable operation
  void operator= (Link&);              // disable operation
  Link *pred;                          // previous object in List
  Link *succ;                          // next object in List
  List *head;                          // pointer to List (if any)
  friend class List;                   // only list can access pred,succ,head
 protected:
  Link(Link *p, Link *s, List *h);
  List *where() { return head; }       // where is linked
 public:
  Link();
  virtual ~Link();
  virtual void Into(List *l);          // insert last
  virtual void Out();                  // remove from list
};

////////////////////////////////////////////////////////////////////////////
// CATEGORY: discrete blocks 

//! entity/process priority values
enum {
  LOWEST_PRIORITY  = 0,
  HIGHEST_PRIORITY = 255,
  DEFAULT_PRIORITY = LOWEST_PRIORITY
};
typedef unsigned char EntityPriority_t;  // process priority
typedef unsigned char ServicePriority_t; // service priority (see Facility)

////////////////////////////////////////////////////////////////////////////
//! abstract base class of all active entities
//
class Entity : public Link {
    Entity(const Entity&);           //## disable
    Entity&operator=(const Entity&); //## disable
  protected:
    static unsigned long _Number;   // current number of entities
    unsigned long _Ident;           // unique identification of entity
    // next will be changed/removed:
    // Queue stores insertion time for statistics:
    friend class Queue;             // ### remove
    double _MarkTime;               // beginning of waiting in queue ###!!!
    // Facility and Store use these data
    friend class Facility;
    friend class Store;
    union {
        double _RestTime; // rest of time of interrupted service (Facility) ###
        unsigned long _ReqCapacity; // required store capacity of Store
    };
    ServicePriority_t _SPrio;           // priority of service (in Facility) ###
  public:
    typedef EntityPriority_t Priority_t;
    Priority_t Priority;                // priority of the entity
    Entity(Priority_t p = DEFAULT_PRIORITY);
    virtual ~Entity();
    operator Entity* () { return this; }
    virtual const char *Name();
    virtual void Activate();            // activate now
    virtual void Activate(double t);    // activate in time t (schedule)
    virtual void Passivate();           // deactivation
    virtual void Wait(double dtime);    // wait dtime time units
    virtual void Terminate();           // end of behavior and remove entity
    bool Idle() { return _Ev==0; }      // is not scheduled
    void Cancel() { Terminate(); }
//    virtual void Into(Queue *q);         // insert into queue
    virtual void Out();                 // remove from queue
  private:
    void *_Ev;                  // points into calendar, if scheduled
    virtual void _Run() = 0;    // run entity behavior
    // friends:
    friend class Calendar;              // internal class
    friend class EventNotice;           // internal calendar class
    friend void SIMLIB_DoActions();     // internal function - event dispatch
};

// global functions:
inline void Activate(Entity *e)  { e->Activate(); }   // activate entity e
inline void Passivate(Entity *e) { e->Passivate(); }  // passivate entity e

////////////////////////////////////////////////////////////////////////////
#define WaitUntil(expr)  while(_WaitUntil(expr));
////////////////////////////////////////////////////////////////////////////
//! abstract base class for processes
//
class Process : public Entity {
    Process(const Process&); //## disable
    Process&operator=(const Process&); //## disable
  char *_p;                       // stack contents
  unsigned int _size;             // size of stack contents
  jmp_buf _ProcStatus;            // stack status (for longjmp)
  enum ProcessStatus_t { _PREPARED=1, _RUNNING, _INTERRUPTED, _TERMINATED };
  unsigned char _status;
#ifdef NEW_WULIST
  bool _wait_until;
  void _WaitUntilRemove();
  friend class WaitUntilList;
#endif
  bool isCurrent() { return (_status==_RUNNING); }     // called from _Run()
  bool Terminated() { return (_status==_TERMINATED); } // zombie...
  virtual void _Run(); // point of activation
 public:
  Process(Priority_t p=DEFAULT_PRIORITY);
  virtual ~Process();
  virtual void Behavior() = 0;  // behavior description
  virtual void Output();        // print object
  virtual const char *Name();   // name of object
  virtual void Activate();              // activate now
  virtual void Activate(double t);      // activate in time t (schedule)
  virtual void Passivate();             // sleeping process (deactivation)
  virtual void Wait(double dtime);      // wait dtime interval
  bool  _WaitUntil(bool test);          // wait for condition (slow!)
  void Interrupt();                     // perform test of WaitUntil list ###
  virtual void Terminate();             // end of process

  // move to global level, use Current ???type check problem
  void Seize(Facility &f, ServicePriority_t sp=0);  //
  void Release(Facility &f);                //
  void Enter(Store &s, unsigned long ReqCap=1); //
  void Leave(Store &s, unsigned long ReqCap=1); //
  virtual void Into(Queue &q);          // insert into queue
};

////////////////////////////////////////////////////////////////////////////
//! abstract base class for events
//
class Event : public Entity {
  virtual void _Run();
 public:
  Event(Priority_t p=DEFAULT_PRIORITY);
  virtual ~Event();
  virtual void Output();          // print object
  virtual const char *Name();
  virtual void Behavior() = 0;    // behavior description
  // inherited: Activate, Passivate, Cancel==Terminate
};

////////////////////////////////////////////////////////////////////////////
//! objects of this class call global function periodically 
//  (typicaly used for output)
//
class Sampler: public Event {
    Sampler(const Sampler&); //## disable
    Sampler&operator=(const Sampler&); //## disable
    static Sampler *First;            // list of objects
    Sampler *Next;                    // next object
  protected:
    void (*function)();
    double last; // last sample -- prevents Stop() from sample duplication
    double step; // step of sampling
    bool on;     // switch on/off
    virtual void Behavior();        // behavior description
  public:
    Sampler(void (*pf)(), double dt=0.0);
    virtual ~Sampler();
    virtual void Output();          // print object
    void Start();                   // start + sample
    void Stop();                    // sample + stop
    void Sample();                  // performs sample (function call)
    double SetStep(double dt=0.0);  // change step
    double GetStep() const { return step; }
  private:
    static void InitAll();          // initialize all samplers (Init)
    static void ActivateAll();      // start all samplers (Run)
};


////////////////////////////////////////////////////////////////////////////
// CATEGORY: discrete blocks - pasive


#ifdef new_version
////////////////////////////////////////////////////////////////////////////
// class aStat - abstract base for statistics
//
class aStat : public SimObject {
 protected:
  double t0;                    // time of initialization
  double min;                   // minimal recorded value
  double max;                   // maximal recorded value
  unsigned long n;              // number of values recorded
 public:
  aStat();
  aStat(const char *name);
  ~aStat();
  virtual void Clear() = 0;                 // initialize
  virtual void Output();                    // print statistic
  virtual void operator () (double x) = 0;  // record value
  virtual double MeanValue() = 0;           // compute mean value
  double Min() const { /* test n==0 */ return min; }
  double Max() const { /* test n==0 */ return max; }
  unsigned long Number() const { return n; }
  double StartTime() const { return t0; }
};
#endif

////////////////////////////////////////////////////////////////////////////
//  class Stat - statistic
//
class Stat : public SimObject {
 protected:
  double sx;                    // sum of values
  double sx2;                   // sum of value square
  double min;                   // min value
  double max;                   // max value
  unsigned long n;              // number of values recorded
 public:
//
  Stat();
  Stat(const char *name);
  ~Stat();
  virtual void Clear();         // initialize
  void operator () (double x);  // record value
// Stat &operator = (Stat &x);  // ???
// Stat &operator += (Stat &x);
  virtual void Output();        // print statistic
//
  unsigned long Number() const { return n; }
  double Min() const           { /* test n==0 */ return min; }
  double Max() const           { /* test n==0 */ return max; }
  double Sum() const           { return sx; }
  double SumSquare() const     { return sx2; }
  double MeanValue() const;
  double StdDev() const;
};


////////////////////////////////////////////////////////////////////////////
//  class TStat - time statistic
//
class TStat : public SimObject {
 protected:
  double sxt;                   // sum of x*time
  double sx2t;                  // sum of squares
  double min;                   // min value x
  double max;                   // max value x
  double t0;                    // time of initialization
  double tl;                    // last record time
  double xl;                    // last recorded value x
 public:
  unsigned long n;              // number of records
//
  TStat(double initval=0.0);
  TStat(const char *name, double initval=0.0);
  ~TStat();
  virtual void Clear(double initval=0.0);        // initialize
  virtual void Output();                         // print
  virtual void operator () (double x);           // record value
//
  unsigned long Number() const { return n; }
  double Min() const           { return min; }
  double Max() const           { return max; }
  double Sum() const           { return sxt; }
  double SumSquare() const     { return sx2t; }
  double StartTime() const     { return t0; }
  double LastTime() const      { return tl; }
  double LastValue() const     { return xl; }
  double MeanValue() const;
};


////////////////////////////////////////////////////////////////////////////
// class List --- list of Link* items, uses data from Link
//
class List : public Link { // circular list of Link items
    List(List&);                         // disable
    void operator= (List&);              // disable
    static Link *next(Link*p) { return p->succ; }
    static Link *previous(Link*p) { return p->pred; }
    unsigned n;                          // number of objects in list
  protected:  //## repair
    class iterator {
	    // next two lines can be removed ##
	    Link *p; // position in List
    public:
	    iterator(const iterator&x): p(x.p) {} 
	    iterator &operator=(const iterator&x) { p = x.p; return *this; }
	    iterator(Link *pos) : p(pos) {}
	    iterator &operator++() { p = List::next(p); return *this; }
	    iterator &operator--() { p = List::previous(p); return *this; }
	    iterator operator++(int) {
	        Link *tmp = p; p = List::next(p); return tmp;
	    }
	    iterator operator--(int) {
	        Link *tmp = p; p = List::previous(p); return tmp;
	    }
	    Link * operator*() const { return p; }
	    bool operator != (iterator q) const { return p!=q.p; }
	    bool operator == (iterator q) const { return p==q.p; }
    }; // iterator
    friend class iterator;
 public:
    List();
    List(const char *_name);
    ~List();
    virtual void Output();               // print
    // should be renamed:
    void InsFirst(Link *e);              // insert operations
    void InsLast (Link *e);
    void PredIns(Link *e, iterator pos); //
    void PostIns(Link *e, iterator pos); //
    Link *GetFirst();                    // removing operations
    Link *GetLast();                     //
    virtual Link *Get(iterator pos);     // remove at position
    //  unsigned Length() { return size(); }  // COMPATIBILITY
    //  virtual void Clear() { clear(); }    // remove all items
    // new-style:
    unsigned size() const  { return n; }
    iterator begin()  { return Link::succ; }
    iterator end()    { return this; }
    Link *front()     { return empty() ? 0 : Link::succ; }
    Link *back()      { return empty() ? 0 : Link::pred; }
    bool empty()      { return Link::succ == this; }
    void clear();
}; // List


////////////////////////////////////////////////////////////////////////////
// class Queue --- priority queue
//
class Queue : public List { // don't inherit interface for now
//##repair
    friend class Facility;
    friend class Store;
  public:
    typedef List::iterator iterator;
    TStat StatN;
    Stat  StatDT;                        // statistics
    Queue();
    Queue(const char *_name);
    ~Queue();
    virtual const char *Name();
    virtual void Output();               // print
    operator Queue* () { return this; }  // allows Queue instead Queue*
    iterator begin()   { return List::begin(); }
    iterator end()     { return List::end(); }
    Entity *front()    { return (Entity*)List::front(); }
    Entity *back()     { return (Entity*)List::back(); }
    void clear();
    // size(), empty() inherited
    // backward COMPATIBILITY
    void Clear()  { clear(); }
    bool Empty()  { return empty(); }
    unsigned Length() { return size(); }
    // to rename:
    void Insert  (Entity *e);            // priority insert
    void InsFirst(Entity *e);
    void InsLast (Entity *e);
    void PredIns (Entity *e, iterator pos); // insert at position
    void PostIns (Entity *e, iterator pos);
    Entity *Get(iterator pos);           // remove entity
    Entity *GetFirst();
    Entity *GetLast();
};

////////////////////////////////////////////////////////////////////////////
//  class Histogram - output
//
class Histogram : public SimObject {
    Histogram(const Histogram&); // ## disable
    Histogram&operator=(const Histogram&); // ## disable
 protected:
  unsigned *dptr;            // value array
  double   low;              // low bound
  double   step;             // interval width
  unsigned count;            // number of intervals
 public:
  Stat     stat;             // statistics
  Histogram();
  Histogram(double low, double step, unsigned count=10);
  Histogram(const char *_name, double low, double step, unsigned count=10);
  ~Histogram();
  virtual void Output();               // print
  void Init(double low, double step, unsigned count);
  void operator () (double x);         // record value x
  virtual void Clear();                // initialize (zero) value array
  double Low() const     { return low; }
  double High() const    { return low + step*count; }
  double Step() const    { return step; }
  unsigned Count() const { return count; }
  unsigned operator [](unsigned i) const;  // # of items in interval[i]
};



////////////////////////////////////////////////////////////////////////////
//  class Facility - (SOL-like)
//
class Facility : public SimObject {
    Facility(const Facility&); // ## disable
    Facility&operator=(const Facility&); // ## disable
  unsigned char _Qflag;
 public:
  Entity *in;                // entity in service
  Queue  *Q1;                // input queue
  Queue  *Q2;                // interrupted requests queue
  TStat tstat;               // stat
  Facility();
  Facility(const char *_name);
  Facility(Queue *_queue1);
  Facility(const char *_name, Queue *_queue1);
  virtual ~Facility();
  virtual void Output();                         // print output
  operator Facility* () { return this; }
  void SetQueue(Queue *queue1);                  // change input queue
  bool OwnQueue() const;                                // test
  bool Busy() const { return in!=0; }
  unsigned QueueLen() const { return Q1->size(); }
  virtual void Seize(Entity *e, ServicePriority_t sp=DEFAULT_PRIORITY);
  virtual void Release(Entity *e);
  virtual void QueueIn(Entity *e, ServicePriority_t sp); // go into queue Q1
  virtual void Clear();                          // init
 protected:
  virtual void QueueIn2(Entity *e);              // do into Q2
};

////////////////////////////////////////////////////////////////////////////
//  class Store - (SOL-like)
//
class Store : public SimObject {
    Store(const Store&);    // ## disable
    Store&operator=(const Store&);    // ## disable
  unsigned char _Qflag;
  unsigned long capacity;        // capacity of store
  unsigned long used;            // used capacity
 public:
  Queue *Q;
  TStat tstat;               // statistics
  Store();
  Store(unsigned long _capacity);
  Store(const char *_name, unsigned long _capacity);
  Store(unsigned long _capacity, Queue *queue);
  Store(const char *_name, unsigned long _capacity, Queue *queue);
  virtual ~Store();
  virtual void Output();                         // print
  operator Store* () { return this; }
  void SetCapacity(unsigned long _capacity);
  void SetQueue(Queue *queue);
  unsigned long Free() const { return capacity - used; }   // free capacity
  unsigned long Used() const { return used; }              // used capacity
  unsigned long Capacity() const { return capacity; }      // max capacity
  bool Full() const   { return Free() == 0; }           // store is full
  bool Empty() const  { return Used() == 0; }           // store is empty
  bool OwnQueue();
  unsigned QueueLen() const { return Q->size(); }
  virtual void Enter(Entity *e, unsigned long rcap); // allocate
  virtual void Leave(unsigned long rcap);            // deallocate
  virtual void QueueIn(Entity *e, unsigned long c);  // go into queue
  virtual void Clear();                          // init
};


////////////////////////////////////////////////////////////////////////////
// CATEGORY: continuous blocks
//

////////////////////////////////////////////////////////////////////////////
// aBlock - base class for blocks ### ???
//
class aBlock : public SimObject {                // base class
};

////////////////////////////////////////////////////////////////////////////
// aContiBlock -- abstract continuous block with single output
//
class aContiBlock : public aBlock {  // abstract continuous block
    aContiBlock(const aContiBlock&);   // disable copy ctr
    void operator= (aContiBlock&);     // disable assignment
    virtual void Eval() {};            // evaluate without loop detection
  protected:
    bool isEvaluated;                  // flag for loop checking ###---
  public:
    aContiBlock(): isEvaluated(false) {}
    virtual void _Eval();              // evaluate with loop detection
    virtual double Value() = 0;        // output value
};

////////////////////////////////////////////////////////////////////////////
// Constant --- value can't be changed
//
class Constant : public aContiBlock {
  const double value;
 public:
  Constant(double x) : value(x) {}
  virtual double Value ()       { return value; }
};

////////////////////////////////////////////////////////////////////////////
// Variable --- variable (value can be changed)
//
class Variable : public aContiBlock {
  double value;
 public:
  Variable(double x=0) : value(x) {}
  Variable &operator= (double x)  { value = x; return *this; }
  virtual double Value ()         { return value; }
};

////////////////////////////////////////////////////////////////////////////
// Parameter -- variable (can't be changed at simulation time)
//
class Parameter : public aContiBlock {
  double value;
 public:
  Parameter(double x) : value(x) {}
  Parameter &operator= (double x)    { value = x; return *this; } // add test ###!!!
  virtual double Value ()        { return value; }
};


// time values:
extern const double & StartTime;       // time of simulation start
extern const double & NextTime;        // next-event time
extern const double & EndTime;         // time of simulation end
//WARNING: Time cannot be used in block expressions!
extern const double & Time;            // simulation time (is NOT the block)
extern aContiBlock  & T;               // reference to time block


////////////////////////////////////////////////////////////////////////////
// class Input --- continuous block connection (transparent reference)
//
class Input {                   // small objects, without virtual methods
  aContiBlock *bp;
 public:
  Input(const Input &in): bp(in.bp) {}        // copy reference
  Input(aContiBlock &cb): bp(&cb) {}          // reference to block
  Input(aContiBlock *cb): bp(cb)  {}          // pointer to block
  Input(const double c):  bp(new Constant(c)) {} // expression of type double
  // WARNING: using C++ variables in block expressions --> constant
  Input Set(Input i)     { Input p=bp; bp=i.bp; /*LoopCheck();*/ return p; }
  double Value() const         { return bp->Value(); }   // get value
  bool operator ==(aContiBlock *p) const { return bp==p; }    // for tests only! ###
  Input &operator= (const Input&x) { bp = x.bp; return *this; }
};


////////////////////////////////////////////////////////////////////////////
// aContiBlock1  --  continuous blocks vith single input
//                   and algebraic loop check
//
class aContiBlock1 : public aContiBlock {
  Input input;
 public:
  aContiBlock1(Input i);
  double InputValue() { return input.Value(); }
};

////////////////////////////////////////////////////////////////////////////
// Expression -- reference to block expression
//
struct Expression : public aContiBlock1 {
  Expression(Input i) : aContiBlock1(i) {}
  double Value() { return InputValue(); }
};

////////////////////////////////////////////////////////////////////////////
// aContiBlock2  --  continuous blocks vith two inputs
//
class aContiBlock2 : public aContiBlock {
  Input input1;
  Input input2;
 public:
  aContiBlock2(Input i1, Input i2);
  double Input1Value() { return input1.Value(); }
  double Input2Value() { return input2.Value(); }
};

////////////////////////////////////////////////////////////////////////////
// aContiBlock3  --  continuous blocks vith three inputs
//                   and algebraic loop check
//
class aContiBlock3 : public aContiBlock {
  Input input1;
  Input input2;
  Input input3;
 public:
  aContiBlock3(Input i1, Input i2, Input i3);
  double Input1Value() { return input1.Value(); }
  double Input2Value() { return input2.Value(); }
  double Input3Value() { return input3.Value(); }
};


////////////////////////////////////////////////////////////////////////////
//  IntegratorContainer - container of integrators,
//                        it is a singleton
//
class IntegratorContainer {
private:
  static dlist<Integrator*> * ListPtr;  // list of integrators
  IntegratorContainer();  // forbid constructor
  static dlist<Integrator*> * Instance(void);  // return list (& create)
public:
  typedef dlist<Integrator*>::iterator iterator;
  // is there any integrator in the list? (e.g. list is not empty)
  static bool isAny(void) {
    return ListPtr!=0 && !(ListPtr->empty());
  }
  // # of elements in the list
  static size_t Size(void) {
    return (ListPtr!=0) ? (ListPtr->size()) : 0;
  }
  // return iterator to the first element
  static iterator Begin(void) {
    return Instance()->begin();
  }
  // return iterator to the end (not to the last element!)
  static iterator End(void) {
    return Instance()->end();
  }
  static iterator Insert(Integrator* ptr);  // insert element into container
  static void Erase(iterator it);  // exclude element
  static void InitAll();           // initialize all
  static void EvaluateAll();       // evaluate all integrators
  static void LtoN();              // last -> now
  static void NtoL();              // now -> last
}; // class IntegratorContainer


////////////////////////////////////////////////////////////////////////////
//  StatusContainer -- container of status variables,
//                     it is a singleton
//
class StatusContainer {
private:
  static dlist<Status*>* ListPtr;  // list of integrators
  StatusContainer();  // forbid constructor
  static dlist<Status*>* Instance(void);  // return list (& create)
public:
  typedef dlist<Status*>::iterator iterator;
  // is there any integrator in the list? (e.g. list is not empty)
  static bool isAny(void) {
    return ListPtr!=0 && !(ListPtr->empty());
  }
  // # of elements in the list
  static size_t Size(void) {
    return (ListPtr!=0) ? (ListPtr->size()) : 0;
  }
  // return iterator to the first element
  static iterator Begin(void) {
    return Instance()->begin();
  }
  // return iterator to the end (not to the last element!)
  static iterator End(void) {
    return Instance()->end();
  }
  static iterator Insert(Status* ptr);  // insert element into container
  static void Erase(iterator it);  // exclude element
  static void InitAll();           // initialize all
  static void ClearAllValueOK();   // invalidate values of all items
  static void EvaluateAll();       // evaluate all integrators
  static void LtoN();              // last -> now
  static void NtoL();              // now -> last
}; // class StatusContainer


////////////////////////////////////////////////////////////////////////////
//  IntegrationMethod
//  Abstract base class for integration methods
//
class IntegrationMethod {
    IntegrationMethod(const IntegrationMethod&); // ## disable
    IntegrationMethod&operator=(const IntegrationMethod&); // ## disable
private:
  static IntegrationMethod* CurrentMethodPtr;  // method used at present
  static dlist<IntegrationMethod*>* MthLstPtr; // list of registrated methods
  dlist<IntegrationMethod*>::iterator ItList;  // position in the list
  char* Name;  // the name of the method
protected:  //## repair
  class Memory;  // forward declaration
  friend class Memory;
private:   //## repair
  size_t PrevINum;  // # of integrators in previous step
  dlist<Memory*> MList;  // list of auxiliary memories
  static dlist<Memory*> * PtrMList;  // pointer to list being filled
  IntegrationMethod();  // forbid implicit constructor
  IntegrationMethod(IntegrationMethod&);  // forbid implicit copy-constructor
  static bool Prepare(void);  // prepare system for integration step
  static void Iterate(void);  // compute new values of state blocks
  static void Summarize(void);  // set up new state after integration
protected:
  static bool IsEndStepEvent; // flag - will be event at the end of the step?
  typedef IntegratorContainer::iterator Iterator;  // iterator of intg. list
  static Iterator FirstIntegrator(void) {  // it. to first integrator in list
    return IntegratorContainer::Begin();
  }
  static Iterator LastIntegrator(void) {  // it. to last integrator in list
    return IntegratorContainer::End();
  }
  static bool StateCond(void);  // check on changes of state conditions
  static IntegrationMethod* SearchMethod(const char* name);  // find method

  /* memory of auxiliary values */

  class Memory {
      Memory(const Memory&); // ## disable
      Memory&operator=(const Memory&); // ## disable
    private:
      static const size_t page_size;  // size of memory page
      double *arr;  // array
      size_t mem_size;  // allocated memory size
      Memory(Memory&);  // forbid copy constructor
      void operator= (Memory&);  // disable the operation
      dlist<Memory*>::iterator it_list;  // position in list
      dlist<Memory*> * ListPtr;  // which list is memory in
    public:
      Memory(dlist<Memory*> * PtrList=PtrMList);  // create empty memory
      virtual ~Memory();
      double& operator[](size_t ind) {  // access the element of the array
        //      dprintf(("IntegrationMethod::Memory::operator[](%lu) = %g",
        //         (long unsigned)ind, arr[ind]));
        return arr[ind];
      }
      virtual void Resize(size_t cs); // change size, content will be undefined!
  }; // class Memory

public:
  IntegrationMethod(const char* name);  // registrate method and name it
  virtual ~IntegrationMethod();  // destructor unregistrates method
  virtual bool IsSingleStep(void)=0; // is it a single-step method?
  virtual void TurnOff(void);  // turn off integration method
  virtual void Integrate(void) = 0;  // the method does integration
  virtual bool PrepareStep(void);  // prepare object for integration step
  virtual void Resize(size_t size);  // resize all memories to given size
  static void StepSim(void);  // single step of numerical integration method
  static void IntegrationDone(void) {  // terminate integration
    CurrentMethodPtr->TurnOff();  // suspend present method
  }
  static void SetMethod(const char* name);  // set method which will be used
  static char* const GetMethod(void) {  // get name of method which is used
    return CurrentMethodPtr->Name;
  }
  // auxiliary functions (interface) for user to add own method
  static void InitStep(double step_frag); // initialize step
  static void FunCall(double step_frag); // evaluate y'(t) = f(t, y(t))
  static void SetOptStep(double opt_step) { // set optimal step size
    extern double SIMLIB_OptStep; // available without including internal.h
    SIMLIB_OptStep = opt_step;
  }
  static void SetStepSize(double step_size) { // set step size
    extern double SIMLIB_StepSize; // available without including internal.h
    SIMLIB_StepSize = step_size;
  }
  static bool IsConditionFlag(void) { // wer any changes of condition vector?
    extern bool SIMLIB_ConditionFlag; // available without ... blah, blah
    return SIMLIB_ConditionFlag;
  }
  static int GetErrNo(void) { // return # of errors
    extern int SIMLIB_ERRNO;
    return SIMLIB_ERRNO;
  }
  static void SetErrNo(int num) { // set # of errors
    extern int SIMLIB_ERRNO;
    SIMLIB_ERRNO = num;
  }
}; // class IntegrationMethod


////////////////////////////////////////////////////////////////////////////
//  single-step integration method
//
class SingleStepMethod : public IntegrationMethod {
private:
  // flag: single-step method is used to start multi-step method
  // (e. g. to restrict step increasing)
  bool StartMode;
public:
  SingleStepMethod(const char* name) :  // initialize method and registrate it
    IntegrationMethod(name),
    StartMode(false)
  { /* NOTHING */ }
  virtual void Integrate(void) = 0;  // the method does integration
  virtual bool IsSingleStep(void) {  // it's a single-step method
    return true;
  }
  void SetStartMode(bool start_mode) {  // set flag on/off
    StartMode=start_mode;
  }
  bool IsStartMode(void) {  // is method used to start multi-step method?
    return StartMode;
  }
}; // class SingleStepMethod


////////////////////////////////////////////////////////////////////////////
//  multi-step integration method
//
class MultiStepMethod : public IntegrationMethod {
    MultiStepMethod(const MultiStepMethod&); // ## disable
    MultiStepMethod&operator=(const MultiStepMethod&); // ## disable
private:
  char* SlaveName;  // the name of the method used for starting
  SingleStepMethod* Slave_Ptr;  // pointer to the method used for starting
protected:
  SingleStepMethod* SlavePtr(void);  // return pointer to the starting method
public:
  // initialize method
  MultiStepMethod(const char* name, const char* slave_name);
  ~MultiStepMethod();  // destructor frees dynamic data
  virtual bool IsSingleStep(void) {  // it's a multi-step method
    return false;
  }
  // set starting method for given method
  static void SetStarter(const char* name, const char* slave_name);
  // set starting method for the method
  virtual void SetStarter(const char* slave_name);
  // get the name of starting method of given method
  static char* const GetStarter(const char* name);
  virtual bool PrepareStep(void);  // prepare the object for the step
  virtual void Integrate(void) = 0;  // the method does integration
  virtual void TurnOff(void);  // turn off method & its slave
}; // class MultiStepMethod


////////////////////////////////////////////////////////////////////////////
//  Abstract base class for integration methods
//  with status auxiliary memories
//
class StatusMethod : public SingleStepMethod {
private:
  StatusMethod();  // forbid implicit constructor
  StatusMethod(StatusMethod&);  // forbid implicit copy-constructor
  size_t PrevStatusNum;  // # of status variables in previous step
  dlist<Memory*> StatusMList;  // list of auxiliary memories
  static dlist<Memory*>* PtrStatusMList;  // pointer to list being filled
protected:
  typedef StatusContainer::iterator StatusIterator;  // iterator of intg. list
  static StatusIterator FirstStatus(void) {  // it. to first status in list
    return StatusContainer::Begin();
  }
  static StatusIterator LastStatus(void) {  // it. to last status in list
    return StatusContainer::End();
  }

//## repair
  friend class EULER;
  friend class RKE;
  /* memory of auxiliary status values */
  class StatusMemory : public Memory {
  private:
    StatusMemory(StatusMemory&);  // forbid copy constructor
    void operator= (StatusMemory&);  // disable the operation
  public:
    // create empty memory
    StatusMemory(dlist<Memory*>* PtrList=PtrStatusMList) : Memory(PtrList) { }
    // free dynamic data
    virtual ~StatusMemory() { }
  }; // class StatusMemory

  friend class StatusMemory;

  // store state of integrators and status variables
  static void StoreState(Memory& di, Memory& si, StatusMemory& xi);
  // restore state of integrators and status variables
  static void RestoreState(double dthlf, Memory& di,
                           Memory& si, StatusMemory& xi);
  // move startpoint to given state
  static void GoToState(Memory& di, Memory& si, StatusMemory& xi);

public:
  StatusMethod(const char* name);  // initailization
  virtual ~StatusMethod() { } // free dynamic datas
  virtual void TurnOff(void);  // turn off integration method
  virtual void Integrate(void) = 0;  // the method does integration
  virtual bool PrepareStep(void);  // prepare integration step
  virtual void StatusResize(size_t size);  // resize status memories
}; // StatusMethod


////////////////////////////////////////////////////////////////////////////
//  interface for class IntegrationMethod & its descendants
//

// set the method which will be used to integrate
// Methods: "abm4", "euler", "fw", "rke"(default), "rkf3", "rkf5", "rkf8"

inline void SetMethod(const char* name)
{
  IntegrationMethod::SetMethod(name);
} // SetMethod

// get the name of the method which is used

inline char* const GetMethod(void)
{
  return IntegrationMethod::GetMethod();
} // GetMethod

// set the method which will be used to start given multistep method

inline void SetStarter(const char* name, const char* slave_name)
{
  MultiStepMethod::SetStarter(name, slave_name);
} // SetStarter

// set the method which will be used to start currently used multistep method

inline void SetStarter(const char* slave_name)
{
  MultiStepMethod::SetStarter(IntegrationMethod::GetMethod(), slave_name);
} // SetStarter

// get the name of the method which is used to start given multistep method

inline char* const GetStarter(const char* name)
{
  return MultiStepMethod::GetStarter(name);
} // GetStarter

// get the name of the method which is used
// to start currently used multistep method

inline char* const GetStarter(void)
{
  return MultiStepMethod::GetStarter(IntegrationMethod::GetMethod());
} // GetStarter


////////////////////////////////////////////////////////////////////////////
//  class Integrator - special continuous block
//
class Integrator : public aContiBlock {   // integrator
 private:
  Integrator &operator= (const Integrator &x); // disable assignment
  double dd;                           // input value: y'=f(t,y)
  double ddl;                          // the same from previous step
  double ss;                           // status: y = S f(t,y) dt
  double ssl;                          // the same from previous step
 protected:
  Input input;                         // input expression: f(t,y)
  double initval;                      // initial value: y(t0)
  void CtrInit();
  IntegratorContainer::iterator it_list; // position in list of integrators
 public:
  Integrator();                        // implicit CTR (input = 0)
  Integrator(Input i, double initvalue=0);
  Integrator(Integrator &i, double initvalue=0); // copy-ctr
  ~Integrator();
  void Init(double initvalue);         // set value
  void Init() { Init(initval); }       // set initial value
  void Set(double value);              // set value
  Integrator &operator= (double x) { Set(x); return *this; }
  Input SetInput(Input inp) { return input.Set(inp); }
  void Eval();                         // input evaluation
  double Value();                      // status
  double InputValue() { return input.Value(); }
  // interface
  void Save(void) { ddl=dd; ssl=ss; }  // save status
  void Restore(void) { dd=ddl; ss=ssl; }  // restore saved status
  void SetState(double s) { ss=s; }
  double GetState(void) { return ss; }
  void SetOldState(double s) { ssl=s; }
  double GetOldState(void) { return ssl; }
  void SetDiff(double d) { dd=d; }
  double GetDiff(void) { return dd; }
  void SetOldDiff(double d) { ddl=d; }
  double GetOldDiff(void) { return ddl; }
};


////////////////////////////////////////////////////////////////////////////
//  class Status -- status variables
//
class Status : public aContiBlock1 {   // state-variables
  Status(Status&);                     // disable copy ctor
  void operator= (Status&);            // disable assignment
 protected:
  double initval;                      // initial value
  bool ValueOK;                        // valid-flag ###
  void CtrInit();
  StatusContainer::iterator it_list;   // position in list of status variables
 public:
  double st;                           // status
  double stl;                          // status from previous step
  Status(Input i, double initvalue=0);
  ~Status();
  void Init(double initvalue);         // value initialization
  void Init() { Init(initval); }
  void Set(double value);              // set status of block
  virtual void Eval();                 // block evaluation
  virtual double Value();              // block status
  // interface
  void Save() { stl = st; }            // save status
  void Restore();                      // restore saved status
  void SetState(double s) { st=s; }
  double GetState(void) { return st; }
  void SetOldState(double s) { stl=s; }
  double GetOldState(void) { return stl; }
  void SetValid(bool flag) { ValueOK = flag; } // set valid flag
};


////////////////////////////////////////////////////////////////////////////
// Hyst --- hysteresis
//
class Hyst : public Status {
  protected:
    double p1,p2;
    double y1,y2;
    double tga;
    virtual void Eval();           // block evaluation
  public:
    Hyst(Input i, double p1, double p2, double y1, double y2, double tga);
};

typedef Hyst Hysteresis; // alias name


////////////////////////////////////////////////////////////////////////////
// Blash --- backlash
//
class Blash : public Status {    // backlash
  protected:
  double p1,p2;
  double tga;
 public:
  Blash(Input i, double p1, double p2, double tga);
  virtual void Eval();           // block evaluation
}; // Blash

typedef Blash Backlash;

////////////////////////////////////////////////////////////////////////////
// Relay --- detects exact time of switch
//
class Relay : public Status {   // general relay block
  protected:
  double p1,p2,p3,p4;           // points on x-axis
  double y1,y2;                 // points on y-axis
 public:
  Relay(Input i, double p1, double p2, double p3, double p4,
	         double y1, double y2);
  virtual void Eval();          // block evaluation
}; // Relay


////////////////////////////////////////////////////////////////////////////
// Continuous block arithmetic operators
//

// binary operators:
Input operator + (Input a, Input b);
Input operator - (Input a, Input b);
Input operator * (Input a, Input b);
Input operator / (Input a, Input b);

// unary operators:
Input operator - (Input a);

// functions:
Input Abs(Input x);             // abs(x)     absolute value
Input Sin(Input x);             // sin(x)
Input Cos(Input x);             // cos(x)
Input Tan(Input x);             // tan(x)
Input ASin(Input x);            // asin(x)
Input ACos(Input x);            // acos(x)
Input ATan(Input x);            // atan(x)
Input ATan2(Input y, Input x);  // atan2(y,x)
Input Exp(Input x);             // exp(x)     e ** x
Input Log10(Input x);           // log10(x)
Input Ln(Input x);              // ln(x)      natural logarithm
Input Pow(Input x, Input y);    // pow(x,y)   x ** y
Input Sqr(Input x);             // square     x * x
Input Sqrt(Input x);            // square root
Input Min(Input x, Input y);    // minimum
Input Max(Input x, Input y);    // maximum
Input Sign(Input x);            // signum  ###warning-steps-not-detected


////////////////////////////////////////////////////////////////////////////
// class Function - functions with one argument
//
class Function : public aContiBlock1 {
    Function(const Function&); // ## disable
    Function&operator=(const Function&); // ## disable
  double (*f)(double); // pointer to function
 public:
  Function(Input i, double (*pf)(double));
  virtual double Value();
};

////////////////////////////////////////////////////////////////////////////
// class Function2 - other functions with two arguments
//
class Function2 : public aContiBlock2 {
    Function2(const Function2&); // ## disable
    Function2&operator=(const Function2&); // ## disable
  double (*f)(double,double); // pointer to function
 public:
  Function2(Input i1, Input i2, double (*pf)(double,double));
  virtual double Value();
};


////////////////////////////////////////////////////////////////////////////
// CATEGORY: state conditions

////////////////////////////////////////////////////////////////////////////
// aCondition --- base abstract class for all state-event blocks
//
class aCondition : public aBlock {
  static aCondition *First;            // list of all conditions
  aCondition *Next;                    // next condition in list
  void operator= (aCondition&);        // disable operation
  aCondition(aCondition&);             // disable operation
 public:
  aCondition();
  ~aCondition();
  static void InitAll();
  static void SetAll();
  static void TestAll();
  static void AllActions();
  static bool isAny();
  virtual bool Value()=0;               // state of condition
 private:
  virtual void Init()=0;
  virtual void SetNewStatus()=0;
  virtual bool Test()=0;               // test of condition
  virtual void Action()=0;             // state event action
};

////////////////////////////////////////////////////////////////////////////
// Condition -- conditional changes - Boolean version (int)
//
class Condition : public aCondition {  // state condition
  Input in;                            // block input
  unsigned char cc;                    // state
  unsigned char ccl;                   // old state
  virtual void Init();
  virtual void SetNewStatus();
 protected:
  virtual bool Test();                  // test function (input >= 0.0)
  bool Up()     { return ccl<cc; }      // change: FALSE->TRUE
  bool Down()   { return ccl>cc; }      // change: TRUE->FALSE
  bool Change() { return ccl!=cc; }     // both changes
 public:
  Condition(Input i);
  ~Condition();
  virtual bool Value() { return cc; }   // status
  Input SetInput(Input inp) { return in.Set(inp); } // change input block
  virtual void Action()=0;             // state event
};

////////////////////////////////////////////////////////////////////////////
// ConditionUp -- detector of FALSE-->TRUE
//
class ConditionUp : public Condition { // state event on FALSE-->TRUE change
 public:
  ConditionUp(Input i) : Condition(i) {}
  bool Test() { return Condition::Test() && Up(); }
  virtual void Action()=0;             // state event
};

////////////////////////////////////////////////////////////////////////////
// ConditionDown -- detector of TRUE-->FALSE
//
class ConditionDown : public Condition { // state event on TRUE-->FALSE change
 public:
  ConditionDown(Input i) : Condition(i) {}
  bool Test() { return Condition::Test() && Down(); }
  virtual void Action()=0;                // state event
};




////////////////////////////////////////////////////////////////////////////
// CATEGORY: non-linear blocks


////////////////////////////////////////////////////////////////////////////
// Lim -- limitation
//
class Lim : public aContiBlock1 {
  protected:
  double low, high;               // limits
  double tgalpha;                 //
 public:
  Lim(Input in, double l, double h, double tga=1.0);
  virtual void _Eval();           // evaluation with loop check
  virtual double Value();         // returned value
};

typedef Lim Limitation;

////////////////////////////////////////////////////////////////////////////
// Insv -- dead zone
//
class Insv : public aContiBlock1 {
  protected:
  double low, high;               // limits
  double tgalpha,tgbeta;          //
 public:
  Insv(Input in, double l, double h, double tga=1.0, double tgb=1.0);
  virtual void _Eval();           // evaluation with loop check
  virtual double Value();         // returned value
};

typedef Insv DeadZone;

////////////////////////////////////////////////////////////////////////////
// Qntzr -- quantizer
//
class Qntzr : public aContiBlock1 {
  protected:
  double step;                    // quantum
 public:
  Qntzr(Input in, double qstep=1.0);
  virtual void _Eval();           // evaluation with loop check
  virtual double Value();         // returned value
};

typedef Qntzr Quantizer;

////////////////////////////////////////////////////////////////////////////
// Frict -- friction
//
class Frict : public aContiBlock1 {
  protected:
  double low, high;               // limits
  double tgalpha;                 //
 public:
  Frict(Input in, double l, double h, double tga=1.0);
  virtual void _Eval();           // evaluation with loop check
  virtual double Value();         // returned value
};

typedef Frict Friction;

////////////////////////////////////////////////////////////////////////////
// Rline -- function defined by table of values
//
//TODO: reimplement with vectors
class Rline : public aContiBlock1 {
    Rline(const Rline&); // ## disable
    Rline&operator=(const Rline&); // ## disable
  protected:
  int n;                          // table item number
  double *tableX;                 // tabulka X
  double *tableY;                 // tabulka Y
 public:
  Rline(Input in, int num, double *X, double *Y);
  ~Rline();
  virtual void _Eval();           // evaluation with loop check
  virtual double Value();         // returned value
};

////////////////////////////////////////////////////////////////////////////
// CATEGORY: algebraic loop solvers


////////////////////////////////////////////////////////////////////////////
// AlgLoop  --  abstract ancestor of algebraic loop solvers
//
class AlgLoop : public aContiBlock1 {
 protected:
  double Eps; // required accuracy
  unsigned long MaxIt; // max. number of iterations
  double TA; // boundary values of interval
  double TB; // (also used for convergency check)
  double T0; // initial value
  bool was_cycle; // flag for going through loop
  int phase; // phase of computation
  double root; // root of equation
 public:
  AlgLoop(Input i, double eps, unsigned long max_it, // constructor
          double t_min, double t_max, double t0);
  void Set(double eps, unsigned long max_it, // set parameters
           double t_min, double t_max, double t0);
  void Set(double eps, unsigned long max_it, // set parameters
           double t_min, double t_max);
  virtual double Value()=0; // returned value
}; // AlgLoop


////////////////////////////////////////////////////////////////////////////
// Iterations  --  solve using iterations
//
class Iterations : public AlgLoop {
 public:
  Iterations(Input i, double eps, unsigned long max_it,
             double t_min, double t_max, double t0):
    AlgLoop(i, eps, max_it, t_min, t_max, t0)
    {/*nothing*/}
  virtual double Value(); // returned value
}; // Iterations


////////////////////////////////////////////////////////////////////////////
// Halvint  --  solve using halving interval method
//
class Halvint : public AlgLoop {
 public:
  Halvint(Input i, double eps, unsigned long max_it,
          double t_min, double t_max):
    AlgLoop(i, eps, max_it, t_min, t_max, t_min)
    {/*nothing*/}
  virtual double Value(); // returned value
}; // Halvint


////////////////////////////////////////////////////////////////////////////
// RegulaFalsi  --  solve using method regula falsi
//
class RegulaFalsi : public AlgLoop {
  double eps_root; // root for force precision test
 public:
  RegulaFalsi(Input i, double eps, unsigned long max_it,
              double t_min, double t_max):
    AlgLoop(i, eps, max_it, t_min, t_max, t_min),
    eps_root(0)
    {/*nothing*/}
  virtual double Value(); // returned value
}; // RegulaFalsi


////////////////////////////////////////////////////////////////////////////
// Newton  --  solve using modified Newton's method
//
class Newton : public AlgLoop {
  double eps_root; // root for force precision test
  double prev_root; // root from previous iteration step
 public:
  Newton(Input i, double eps, unsigned long max_it,
         double t_min, double t_max, double t0):
    AlgLoop(i, eps, max_it, t_min, t_max, t0),
    eps_root(0), 
    prev_root(0)
    {/*nothing*/}
  virtual double Value(); // returned value
}; // Newton


////////////////////////////////////////////////////////////////////////////
// CATEGORY: global functions

////////////////////////////////////////////////////////////////////////////
// Naming Subsystem --- SimObject names (text identifiers)
// this is system dictionary:   relation: objectptr---textname
//
void SetName(SimObject &o, const char *name);
void SetName(SimObject *o, const char *name);
void RemoveName(SimObject &o);
void RemoveName(SimObject *o);
const char *GetName(SimObject &o);
const char *GetName(SimObject *o);


////////////////////////////////////////////////////////////////////////////
// InstallBreak --- set function for checking if user breaks simulation
//
// f will be called each step of simulation
//
void InstallBreak(void (*f)());  // f can call Stop() or Abort()


////////////////////////////////////////////////////////////////////////////
//  class Semaphore --- basic synchronization tool for processes
//
class Semaphore : public SimObject {
  protected:
  int n;
 public:
  Queue Q;                                      // internal quqeue
  Semaphore();                                  // constructor
  Semaphore(const char *_name);                 // with associated name
  virtual ~Semaphore();
  virtual void Clear();                         // initialization
  virtual void Output();
  virtual void P();                             // P operation
  virtual void V();                             // V operation
  operator Semaphore* () { return this; }
};

////////////////////////////////////////////////////////////////////////////
// class Barrier --- synchronization tool for processes
//
class Barrier : public SimObject {
    Barrier(const Barrier&); // ## disable
    Barrier&operator=(const Barrier&); // ## disable
  protected:
  Entity **waiting;     // array of waiting entities (fixed size)
  unsigned n;           // number of waiting entities (actual number)
  const unsigned maxn;  // barrier capacity ### (size)
  void Init();          // initialization
 public:
  Barrier(unsigned N);
  Barrier(const char *_name, unsigned N);
  virtual ~Barrier();
//  void ChangeCapacity(unsigned N);          // change N
  unsigned Capacity() const { return maxn; }      // barrier size
  virtual void Enter(Entity *e);            // entity arrival
  virtual int Break();                      // activate all waiting entities
  virtual void Clear();                     // initialization
  virtual void Output();                    // print
  operator Barrier* () { return this; }
};


#endif // ifndef __SIMLIB_H

// end of simlib.h

