#include "pdefs.h" #include "precision.h" #include #ifdef ASM_16BIT #include "asm16bit.h" #endif /* * Multiply u by v (assumes normalized) */ precision pmul(u, v) register precision v; /* register a5 on 68000 */ #ifdef ASM_16BIT register precision u; /* register a4 */ { #else precision u; { digitPtr vPtr; register digitPtr uPtr, wPtr, HiDigit; register accumulator temp; /* 0 <= temp < base * base */ /* d7 */ register digit vdigit; /* d6 */ #endif register digit hi; /* 0 <= hi < base */ /* d5 */ precision w; (void) pparm(u); (void) pparm(v); /* * Check for multiply by zero. Helps prevent wasted storage and -0 */ if (peqz(u) || peqz(v)) { w = palloc(1); if (w == pUndef) return w; w->sign = false; w->value[0] = 0; } else { if (u->size < v->size) { /* u is biggest number (for inner loop speed) */ w = u; u = v; v = w; } w = palloc(u->size + v->size); if (w == pUndef) return w; w->sign = (u->sign != v->sign); #ifndef ASM_16BIT uPtr = u->value; vPtr = v->value; wPtr = w->value + u->size; /* this is correct! */ do { *--wPtr = 0; } while (wPtr > w->value); vPtr = v->value; HiDigit = u->value + u->size; do { uPtr = u->value; wPtr = w->value + (vPtr - v->value); hi = 0; vdigit = *vPtr; do { temp = uMul(vdigit, *uPtr++); /* 0 <= temp <= (base-1)^2 */ temp += *wPtr; /* 0 <= temp <= base(base-1) */ temp += hi; /* 0 <= temp < base * base */ hi = divBase(temp); /* 0 <= hi < base */ *wPtr++ = modBase(temp); } while (uPtr < HiDigit); *wPtr++ = hi; } while (++vPtr < v->value + v->size); #else hi = memmulw(w->value, u->value, u->size, v->value, v->size); #endif if (hi == 0) { --(w->size); /* normalize */ } } pdestroy(u); pdestroy(v); return presult(w); }