/**************************************************************************/
/**************************************************************************/
/*
apdith.c: This file contains the analysis code for doing the CSX proprietary
	APCM scaling and error adjustments on the Pre-emph data for CSXC.
	This file contains the addition of dither to the non-dithered
	algorithm. The file aperr.c has non-dithered apcm.
*/
/**************************************************************************/
/*
Copyright, 1995 Atari Corporation.
Written for Atari by Highlight Software Solutions.
*/
/**************************************************************************/

#include "hdef.h"	/* this file contains the data types and constants. */



/**************************************************************************/
/*
Function: daperr

definition:
	This function implements a scaling multiply with error adjusting
	on a block of data. The calling parameters contain the number
	of word elements to be processed from an input buffer, the
	scale factor, an initial error value if needed, and a destination
	buffer.
arguments:
	num: contains the number of word elements to scale.
	sf: contains the scale factor as a 16 bit unsigned integer.
	eval: contains a pointer to a starting error value. The
		function returns the ending error value to this location.
	from: the source buffer.
	to: the destination buffer.
	rparam: this is a pointer to the random number seed. It is modified
	on return to the latest seed.
-------------------------------------------------------
returns:
	an HINT that is currently not meaningful
-------------------------------------------------------
example:
aperr(256, 500, &errval, datain, dataout,&rand);
calls this function to scale each of the 256 elements at datain by a
factor of 500/32767 with the errval passed in *errval and places the
results in dataout. The random number seed is in rand. The new seed is
returned in rand.

*/
/**************************************************************************/

HINT daperr(HINT num, HWORD sf, LPHLONG eval, LPHINT from, LPHINT to, LPHWORD rparam)
{
HINT	i;
HLONG	errsav;
HLONG   p, acc;
HLONG	te;
HWORD	rand;
double	tester;

	errsav = *eval;
	rand = *rparam;
	for (i = 0; i < num; i++) {
		get_rand(&rand);
		p = ((HLONG) from[i]) * ((HLONG) sf);
		tester = ((double) p) + ((double) errsav) + ((double) rand);
		if ((tester > ((double) ((long) 0x7fffffff))) ||
			(tester < ((double) ((long) 0x80000000)))) {
			printf(" Error:%f ",tester);
		}
		acc = p + errsav + (rand>>1);
		te = acc - ((HLONG) acc - (HLONG) (acc & ((HLONG)0x0000ffff)));
        	errsav = te;
                to[i] = (HINT) ((acc & 0xffff0000) >> 16);
	}
	*rparam = rand;
	*eval = errsav;
return(0);
}


HINT get_rand(LPHWORD inm)
{
HLONG acc;
HWORD	temp;
HWORD	mnum = 947;

acc = ((HLONG) mnum) * ((HLONG) *inm);
if (acc <= 0L) {
	acc += ((HLONG) (((HLONG) mnum) << 16));
}
temp = (HWORD) ((acc >> 16) & 0x0000ffff);
acc = (acc & 0x0000ffff) - temp;
if (acc <= 0L) {
	acc+=1;
}
*inm = (HWORD) acc & 0x0000ffff;
return(0);
} /* end of get_rand */

