/////////////////////////////////////////////////////////////////////////////
// continuous.cc
//
// SIMLIB version: 2.18
// Date: 2004-01-25
//
// Copyright (c) 1991-2004 Petr Peringer 
//
// This library is licensed under GNU Library GPL. See the file COPYING.
//

//
// description: news to version 2.0
//
//  - blocks for + - * / operations
//  - dynamical section replacement: _Dynamic()
//  - evaluation with alg. loop detections


////////////////////////////////////////////////////////////////////////////
// interface
//

#include "simlib.h"
#include "internal.h"


////////////////////////////////////////////////////////////////////////////
// implementation
//

SIMLIB_IMPLEMENTATION

////////////////////////////////////////////////////////////////////////////
// _Dynamic -- replacement of dynamical section
//
// performs evaluation of integrators and status blocks
//
void SIMLIB_Dynamic() // called every step
{
  StatusContainer::ClearAllValueOK(); // zero flags ###
  StatusContainer::EvaluateAll();     // evaluation (with loop detection) ???
  IntegratorContainer::EvaluateAll(); // evaluation without loop detection
}


////////////////////////////////////////////////////////////////////////////
// aContiBlock::_Eval -- evaluation with algebraic loop detection   ###
//
void aContiBlock::_Eval()
{
  if(isEvaluated)                      // was evaluated
    SIMLIB_error(AlgLoopDetected);     // recursive call
  isEvaluated = true;                  // eval-flag
  Eval();                              // evaluation of block
  isEvaluated = false;
}


////////////////////////////////////////////////////////////////////////////
//  aContiBlock1 -- base for blocks with one input
//
aContiBlock1::aContiBlock1(Input i) : input(i)
{
  if(input==this) SIMLIB_error(AlgLoopDetected);
//  LoopCheck();  // ERROR!!!!!!!! uninitializaed references!
}

/*
void aContiBlock1::LoopCheck()
{
  dprintf(("aContiBlock1::LoopCheck() oid=%p", this));
  if(isEvaluated)
    SIMLIB_error(AlgLoopDetected);    // if recursive call
  isEvaluated = true;
  input.LoopCheck();
  isEvaluated = false;
}
*/

/*
Input aContiBlock1::SetInput(Input i)
{
  if(i==this)    SIMLIB_error(AlgLoopDetected);
//  LoopCheck();                  // detect algebraic loops
  return input.Set(i);
}
*/

////////////////////////////////////////////////////////////////////////////
//  aContiBlock2 -- base for blocks with 2 inputs
//
aContiBlock2::aContiBlock2(Input i1, Input i2) : input1(i1), input2(i2)
{
  if(input1==this || input2==this) SIMLIB_error(AlgLoopDetected);
//  LoopCheck();  // ERROR!!!!!!!! uninitializaed references!
}

aContiBlock3::aContiBlock3(Input i1, Input i2, Input i3)
  : input1(i1), input2(i2), input3(i3)
{
  if(input1==this || input2==this || input3==this )
    SIMLIB_error(AlgLoopDetected);
}

/*
void aContiBlock2::LoopCheck()
{
  dprintf(("aContiBlock2::LoopCheck() oid=%p", this));
  if(isEvaluated)
    SIMLIB_error(AlgLoopDetected);    // if recursive call
  isEvaluated = true;
  input1.LoopCheck();
  input2.LoopCheck();
  isEvaluated = false;
}
*/

/*
void aContiBlock2::SetInputs(Input i1, Input i2)
{
  input1.Set(i1);
  input2.Set(i2);
  if(input1==this || input2==this) SIMLIB_error(AlgLoopDetected);
//  LoopCheck();                  // detect algebraic loops
}

Input aContiBlock2::SetInput1(Input inp)
{
  if(inp==this) SIMLIB_error(AlgLoopDetected);
  Input old = input1.Set(inp);
//  LoopCheck();                  // detect algebraic loops
  return old;
}

Input aContiBlock2::SetInput2(Input inp)
{
  if(inp==this) SIMLIB_error(AlgLoopDetected);
  Input old = input2.Set(inp);
//  LoopCheck();                  // detect algebraic loops
  return old;
}
*/



