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

#include "ObjProUsr/fde1.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 * ZFde1NodeList = 0 ;
static InteractiveEntity * IntEntZFde1 ;
void ZFde1NodesInit();
ZFde1::ZFde1 (const char * Name, double Factor, int32 Interval, int32 MaxSize, 
		int32 * Time0, int32 Time0_Length, int32 * Time1, 
		int32 Time1_Length, int32 DoubMaxSteps, int32 DiscrScheme):
	Signal(Name, 1, 2, 1, 1, TimingTypeLinear, 
	(ArithType::ArithCapabilities)(TheArithType == ArithType::ArithInt16 ? TheArithType : ArithType::ArithInt32))
,
	Factor_1(Factor),
	Interval_2(Interval),
	MaxSize_3(MaxSize),
	Time0_4(Time0),
	Time0_Length_5(Time0_Length),
	Time1_6(Time1),
	Time1_Length_7(Time1_Length),
	DoubMaxSteps_8(DoubMaxSteps),
	DiscrScheme_9(DiscrScheme),
	sim(0)
{
	if (!ZFde1NodeList) ZFde1NodesInit() ;
	ZFde1NodeList->Append(MakeDeclaredEntity(this, IntEntZFde1)) ;
	InitArithType(TheArithType);
	NewMenuItem("ZFde1",GetName());
#line 104 "../fde1.usr"
 
	state = OK ;
	sim = new Fde1Sim(*this);
#line 44 "../fde1.cxx"
} // end constructor

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

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

ZFde1 * ZFde1Def;

ErrCode ZFde1::DoNode(int32 k)
{
#line 124 "../fde1.usr"
 
	if (state < EndOfData) state = sim->simulate(k);
	return state ;
#line 68 "../fde1.cxx"
} // end kernel code

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

void ZFde1::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeZFde1(Out,EntityReqDescribeFull,*IntEntZFde1, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("Factor");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetFactor()));
		Out.NextFillOut(")");
		Out.NextFillOut("determines the velocity of propagation in the");
		Out.NextFillOut("the difference equation");
		Out.NextFillOut("Every");
		Out.NextQuoteOut("Interval");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetInterval()));
		Out.NextFillOut(")");
		Out.NextFillOut("time steps an output is generated. Only");
		Out.NextFillOut("values between the first and last nonzero value are displayed.");
		Out.NextQuoteOut("MaxSize");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetMaxSize()));
		Out.NextFillOut(")");
		Out.NextFillOut("is the maximum array size or the maximum length");
		Out.NextFillOut("and initial disturbance can spread out.");
		Out.NextQuoteOut("Time0");
		Out.NextFillOut("is the array of values at the first time step.");
		Out.NextQuoteOut("Time1");
		Out.NextFillOut("is the array of values at the first time step.");
		Out.NextQuoteOut("DoubMaxSteps");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetDoubMaxSteps()));
		Out.NextFillOut(")");
		Out.NextFillOut("limits the number of steps for the");
		Out.NextFillOut("double simulation. This can be decreased to turn off");
		Out.NextFillOut("simulation but not increased. If it is 0 initially no");
		Out.NextFillOut("double array will be declared.");
		Out.NextQuoteOut("DiscrScheme");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetDiscrScheme()));
		Out.NextFillOut(")");
		Out.NextFillOut("selects the discretization scheme.");
		Out.NextFillOut("The default (0) truncates towards 0.");
		Out.NextFillOut("1 rounds up to the largest magnitude integer value.");
		Out.NextFillOut("2 does conventional rounding.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntZFde1->GetOneParameter("Factor")->
			FloatP->CurrentValue = Factor_1;
		IntEntZFde1->GetOneParameter("Interval")->
			IntP->CurrentValue = Interval_2;
		IntEntZFde1->GetOneParameter("MaxSize")->
			IntP->CurrentValue = MaxSize_3;
		IntEntZFde1->GetOneParameter("Time0")->
			ArrayP->CurrentValue = 
		(new ArrayData)->SetArrayData(Time0_Length_5, DecInt, Time0_4);
		IntEntZFde1->GetOneParameter("Time1")->
			ArrayP->CurrentValue = 
		(new ArrayData)->SetArrayData(Time1_Length_7, DecInt, Time1_6);
		IntEntZFde1->GetOneParameter("DoubMaxSteps")->
			IntP->CurrentValue = DoubMaxSteps_8;
		IntEntZFde1->GetOneParameter("DiscrScheme")->
			IntP->CurrentValue = DiscrScheme_9;
		break;
	}
} // end  list entity switch

