#include "ObjProDSP/portable.h"
#include "ObjProGen/genrand.h"
#include "ObjProArith/hrdarth.h"
#include "ObjProArithGen/artherr.h"
#include "ObjProArithGen/arthfnc.h"
#include "ObjProComGui/cgidbg.h"
#include "ObjProDSPcom/myrand.h"
#include <stdlib.h>
#include <limits.h>
#include "ObjProGui/sigintfc.h"
#include "ObjProNet/dfnode.h"

#include "ObjProUsr/unnoise.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 * UniformNoiseNodeList = 0 ;
static InteractiveEntity * IntEntUniformNoise ;
void UniformNoiseNodesInit();
UniformNoise::UniformNoise (const char * Name, double Maximum, double Minimum, 
		int16 ElementSize, int32 Seed):
	Signal(Name, 1, ElementSize, 1, 1, TimingTypeLinear, 
	(ArithType::ArithCapabilities)ArithType::ArithTypeUndefined)
,
	Maximum_1(Maximum),
	Minimum_2(Minimum),
	ElementSize_3(ElementSize),
	Seed_4(Seed)
{
	if (!UniformNoiseNodeList) UniformNoiseNodesInit() ;
	UniformNoiseNodeList->Append(MakeDeclaredEntity(this, IntEntUniformNoise)) ;
	InitArithType(TheArithType);
	NewMenuItem("UniformNoise",GetName());
#line 88 "../unnoise.usr"
 
#ifndef __NT_VC__ 
	state = (char *) new int32[state_size >> 2] ;
	for (int i = 0 ; i < state_size;i++) state[i] = 0 ;
	char * save_state = (char *) initstate(GetSeed(),state,state_size);
	setstate(save_state);
#endif
#line 49 "../unnoise.cxx"
} // end constructor

UniformNoise::~UniformNoise()
{
	TheMenuServer->DeleteMenuItem("UniformNoise",GetName());
	UniformNoiseNodeList->Delete(GetName()) ;
#line 97 "../unnoise.usr"
 
	delete state ;
#line 59 "../unnoise.cxx"
} // end destructor

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

double UniformNoise::TimeFirst( DfNodeInLink * , DfNodeOutLink * )
{
#line 118 "../unnoise.usr"
	return 0.0 ;
#line 73 "../unnoise.cxx"
} // end timing code

UniformNoise * UniformNoiseDef;

ErrCode UniformNoise::DoNode(int32 k)
{
#line 126 "../unnoise.usr"
 
	// this gives the same sequence even if multiple processes use random
#ifndef __NT_VC__
	char * save_state = (char *) setstate(state);
#endif
	double ScaleFactor = (GetMaximum() - GetMinimum())/INT_MAX;
	for (int32 i = 0 ; i < k ; i++ ) {
		for (int j = 0 ; j < GetElementSize(); j++) {
			WriteWord((MachWordCast) (
#ifndef __NT_VC__
				random()
#else
				rand()
#endif
				* ScaleFactor + GetMinimum()));
		}
	}
#ifndef __NT_VC__
	setstate(save_state);
#endif
	return OK ;
#line 102 "../unnoise.cxx"
} // end kernel code

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

void UniformNoise::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeUniformNoise(Out,EntityReqDescribeFull,*IntEntUniformNoise, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("Maximum");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetMaximum()));
		Out.NextFillOut(")");
		Out.NextFillOut("is the largest value of uniformly distributed");
		Out.NextFillOut("noise.");
		Out.NextQuoteOut("Minimum");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetMinimum()));
		Out.NextFillOut(")");
		Out.NextFillOut("is the smallest value of uniformly distributed");
		Out.NextFillOut("noise. Most commonly");
		Out.NextQuoteOut("Minimum");
		Out.NextFillOut("= -");
		Out.NextQuoteOut("Maximum");
		Out.NextFillOutConcat(".");
		Out.NextQuoteOut("ElementSize");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetElementSize()));
		Out.NextFillOut(")");
		Out.NextFillOut("specifies the number of words in a single sample.");
		Out.NextFillOut("It is most commonly 1 for real data or 2 for complex data.");
		Out.NextQuoteOut("Seed");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetSeed()));
		Out.NextFillOut(")");
		Out.NextFillOut("seeds the random number generator. Each object instance");
		Out.NextFillOut("maintains a separate history state for the random number");
		Out.NextFillOut("generator. If the same");
		Out.NextFillOut("value of");
		Out.NextQuoteOut("Seed");
		Out.NextFillOut("is used in different object instances");
		Out.NextFillOut("they will generate the same.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntUniformNoise->GetOneParameter("Maximum")->
			FloatP->CurrentValue = Maximum_1;
		IntEntUniformNoise->GetOneParameter("Minimum")->
			FloatP->CurrentValue = Minimum_2;
		IntEntUniformNoise->GetOneParameter("ElementSize")->
			IntP->CurrentValue = ElementSize_3;
		IntEntUniformNoise->GetOneParameter("Seed")->
			IntP->CurrentValue = Seed_4;
		break;
	}
} // end  list entity switch

static ValueType * SetMaximum(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				double Maximum =
			Param->GetFloatParameterValue("Maximum");
		((UniformNoise *) This)->SetMaximum(Maximum);
		return 0 ;
	}
	}
	return 0;
}