////////////////////////////////////////////////////////////////////////////
// Add - sum of two inputs
//
class _Add : public aContiBlock2 {
  virtual void Eval() {}
  virtual void _Eval() {}
public:
  _Add(Input a, Input b): aContiBlock2(a,b) {
    dprintf(("ctr: _Add[%p](in1,in2)", this));
  }
  ~_Add() {
    dprintf(("dtr: _Add[%p]", this));
  }
  virtual double Value() { return Input1Value() + Input2Value(); }
};


////////////////////////////////////////////////////////////////////////////
// Sub - subtract
//
class _Sub : public aContiBlock2 {
  virtual void Eval() {}
  virtual void _Eval() {}
public:
  _Sub(Input a, Input b): aContiBlock2(a,b) {
    dprintf(("ctr: _Sub[%p](in1,in2)", this));
  }
  ~_Sub() {
    dprintf(("dtr: _Sub[%p]", this));
  }
  virtual double Value() { return Input1Value() - Input2Value(); }
};


////////////////////////////////////////////////////////////////////////////
// Mul - multiplier
//
class _Mul : public aContiBlock2 {
  virtual void Eval() {}
  virtual void _Eval() {}
public:
  _Mul(Input a, Input b): aContiBlock2(a,b) {
    dprintf(("ctr: _Mul[%p](in1,in2)", this));
  }
  ~_Mul() {
    dprintf(("dtr: _Mul[%p]", this));
  }
  virtual double Value() { return Input1Value() * Input2Value(); }
};


////////////////////////////////////////////////////////////////////////////
// Div - divider
//
class _Div : public aContiBlock2 {
  virtual void Eval() {}
  virtual void _Eval() {}
public:
  _Div(Input a, Input b): aContiBlock2(a,b) {
    dprintf(("ctr: _Div[%p](in1,in2)", this));
  }
  ~_Div() {
    dprintf(("dtr: _Div[%p]", this));
  }
  virtual double Value() { return Input1Value() / Input2Value(); }
};


////////////////////////////////////////////////////////////////////////////
// binary operators ...
//
Input operator + (Input a, Input b) { return new _Add(a,b); }
Input operator - (Input a, Input b) { return new _Sub(a,b); }
Input operator * (Input a, Input b) { return new _Mul(a,b); }
Input operator / (Input a, Input b) { return new _Div(a,b); }

// function
Input Sqr(Input x) { return new _Mul(x,x); }

////////////////////////////////////////////////////////////////////////////
// UMinus - unary minus
//
class _UMinus: public aContiBlock1 {
  virtual void Eval() {}
  virtual void _Eval() {}
public:
  _UMinus(Input a): aContiBlock1(a) {
    dprintf(("ctr: _UMinus[%p](in)", this));
  }
  ~_UMinus() {
    dprintf(("dtr: _UMinus[%p]", this));
  }
  virtual double Value()    { return -InputValue(); }
};


////////////////////////////////////////////////////////////////////////////
// unary operators ...
//
Input operator - (Input a) { return new _UMinus(a); }

////////////////////////////////////////////////////////////////////////////
// _Time - block: simulation time
//
class _Time: public aContiBlock {
 public:
  _Time() {}
  virtual double Value () { return Time; }
//  virtual void LoopCheck() {}
};
static class _Time _T;  // std. block -- simulation time
aContiBlock & T = _T;

////////////////////////////////////////////////////////////////////////////
// disabled operations -- for old GNU C++ only
//
#if 0
SimObject::SimObject(SimObject&) {}              
void SimObject::operator= (SimObject&) {}        

Link::Link(Link&) {}                             
void Link::operator= (Link&) {}                  

List::List(List&) {}                             
void List::operator= (List&) {}                  

Status::Status(Status&) : aContiBlock1(this) {}
void Status::operator= (Status&) {}              

aCondition::aCondition(aCondition&) {}           
void aCondition::operator= (aCondition&) {}      
#endif

// end of continuous.cc

