#include "pdefs.h" #include "precision.h" #include #ifdef ASM_16BIT #include "asm16bit.h" #endif /* * Subtract u from v (assumes normalized) */ precision psub(u, v) #ifndef ASM_16BIT precision u, v; { register digitPtr HiDigit, wPtr, uPtr; register digitPtr vPtr; #else register precision u, v; { register digitPtr wPtr, uPtr; #endif precision w; register accumulator temp; #ifndef ASM_16BIT register digit noborrow; #endif register int i; (void) pparm(u); (void) pparm(v); if (u->sign != v->sign) { /* Are we actually adding? */ w = pUndef; v->sign = !v->sign; /* may generate -0 */ pset(&w, padd(u, v)); v->sign = !v->sign; } else { i = pcmp(u, v); if (u->sign) i = -i; /* compare magnitudes only */ if (i < 0) { w = u; u = v; v = w; /* make u the largest */ } w = palloc(u->size); /* may produce much wasted storage */ if (w == pUndef) return w; if (i < 0) w->sign = !u->sign; else w->sign = u->sign; uPtr = u->value; wPtr = w->value; #ifndef ASM_16BIT vPtr = v->value; noborrow = 1; HiDigit = v->value + v->size; /* digits in both args */ do { temp = (BASE-1) - *vPtr++; /* 0 <= temp < base */ temp += *uPtr++; /* 0 <= temp < 2*base-1 */ temp += noborrow; /* 0 <= temp < 2*base */ noborrow = divBase(temp); /* 0 <= noborrow <= 1 */ *wPtr++ = modBase(temp); } while (vPtr < HiDigit); HiDigit = u->value + u->size; /* propagate borrow */ while (uPtr < HiDigit) { temp = (BASE-1) + *uPtr++; temp += noborrow; /* 0 <= temp < 2 * base */ noborrow = divBase(temp); /* 0 <= noborrow <= 1 */ *wPtr++ = modBase(temp); } /* noborrow = 1 */ #else i = v->size; temp = u->size - i; if (temp > 0) { memcpy(wPtr + i, uPtr + i, temp * sizeof(digit)); } if (memsubw(wPtr, uPtr, v->value, i)) { /* trashes uPtr */ memdecw(wPtr + i, temp); } wPtr += w->size; #endif do { /* normalize */ if (*--wPtr != 0) break; } while (wPtr > w->value); w->size = (wPtr - w->value) + 1; } pdestroy(u); pdestroy(v); return presult(w); }