aboutsummaryrefslogtreecommitdiff
path: root/src/benchmarks/cfrac/pimod.c
blob: b26536d3c7dff3e2f42c173900a9fc9fa3bff29a (plain)
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
#include "pdefs.h"
#include "precision.h"
#ifdef ASM_16BIT
#include "asm16bit.h"
#endif

/*
 * Single-digit remainder
 */
int pimod(u, v)
   register precision u;
   int 	    v;
{
#ifndef ASM_16BIT
   register digitPtr	uPtr;
   register accumulator temp;		       /* 0 <= temp < base^2 */
#endif
   register digit	r = 0, d;		/* 0 <= r,d < base */
   register int res = 0;

   (void) pparm(u);
   if (v < 0) d = (digit) -v; else d = (digit) v;
   if (d >= BASE) {
      errorp(PDOMAIN, "pimod", "divisor too big for single digit");
      goto done;
   } 
   if (d == 0) {
      errorp(PDOMAIN, "pimod", "divide by zero");
      goto done;
   } 
#ifndef ASM_16BIT
   uPtr = u->value + u->size;
   r    = 0;			  	/* r is current remainder */
   do {
       temp  = mulBase(r);		/* 0 <= temp <= (base-1)^2 */
       temp += *--uPtr;			/* 0 <= temp <= base(base-1) */
       r     = temp % d; 		/* 0 <= r < base */
   } while (uPtr > u->value);
#else
   r = memmodw1(u->value, u->size, d);
#endif

   res = (int) r;
   if (u->sign) res = -res;
done:
   pdestroy(u);
   return res;
}