#include <complex.h>
#include <signal.h>
#include "ObjProDSP/portable.h"
#include "ObjProComGui/cgidbg.h"
#include "ObjProGen/gcd.h"
#include "ObjProGen/nbits.h"
#include "ObjProGui/yacintfc.h"
#include "ObjProNet/dfnode.h"

#include "ObjProUsr/repackstr.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 * RepackStreamNodeList = 0 ;
static InteractiveEntity * IntEntRepackStream ;
void RepackStreamNodesInit();
RepackStream::RepackStream (const char * Name, int16 OutputWordSize, int16 InputWordSize, 
		int16 SignedOutput):
	ProcessNode(Name, 1, 1, 1, 0, 
	OutputWordSize / GreatestCommonDivisor(OutputWordSize , InputWordSize), 
	InputWordSize / GreatestCommonDivisor(OutputWordSize , InputWordSize), 0, 0, 0, 0, TimingTypeLinear, ArithType::ArithCapabilityAnyInt, 
	ArithType::ArithCapabilityAnyInt)
,
	OutputWordSize_1(OutputWordSize),
	InputWordSize_2(InputWordSize),
	SignedOutput_3(SignedOutput)
{
	if (!RepackStreamNodeList) RepackStreamNodesInit() ;
	RepackStreamNodeList->Append(MakeDeclaredEntity(this, IntEntRepackStream)) ;
	InitArithType(TheArithType);
	NewMenuItem("RepackStream",GetName());
#line 103 "../repackstr.usr"
 
	ctor();
#line 42 "../repackstr.cxx"
} // end constructor

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

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

RepackStream * RepackStreamDef;

ErrCode RepackStream::DoNode(int32 k)
{
#line 142 "../repackstr.usr"
 
	return kernel(k);
#line 65 "../repackstr.cxx"
} // end kernel code

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

void RepackStream::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeRepackStream(Out,EntityReqDescribeFull,*IntEntRepackStream, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("OutputWordSize");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetOutputWordSize()));
		Out.NextFillOut(")");
		Out.NextFillOut("is the number of bits in each output");
		Out.NextFillOut("word. The output is treated as a continuous stream of bits");
		Out.NextFillOut("made up of the least significant");
		Out.NextQuoteOut("OutputWordSize");
		Out.NextFillOut("bits");
		Out.NextFillOut("from each physical output word.");
		Out.NextQuoteOut("InputWordSize");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetInputWordSize()));
		Out.NextFillOut(")");
		Out.NextFillOut("is the number of bits in the input");
		Out.NextFillOut("word. The input is treated as a continuous stream of bits");
		Out.NextFillOut("made up of the least significant");
		Out.NextQuoteOut("OutputWordSize");
		Out.NextFillOut("bits");
		Out.NextFillOut("from each physical output word.");
		Out.NextFillOut("If");
		Out.NextQuoteOut("SignedOutput");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetSignedOutput()));
		Out.NextFillOut(")");
		Out.NextFillOut("is set the output will be written as a signed");
		Out.NextFillOut("two's compliment value in the full physical word size.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntRepackStream->GetOneParameter("OutputWordSize")->
			IntP->CurrentValue = OutputWordSize_1;
		IntEntRepackStream->GetOneParameter("InputWordSize")->
			IntP->CurrentValue = InputWordSize_2;
		IntEntRepackStream->GetOneParameter("SignedOutput")->
			IntP->CurrentValue = SignedOutput_3;
		break;
	}
} // end  list entity switch

