divide.c 1.42 KB

#include "graphic.h"

#define INPUT_DATA 30
#define INPUT_MAX (1<<INPUT_DATA)
#define INPUT_MASK (INPUT_MAX-1)
#define ROM_ADRS 9
#define ROM_DATA 16
#define ROM_DEPTH (1<<ROM_ADRS)
#define ROM_WIDTH (1<<ROM_DATA)
static int rom[ROM_DEPTH];
static int rom_valid = FALSE;
/*---------------------------------------------*/
divide_seed( v, r)
int v, *r;
{
int neg = FALSE;
int shift;
int adrs;
int seed;
int result;
double recp;
double scal;
if (!rom_valid) { /* initialize rom to hidden MSB */
	int i;
	rom_valid = TRUE;
	rom[0] = ROM_WIDTH-1;	/* maximum value */
	for (i=1; i<ROM_DEPTH; i++) 
	 rom[i] = (int)((float)(ROM_WIDTH*ROM_DEPTH)/(ROM_DEPTH+i));
	}
/* abs(v) */
	if (v < 0) {
		v = ~v; neg = TRUE; }
/* find leading bit up to entire input in rom address */
	for (shift=1; shift<(INPUT_DATA); shift++)
		if (v & (1<<(INPUT_DATA-shift))) break;
	adrs = (v << shift) & INPUT_MASK;
	adrs = adrs >> (INPUT_DATA-ROM_ADRS);
	seed = rom[adrs];
	recp = (double)seed/ROM_WIDTH;
	scal = (double)DIV_RECP_FRAC*(1<<shift)/(1<<INPUT_DATA);
	recp = recp * scal;
	result = (int)recp;
	if (neg) result = ~result;
	*r = result;
}
/*---------------------------------------------*/
divide_newt( v, r, n)
int v, r, *n;
{
float recp;
float newt;
	recp = (float)r * ((float)1/DIV_RECP_FRAC);
/* newton-raphson iteration */
	newt = recp * ((float)2 - recp * (float)v);
	*n = (int)(newt * (float)DIV_RECP_FRAC);
}
/*---------------------------------------------*/