static ValueType * SetMinimum(OutTokens&,EntityReq Request,
		UserParameters * Param,UserEntity *This) 
{
	switch (Request) {
case EntityReqDescribe:
	break ;
case EntityReqDescribeFull:
	break ;
case EntityReqCall:
		{		// Call procedure
				double Minimum =
			Param->GetFloatParameterValue("Minimum");
		((UniformNoise *) This)->SetMinimum(Minimum);
		return 0 ;
	}
	}
	return 0;
}

void UniformNoiseNodesInit()
{
	if (UniformNoiseNodeList)  return ;

	static StringParam UniformNoiseNameParam =
		{"UniformNoise", MakeNewEntityName, 0, LegalEntityName};
	static FloatParam UniformNoiseMaximumParam = {
		 1024.0, 0, 0, -1e+100, 0, 1e+100};
	static FloatParam UniformNoiseMinimumParam = {
		 -1024.0, 0, 0, -1e+100, 0, 1e+100};
	static IntParam UniformNoiseElementSizeParam = {
		 1, 0,  0,  1, 0, 32767};
	static IntParam UniformNoiseSeedParam = {
		 1, 0,  0,  0, 0, 2.14748e+09};

	static OneParameter UniformNoiseParArray[] = {
		{"Name", 0, "node name", 0, 0, &UniformNoiseNameParam},
		{"Maximum", 0, 
			"largest value of uniformly distributed noise",
			0, &UniformNoiseMaximumParam},
		{"Minimum", 0, 
			"smallest value of uniformly distributed noise",
			0, &UniformNoiseMinimumParam},
		{"ElementSize", 0, 
			"number of words in one sample",
			&UniformNoiseElementSizeParam, 0, 0, 0, 0, 1},
		{"Seed", 0, 
			"random number generator seed",
			&UniformNoiseSeedParam, 0, 0, 0, 0, 1},
		{0}
	};

	static OneParameter SetMaximumUniformNoiseList[] = {
		{"Maximum", 0, "largest value of uniformly distributed noise",
			 0, &UniformNoiseMaximumParam},
			{0}
	};
	UserParameters * SetMaximumMemberParam = new UserParameters
		(SetMaximumUniformNoiseList);

	Procedure * SetMemberProcMaximum = new Procedure("SetMaximum", SetMaximum,
		 SetMaximumMemberParam, "void");
	static OneParameter SetMinimumUniformNoiseList[] = {
		{"Minimum", 0, "smallest value of uniformly distributed noise",
			 0, &UniformNoiseMinimumParam},
			{0}
	};
	UserParameters * SetMinimumMemberParam = new UserParameters
		(SetMinimumUniformNoiseList);

	Procedure * SetMemberProcMinimum = new Procedure("SetMinimum", SetMinimum,
		 SetMinimumMemberParam, "void");
static ValueType * UniformNoiseMembers[3] ;
	int ii = 0 ;
	UniformNoiseMembers[ii++] = new ValueType(DecProcedure, SetMemberProcMaximum) ;
	UniformNoiseMembers[ii++] = new ValueType(DecProcedure, SetMemberProcMinimum) ;
	UniformNoiseMembers[ii++] = 0 ;
	UniformNoiseNodeList = new EntityList;
	IntEntUniformNoise = new InteractiveEntity("UniformNoise", UniformNoiseNodeList,
		MakeUniformNoise, InteractiveSignal, "unnoise.h",
		UniformNoiseMembers, "Signal");
	IntEntUniformNoise->SetParameters(new UserParameters(UniformNoiseParArray));
	TheNodes->Append(IntEntUniformNoise);
	new UniformNoise("CxNormal", 128.0, 0.0, 2, 1);
} // end initalization

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

case EntityReqDescribeFull:
		Out.NextQuoteOut("UniformNoise");
		Out.NextFillOut("generates noise samples of");
		Out.NextQuoteOut("ElementSize");
		Out.NextFillOut("elements");
		Out.NextFillOut("from a uniform distribution. Set");
		Out.NextQuoteOut("ElementSize");
		Out.NextFillOut("to 1 for real");
		Out.NextFillOut("data or 2 for complex.");
		Out.NextFillOut("The values generated range between");
		Out.NextQuoteOut("Minimum");
		Out.NextFillOut("and");
		Out.NextQuoteOut("Maximum");
		Out.NextFillOutConcat(".");
		Out.NextQuoteOut("Seed");
		Out.NextFillOut("determines the sequence generated.");
		Out.NextFillOut("Each object instance maintains it a separate state for the");
		Out.NextFillOut("random number generator.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		double Maximum =
			IntNode.GetFloatParameterValue("Maximum");
		double Minimum =
			IntNode.GetFloatParameterValue("Minimum");
		int16 ElementSize =
			IntNode.GetIntParameterValue("ElementSize");
		int32 Seed =
			IntNode.GetIntParameterValue("Seed");
		return new UniformNoise(Name, Maximum, Minimum, ElementSize, Seed);

	}
	}
	return 0;
}

static InitObj LocalInit(UniformNoiseNodesInit, "UniformNoise", "Signal");