static ValueType * SetInterval(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				int32 Interval =
			Param->GetIntParameterValue("Interval");
		((ZFde1 *) This)->SetInterval(Interval);
		return 0 ;
	}
	}
	return 0;
}

static ValueType * SetDoubMaxSteps(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				int32 DoubMaxSteps =
			Param->GetIntParameterValue("DoubMaxSteps");
		((ZFde1 *) This)->SetDoubMaxSteps(DoubMaxSteps);
		return 0 ;
	}
	}
	return 0;
}

static ValueType * SetDiscrScheme(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				int32 DiscrScheme =
			Param->GetIntParameterValue("DiscrScheme");
		((ZFde1 *) This)->SetDiscrScheme(DiscrScheme);
		return 0 ;
	}
	}
	return 0;
}

int32 TheDataForZFde1Time0DefaultArray[] = {

		10, 100, 10
	};

	static ArrayData ZFde1Time0DefaultArray = { 3, DecInt,
		(void *) TheDataForZFde1Time0DefaultArray};

int32 TheDataForZFde1Time1DefaultArray[] = {

		10, 100, 10
	};

	static ArrayData ZFde1Time1DefaultArray = { 3, DecInt,
		(void *) TheDataForZFde1Time1DefaultArray};

void ZFde1NodesInit()
{
	if (ZFde1NodeList)  return ;

	static StringParam ZFde1NameParam =
		{"ZFde1", MakeNewEntityName, 0, LegalEntityName};
	static FloatParam ZFde1FactorParam = {
		 .6, 0, 0, -1e+100, 0, 1e+100};
	static IntParam ZFde1IntervalParam = {
		 100, 0,  0,  1,  0,  100000};
	static IntParam ZFde1MaxSizeParam = {
		 100000, 0,  0,  10000,  0,  1000000};
	static int32 ZFde1Time0LowerArrayBound =
		-2147483647 ;

	static int32 ZFde1Time0UpperArrayBound =
		2147483647 ;

	static ArrayParam ZFde1Time0Param = {
		DecInt, &ZFde1Time0DefaultArray,
		0, 0, (void *) &ZFde1Time0LowerArrayBound, 0,
		(void *) &ZFde1Time0UpperArrayBound, 1, 10000};
	static int32 ZFde1Time1LowerArrayBound =
		-2147483647 ;

	static int32 ZFde1Time1UpperArrayBound =
		2147483647 ;

	static ArrayParam ZFde1Time1Param = {
		DecInt, &ZFde1Time1DefaultArray,
		0, 0, (void *) &ZFde1Time1LowerArrayBound, 0,
		(void *) &ZFde1Time1UpperArrayBound, 1, 10000};
	static IntParam ZFde1DoubMaxStepsParam = {
		 100000000, 0,  0,  0, 0, 2.14748e+09};
	static IntParam ZFde1DiscrSchemeParam = {
		 0, 0,  0,  0, 0, 2.14748e+09};

	static OneParameter ZFde1ParArray[] = {
		{"Name", 0, "node name", 0, 0, &ZFde1NameParam},
		{"Factor", 0, 
			"`Factor' determines the velocity of propagation",
			0, &ZFde1FactorParam},
		{"Interval", 0, 
			"an output is generated every `Interval' time steps",
			&ZFde1IntervalParam},
		{"MaxSize", 0, 
			"`MaxSize' is the maximum array size",
			&ZFde1MaxSizeParam},
		{"Time0", 0, 
			"values at time step 0",
			0, 0, 0, 0,
			&ZFde1Time0Param, 1},

		{"Time1", 0, 
			"values at time step 1",
			0, 0, 0, 0,
			&ZFde1Time1Param, 1},

		{"DoubMaxSteps", 0, 
			"maximum time steps for double simulation",
			&ZFde1DoubMaxStepsParam, 0, 0, 0, 0, 1},
		{"DiscrScheme", 0, 
			"select discretization scheme",
			&ZFde1DiscrSchemeParam, 0, 0, 0, 0, 1},
		{0}
	};

	static OneParameter SetIntervalZFde1List[] = {
		{"Interval", 0, "an output is generated every `Interval' time steps",
			 &ZFde1IntervalParam},
			{0}
	};
	UserParameters * SetIntervalMemberParam = new UserParameters
		(SetIntervalZFde1List);

	Procedure * SetMemberProcInterval = new Procedure("SetInterval", SetInterval,
		 SetIntervalMemberParam, "void");
	static OneParameter SetDoubMaxStepsZFde1List[] = {
		{"DoubMaxSteps", 0, "maximum time steps for double simulation",
			 &ZFde1DoubMaxStepsParam, 0, 0, 0, 0, 1},
			{0}
	};
	UserParameters * SetDoubMaxStepsMemberParam = new UserParameters
		(SetDoubMaxStepsZFde1List);

	Procedure * SetMemberProcDoubMaxSteps = new Procedure("SetDoubMaxSteps", SetDoubMaxSteps,
		 SetDoubMaxStepsMemberParam, "void");
	static OneParameter SetDiscrSchemeZFde1List[] = {
		{"DiscrScheme", 0, "select discretization scheme",
			 &ZFde1DiscrSchemeParam, 0, 0, 0, 0, 1},
			{0}
	};
	UserParameters * SetDiscrSchemeMemberParam = new UserParameters
		(SetDiscrSchemeZFde1List);

	Procedure * SetMemberProcDiscrScheme = new Procedure("SetDiscrScheme", SetDiscrScheme,
		 SetDiscrSchemeMemberParam, "void");
static ValueType * ZFde1Members[4] ;
	int ii = 0 ;
	ZFde1Members[ii++] = new ValueType(DecProcedure, SetMemberProcInterval) ;
	ZFde1Members[ii++] = new ValueType(DecProcedure, SetMemberProcDoubMaxSteps) ;
	ZFde1Members[ii++] = new ValueType(DecProcedure, SetMemberProcDiscrScheme) ;
	ZFde1Members[ii++] = 0 ;
	ZFde1NodeList = new EntityList;
	IntEntZFde1 = new InteractiveEntity("ZFde1", ZFde1NodeList,
		MakeZFde1, InteractiveNode, "fde1.h",
		ZFde1Members, "Signal");
	IntEntZFde1->SetParameters(new UserParameters(ZFde1ParArray));
	TheNodes->Append(IntEntZFde1);
} // end initalization

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

