| #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); |
| } |