#include "integ.h"
#include "ObjProArithGen/artherr.h"
#include "cgidbg.h"


void Integrate::ctor()
{
    NumberOfOverflows = 0;
    ArraySize = 0 ;
    Sums = 0 ;
    ElementSize = 0 ;
    first_index_used = 0 ;
    last_index_used = 0 ;
	total_samples = 0 ;
	if (GetIntegrationSize() == 0) {
		NextOut = GetOutputStep() ;
		NumberOutputSums = 1 ;
		skip_data = 2 ;
		need_new_index = 0 ;
		size = 1 ;
		return ;
	}
    NextOut = GetIntegrationSize() ; 
    need_new_index = GetOutputStep()  ;
    NumberOutputSums = (GetIntegrationSize() + GetOutputStep() -1) /
        GetOutputStep() ;
	skip_data = GetOutputStep() > GetIntegrationSize();
    update_size();
}

void Integrate::dtor()
{
	delete Sums ;
}


void Integrate::update_size()
{
	int last = last_index_used ;
	if (last < first_index_used) last += NumberOutputSums ;
    size = last - first_index_used + 1 ;
}

ErrCode Integrate::kernel(int32 k)
{
	if (!Sums) {
		ElementSize = GetEltSize();
		ArraySize = NumberOutputSums * ElementSize ;
		Sums = new double [ArraySize] ;
		for (int i = 0 ; i < ArraySize;i++) Sums[i] = 0 ;
	}
	int32 SaveOverflows = NumberOfOverflows ;
	for (int32 i = 0 ; i < k ; i++ )
	  for (int32 b = 0 ; b < GetBlockSize() ; b++) {
		total_samples += 1 ;
		for (int  j = 0 ; j < ElementSize; j++) {
			MachWord Next = ReadWord() ;
			for (int s = 0 ; s < size; s++ ) {
				int ss = s + first_index_used ;
				if (ss >= NumberOutputSums) ss -= NumberOutputSums ;
					Sums[ss*ElementSize+j] += (double) Next ;
			}
		}
		if (skip_data !=2) if (--need_new_index <= 0) {
			last_index_used++ ;
			if (last_index_used >= NumberOutputSums) last_index_used = 0 ;
			need_new_index = GetOutputStep() ;
			update_size();
		}
		if (--NextOut  > 0) continue ;
		for (j = 0; j < ElementSize;j++) {
			double scaled_sum = Sums[first_index_used*ElementSize+j] *
                GetScale();
			if (skip_data == 2) scaled_sum /= total_samples ;
			else Sums[first_index_used*ElementSize+j] = 0.0 ;
			WriteWord(check_overflow(scaled_sum,NumberOfOverflows));
		}
		if (skip_data != 2) {
			first_index_used++ ;
			if (first_index_used >= NumberOutputSums) first_index_used = 0 ;
			NextOut = GetOutputStep() ;
			if (skip_data==1) size = 0 ;
			else update_size();
		}
	}
	if (NumberOfOverflows > SaveOverflows) ReportOverflows(
		NumberOfOverflows, SaveOverflows,GetName());
	return OK ;
}

