#include "ObjProDSP/portable.h"
#include "ObjProComGui/cgidbg.h"
#include "ObjProNet/dfnode.h"

#include "ObjProUsr/fde0.h"
#include "ObjProGen/outtok.h"
#include "ObjProGui/intfc.h"
#include "ObjProGui/remmen.h"
#include "ObjProGui/user.h"
#include "ObjProGui/dynmnu.h"
#include "ObjProArith/typout.h"
#include "ObjProGui/array.h"
#include "ObjProGui/interinit.h"
#include "ObjProGen/stattyp.h"
static EntityList * ZFde0NodeList = 0 ;
static InteractiveEntity * IntEntZFde0 ;
void ZFde0NodesInit();
ZFde0::ZFde0 (const char * Name, int32 Time0, int32 Time1, double Factor):
	Signal(Name, 1, 2, 1, 1, TimingTypeLinear, 
	(ArithType::ArithCapabilities)(TheArithType == ArithType::ArithInt16 ? TheArithType : ArithType::ArithInt32))
,
	Time0_1(Time0),
	Time1_2(Time1),
	Factor_3(Factor)
{
	if (!ZFde0NodeList) ZFde0NodesInit() ;
	ZFde0NodeList->Append(MakeDeclaredEntity(this, IntEntZFde0)) ;
	InitArithType(TheArithType);
	NewMenuItem("ZFde0",GetName());
#line 49 "../fde0.usr"
 
	ean = an = Time1 ;
	eanm1 = anm1 = Time0 ;
	factor = Factor ;
	state = OK ;
#line 37 "../fde0.cxx"
} // end constructor

ZFde0::~ZFde0()
{
	TheMenuServer->DeleteMenuItem("ZFde0",GetName());
	ZFde0NodeList->Delete(GetName()) ;
} // end destructor

int ZFde0::CheckSafeDelete()
{
	int Safe_Check_Return = DfNode::CheckSafeDelete();
	if (!Safe_Check_Return) return 0;
	return 1;
} // end check safe delete

ZFde0 * ZFde0Def;

ErrCode ZFde0::DoNode(int32 k)
{
#line 73 "../fde0.usr"
 
	if (state < EndOfData) for (int32 i = 0 ; i < k ; i++ ) {
		double enew = factor * ean -eanm1 ;
		eanm1 = ean ;
		ean = enew ;
		double truncate = factor * an;
		int32 to_add ;
		if (truncate < 0) {
			to_add = (int32) -truncate ;
			to_add = - to_add ;
		} else to_add = (int) truncate ;
		int32 anew =  to_add - anm1 ;
		anm1 = an ;
		an = anew ;
		WriteInteger(an);
		WriteInteger((int)ean);
		if (an == GetTime1() && anm1 == GetTime0()) {
			state = EndOfData ;
			break ;
		}
		
	}
	return state ;
#line 81 "../fde0.cxx"
} // end kernel code

static UserEntity * MakeZFde0(OutTokens& Out, EntityReq Request,
	InteractiveEntity& IntNode,
	ArithType::ArithCapabilities arith = (ArithType::ArithCapabilities) TheArithType) ;
int ZFde0::CppList(OutTokens& Out, CppListCmds Cmd)
{
	return IntEntZFde0->CppList(Out,Cmd,this);
}

void ZFde0::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeZFde0(Out,EntityReqDescribeFull,*IntEntZFde0, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("Time0");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetTime0()));
		Out.NextFillOut(")");
		Out.NextFillOut("is the first of two samples that (along with the");
		Out.NextFillOut("frequency coefficient) that determine the time sequence.");
		Out.NextQuoteOut("Time1");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetTime1()));
		Out.NextFillOut(")");
		Out.NextFillOut("is the second of two samples that (along with the");
		Out.NextFillOut("frequency coefficient) that determine the time sequence.");
		Out.NextQuoteOut("Factor");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetFactor()));
		Out.NextFillOut(")");
		Out.NextFillOut("determines the frequency of the exact solution of");
		Out.NextFillOut("the difference equation and the approximate frequency of");
		Out.NextFillOut("the iterated solution.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntZFde0->GetOneParameter("Time0")->
			IntP->CurrentValue = Time0_1;
		IntEntZFde0->GetOneParameter("Time1")->
			IntP->CurrentValue = Time1_2;
		IntEntZFde0->GetOneParameter("Factor")->
			FloatP->CurrentValue = Factor_3;
		break;
	}
} // end  list entity switch

void ZFde0NodesInit()
{
	if (ZFde0NodeList)  return ;

	static StringParam ZFde0NameParam =
		{"ZFde0", MakeNewEntityName, 0, LegalEntityName};
	static IntParam ZFde0Time0Param = {
		 0, 0, 0, -2.14748e+09, 0, 2.14748e+09};
	static IntParam ZFde0Time1Param = {
		 1000, 0, 0, -2.14748e+09, 0, 2.14748e+09};
	static FloatParam ZFde0FactorParam = {
		 .25, 0, 0, -1e+100, 0, 1e+100};

	static OneParameter ZFde0ParArray[] = {
		{"Name", 0, "node name", 0, 0, &ZFde0NameParam},
		{"Time0", 0, 
			"sequence value at time 0",
			&ZFde0Time0Param},
		{"Time1", 0, 
			"sequence value at time 1",
			&ZFde0Time1Param},
		{"Factor", 0, 
			"Factor determines the frequency of the solution",
			0, &ZFde0FactorParam},
		{0}
	};

	ZFde0NodeList = new EntityList;
	IntEntZFde0 = new InteractiveEntity("ZFde0", ZFde0NodeList,
		MakeZFde0, InteractiveNode, "fde0.h",
		0, "Signal");
	IntEntZFde0->SetParameters(new UserParameters(ZFde0ParArray));
	TheNodes->Append(IntEntZFde0);
} // end initalization

static UserEntity * MakeZFde0(OutTokens& Out, EntityReq Request,
	InteractiveEntity& IntNode,
	ArithType::ArithCapabilities arith)
{
	switch(Request) {
case EntityReqDescribe:

case EntityReqDescribeFull:
		Out.NextQuoteOut("ZFde0");
		Out.NextFillOut("generates outputs form a discretized and exact finite");
		Out.NextFillOut("difference equation. The discretized solution is output as");
		Out.NextFillOut("the real part and the exact solution as the imaginary part.");
		Out.NextFillOut("This is intended as a demonstration of the combinatorial");
		Out.NextFillOut("complexity of the discretized finite difference equation");
		Out.NextFillOut("as compared to the continuous solution. The output stops");
		Out.NextFillOut("once the initial state is repeated.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		int32 Time0 =
			IntNode.GetIntParameterValue("Time0");
		int32 Time1 =
			IntNode.GetIntParameterValue("Time1");
		double Factor =
			IntNode.GetFloatParameterValue("Factor");
		return new ZFde0(Name, Time0, Time1, Factor);

	}
	}
	return 0;
}

static InitObj LocalInit(ZFde0NodesInit, "ZFde0", "Signal");