case EntityReqDescribeFull:
		Out.NextQuoteOut("ZFde1");
		Out.NextFillOut("generates outputs form a 1 dimensional finite difference");
		Out.NextFillOut("approximation to the wave equation. Each step generates a linear");
		Out.NextFillOut("array of outputs as a function of the two previous linear arrays.");
		Out.NextFillOut("The initial disturbance");
		Out.NextFillOut("will spread in space until it reaches the boundaries of a predefined");
		Out.NextFillOut("array. At that point the output stops. This example illustrates");
		Out.NextFillOut("some of the properties of discretized finite difference equations.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		double Factor =
			IntNode.GetFloatParameterValue("Factor");
		int32 Interval =
			IntNode.GetIntParameterValue("Interval");
		int32 MaxSize =
			IntNode.GetIntParameterValue("MaxSize");
		int32 * Time0 =
			(int32 *  ) IntNode.GetArrayParameterValue("Time0");
		int32 Time0_Length =
			IntNode.GetLengthArrayParameterValue("Time0");
		int32 * Time1 =
			(int32 *  ) IntNode.GetArrayParameterValue("Time1");
		int32 Time1_Length =
			IntNode.GetLengthArrayParameterValue("Time1");
		int32 DoubMaxSteps =
			IntNode.GetIntParameterValue("DoubMaxSteps");
		int32 DiscrScheme =
			IntNode.GetIntParameterValue("DiscrScheme");
		return new ZFde1(Name, Factor, Interval, MaxSize, Time0, Time0_Length, Time1, Time1_Length, DoubMaxSteps, DiscrScheme);

	}
	}
	return 0;
}

static InitObj LocalInit(ZFde1NodesInit, "ZFde1", "Signal");

