blob: 61c09a750caf0aea0fbd46cfe88ee7928085458c [file] [log] [blame]
#include "pdefs.h"
#include "precision.h"
#ifdef ASM_16BIT
#include "asm16bit.h"
#endif
/*
* Single-digit divide
*/
precision pidiv(u, v)
register precision u;
int v;
{
#ifndef ASM_16BIT
register digitPtr uPtr, qPtr;
register accumulator temp; /* 0 <= temp < base^2 */
#endif
register digit r, d; /* 0 <= r,d < base */
register posit m;
register precision q;
(void) pparm(u);
if (v < 0) d = (digit) -v; else d = (digit) v;
if (d >= BASE) {
q = pnew(errorp(PDOMAIN, "pidiv", "divisor too big for single digit"));
goto done;
}
if (d == 0) {
q = pnew(errorp(PDOMAIN, "pidiv", "divide by zero"));
goto done;
}
m = u->size;
q = palloc(m);
if (q == pUndef) goto done;
#ifndef ASM_16BIT
qPtr = q->value + m;
uPtr = u->value + m;
r = 0; /* r is current remainder */
do {
temp = mulBase(r); /* 0 <= temp <= (base-1)^2 */
temp += *--uPtr; /* 0 <= temp <= base(base-1) */
r = uModDiv(temp, d, --qPtr); /* 0 <= r < base */
} while (uPtr > u->value);
#else
r = memdivw1(q->value, u->value, m, d);
#endif
/*
* normalize q
*/
if (m > 1 && q->value[m-1] == 0) {
--(q->size);
}
q->sign = (u->sign != (v < 0));
if (q->size == 1 && *(q->value) == 0) q->sign = false;
done:
pdestroy(u);
return presult(q);
}