/* int _IntPwrDec80Bit(pDst,pSrc,i) * * ARGUMENT * DEC *pDst,*pSrc; * int i; * * DESCRIPTION * Raises pSrc to the power 'i'. If i<0, raises pSrc to the |i|, then * takes the reciprocal(ie, if i<0, then x**i = 1/x**|i|). If x=0, then * if i=<0, then error (GM_PWR0), else pDst is set to 1. If x<0, then if the * power is odd, the result will be negative, otherwise positive. The * absolute value cannot exceed 2**79 -1. Other high-level functions need * returns of 2**79 -1, which is what this routine returns. * * SIDE EFFECTS * None. * * RETURNS * GM_SUCCESS if no error, otherwise one of the errors below. Note that * it is up to the caller to set any of these (with SetMathError()): * GM_OVERFLOW if number is too large; * GM_UNDERFLOW too small; or * GM_PWR0 if power and base is as described above. * * AUTHOR * Andy Anderson 08-10-87 0930 * Copyright (C) 1987-1990 Greenleaf Software Inc. All rights reserved. * * MODIFICATIONS */ #include #include "gm.h" #include "gmsystem.h" int _IntPwrDec80Bit(pDst,pSrc,i) DEC *pDst,*pSrc; int i; { register int j; int k; mbool wfRecip, wfIsNeg, wfWasOdd; DEC y,z,*py=&y,*pz=&z,*pone; j=i; /* constant of one for reciprocals */ pone=&decOne; _MacDCopy(py,pone); if(j==0) { if(_MacIsDecP(pSrc)) { _MacDCopy(pDst,pone); return(GM_SUCCESS); } else /* 0**0 and -x**0 are undefined */ return(GM_PWR0); } /* then find out if final answer will be positive or negative */ _MacDCopy(pz,pSrc); if(_MacIsDecN(pSrc)) { _MacDChgs(pz); if(j&0x0001) wfIsNeg=TRUE; /* negative number to odd exp = neg */ else wfIsNeg=FALSE; /* neg. number to even exp = pos */ } else { wfIsNeg=FALSE; /* pos number to any exp = pos */ } _MacDZero(pDst); /* then set do reciprocal bit */ if(j<0) { if ((long) j == -32768L) { /* -32768 must be handled separately */ k = _MulDec80Bit(pz, pz, pz); if (k == GM_OVERFLOW) return(GM_UNDERFLOW); j = -16384; } wfRecip = TRUE; j = -j; } else wfRecip = FALSE; /* now do the calculation x ** i */ do { wfWasOdd = (j&0x0001) ? TRUE : FALSE; j >>= 1; /* divide power by two */ if(wfWasOdd) { k=_MulDec80Bit(py,py,pz); if(k!=GM_SUCCESS) return(((k==GM_OVERFLOW)^wfRecip) ? GM_OVERFLOW : GM_UNDERFLOW); if(j==0) { if(wfRecip) { k=_DivDec80Bit(py,pone,py); if(k!=GM_SUCCESS) return(k); } if(wfIsNeg) _MacDChgs(py); _MacDCopy(pDst,py); return(GM_SUCCESS); } k=_MulDec80Bit(pz,pz,pz); if(k!=GM_SUCCESS) return(((k==GM_OVERFLOW)^wfRecip) ? GM_OVERFLOW : GM_UNDERFLOW); } else { k=_MulDec80Bit(pz,pz,pz); /* z = z * z */ if(k!=GM_SUCCESS) return(((k==GM_OVERFLOW)^wfRecip) ? GM_OVERFLOW : GM_UNDERFLOW); } } while(j>0); if(wfRecip) { k=_DivDec80Bit(pz,pone,pz); if(k!=GM_SUCCESS) return(k); } if(wfIsNeg) _MacDChgs(pz); _MacDCopy(pDst,pz); return(GM_SUCCESS); }