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

void RepackStream::ctor()
{
	MaskIn = 1 ;
    for (int i = 1 ; i < GetInputWordSize(); i++)
        MaskIn = (MaskIn << 1) | 1 ;
    BitsLeftInWord = 0 ;
    min_word_size = GetInputWordSize();
    if (min_word_size < GetOutputWordSize()) min_word_size =
        GetOutputWordSize();

	fill_ones = 0 ;
	sign_bit = 1 << (GetOutputWordSize()-1) ;
	for (i = 0 ; i < 33 - GetOutputWordSize(); i++) fill_ones =
		(fill_ones <<  1) | sign_bit ;
}

ErrCode RepackStream::kernel(int32 k)
{
	if (State.IsError()) return FatalError ;
	if (err_state == FatalError) {
		State.Error("`",GetName(),"' is not useable");
		return FatalError ;
	} 
	int32 Limit = k * GetIncrementOut(0) ;
	// TheLog << "RepackStream::Kernel Limit = " << Limit << "\n" ;
	for (int32 i = 0 ; i < Limit ; i++ )  {
		BinMachWord out = GetNextOutWord() ;
		if (GetSignedOutput()) if (out & sign_bit) out |= fill_ones ;
		WriteInteger(out);
	}
	return OK ;
}



BinMachWord RepackStream::GetNextOutWord()
{
	int32 BitsLeftToWrite = GetOutputWordSize() ;
	BinMachWord Ret =  0 ;
	int BitsPerBinWord = sizeof(BinMachWord) * 8 ;
	for (;;) {
/*
 *		TheLog << "InWord = " << BitsLeftInWord << ", ToWrite = " <<
 *			BitsLeftToWrite << "\n" ;
 */
		if (BitsLeftInWord <= 0) {
			Word = ReadInteger() & MaskIn ;	
			BitsLeftInWord = GetInputWordSize();
		}
		// TheLog << "Word = 0x" << hex << Word << dec << "\n" ;
		// TheLog << "Ret = 0x" << hex << Ret << dec << "\n" ;

		int BitsUsed ;
		if (BitsLeftInWord >= BitsLeftToWrite)
			BitsUsed = BitsLeftToWrite ;
		else BitsUsed = BitsLeftInWord ;

		int Shift = BitsPerBinWord - BitsUsed ;
		BinMachWord Temp = Word << Shift ;
		Temp >>= Shift - GetOutputWordSize() + BitsLeftToWrite ;
		Ret |= Temp ;
		Word >>= BitsUsed ;
		BitsLeftInWord -= BitsUsed ;
		BitsLeftToWrite -= BitsUsed ;
		if (BitsLeftToWrite <= 0) {
			// TheLog<<"Returning 0x" <<hex<< Ret << dec << "\n" ;
			if (GetSignedOutput()) if (Ret & sign_bit) Ret |= fill_ones ;
			return Ret ;
		}
	}
	
}