void RepackStreamNodesInit()
{
	if (RepackStreamNodeList)  return ;

	static StringParam RepackStreamNameParam =
		{"RepackStream", MakeNewEntityName, 0, LegalEntityName};
	static IntParam RepackStreamOutputWordSizeParam = {
		 8, 0,  0,  1,  0,  32};
	static IntParam RepackStreamInputWordSizeParam = {
		 1, 0,  0,  1,  0,  32};
	static IntParam RepackStreamSignedOutputParam = {
		 0, 0,  0,  0,  0,  1};

	static OneParameter RepackStreamParArray[] = {
		{"Name", 0, "node name", 0, 0, &RepackStreamNameParam},
		{"OutputWordSize", 0, 
			"size in bits of output word",
			&RepackStreamOutputWordSizeParam},
		{"InputWordSize", 0, 
			"size in bits of input word",
			&RepackStreamInputWordSizeParam},
		{"SignedOutput", 0, 
			"option(1) to treat output as signed two's compliment value",
			&RepackStreamSignedOutputParam},
		{0}
	};

	RepackStreamNodeList = new EntityList;
	IntEntRepackStream = new InteractiveEntity("RepackStream", RepackStreamNodeList,
		MakeRepackStream, InteractiveNode, "repackstr.h",
		0, "ProcessNode");
	IntEntRepackStream->SetParameters(new UserParameters(RepackStreamParArray));
	TheNodes->Append(IntEntRepackStream);
} // end initalization

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

case EntityReqDescribeFull:
		Out.NextQuoteOut("RepackStream");
		Out.NextFillOut("repacks a bit stream from");
		Out.NextFillOut("an input physical word size,");
		Out.NextQuoteOut("InputWordSize");
		Out.NextFillOut("to");
		Out.NextFillOut("an output physical word size,");
		Out.NextQuoteOut("OutputWordSize");
		Out.NextFillOutConcat(".");
		Out.NextFillOut("If");
		Out.NextQuoteOut("SignedOutput");
		Out.NextFillOut("is set the output will be written as a signed");
		Out.NextFillOut("two's compliment value in the full physical word size.");
		Out.NextFillOut("Both input and output");
		Out.NextFillOut("are treated as continuous bit streams made up of physical words");
		Out.NextFillOut("of the specified number of bits. The least significant physical");
		Out.NextFillOut("bits occur logically first in the continuous stream.");
		Out.NextFillOut("Logical words can cross physical word");
		Out.NextFillOut("boundaries on both the input and output streams.");
		Out.NextFillOut("One can use this to repack bit streams containing logical words of");
		Out.NextFillOut("any length to a different physical word size. One can also use");
		Out.NextFillOut("it to unpack a continuous stream of bits of any");
		Out.NextFillOut("logical word size (up to 32 bits) to a stream of one physical");
		Out.NextFillOut("output word for each each logical input word. Similarly on can");
		Out.NextFillOut("pack a stream of physical words into a continuous bit stream,");
		Out.NextFillOut("By setting");
		Out.NextQuoteOut("OutputWordSize");
		Out.NextFillOut("to the logical word size in the continuous input bit stream you unpack that");
		Out.NextFillOut("stream placing one logical input word in each physical output word.");
		Out.NextFillOut("By setting");
		Out.NextQuoteOut("InputWordSize");
		Out.NextFillOut("to the input logical word size");
		Out.NextFillOut("you pack an input stream that has one logical word in each");
		Out.NextFillOut("physical word into a continuous output bit stream.");
		Out.NextFillOut("Neither");
		Out.NextQuoteOut("InputWordSize");
		Out.NextFillOut("and");
		Out.NextQuoteOut("OutputWordSize");
		Out.NextFillOut("can be greater then the");
		Out.NextFillOut("physical word size. If either is the node will not be usable.");
		Out.NextFillOut("If");
		Out.NextQuoteOut("InputWordSize");
		Out.NextFillOut("is an exact multiple of");
		Out.NextQuoteOut("OutputWordSize");
		Out.NextFillOut("(or");
		Out.NextFillOut("vice versa)");
		Out.NextFillOut("`UnpackWord'");
		Out.NextFillOut("(");
		Out.NextFillOutConcat("`PackWord'");
		Out.NextFillOutConcat(") is a more efficient process");
		Out.NextFillOut("that does the same operation.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		int16 OutputWordSize =
			IntNode.GetIntParameterValue("OutputWordSize");
		int16 InputWordSize =
			IntNode.GetIntParameterValue("InputWordSize");
		int16 SignedOutput =
			IntNode.GetIntParameterValue("SignedOutput");
		return new RepackStream(Name, OutputWordSize, InputWordSize, SignedOutput);

	}
	}
	return 0;
}

static InitObj LocalInit(RepackStreamNodesInit, "RepackStream", "ProcessNode");

