divide.c
1.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#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);
}
/*---------------------------------------------*/