/* DEC *PowerDecimal(pDst,pSrc1,pSrc2) * * ARGUMENT * DEC *pDst,*pSrc1,*pSrc2; * * DESCRIPTION * Calculates pSrc1 to the power pSrc2 and returns the answer in pDst. * This provides an x**y power function for DEC numbers. Because of * the way we store DEC numbers, the base can't be very large if the * power is greater than 3 or 4. A separate function is provided for * integral powers, which uses a different algorithm and is MUCH FASTER. * * SIDE EFFECTS * None. * * RETURNS * Pointer to the result if no error, otherwise GM_NULL. * * ALGORITHM: * x**y = e**(y*ln(x)). Therefore, call dlnx() to get the natural log * and then multiply by the power of x. Finally, call dexx() to provide * e**z. * * POSSIBLE ERROR CODES * * GM_NULLPOINTER * GM_OVERFLOW * GM_UNDERFLOW * GM_IMAG * GM_PWR0 * * AUTHOR * Andy Anderson 05-JAN-1987 17:30 * Copyright (C) 1987-1990 Greenleaf Software Inc. All rights reserved. * * MODIFICATIONS * */ #include #include "gm.h" #include "gmsystem.h" DEC *PowerDecimal(pDst,pSrc1,pSrc2) DEC *pDst, *pSrc1, *pSrc2; { DEC temp, *pt; int i; _MacStart(GM_DPOW); _MacInVarD(pSrc1); _MacInVarD(pSrc2); _MacOutVarD(pDst); if (_MacIsDecN(pSrc1)) { _MacErr(GM_IMAG); _MacRet(GM_NULL); } if (_MacIsDecZ(pSrc1)) { if (_MacIsDecP(pSrc2)) { _MacDZero(pDst); _MacRet(pDst); } else { _MacErr(GM_PWR0); _MacRet(GM_NULL); } } pt = &temp; /* if the power is integer and small enough, use int power rtn */ if((pSrc2->dc.id == 0) && ((pSrc2->dc.msd == 0) && (pSrc2->ls.lsl[1] == 0L) && (pSrc2->dc.sl[1] == 0)) && (!(pSrc2->dc.sl[0] & 0x8000))) { i = _IntPwrDec80Bit(pt,pSrc1,ConvDecimalToInt(pSrc2)); if(i == GM_OVERFLOW) { _MacErr(i); _MacRet(GM_NULL); } } else { (void) _LnDec80Bit(pt, pSrc1); i = _MulDec80Bit(pt, pt, pSrc2); if(i!=GM_SUCCESS) { _MacErr(i); _MacRet(GM_NULL); } i = _ExpDec80Bit(pt, pt); if(i==GM_OVERFLOW) { _MacErr(i); _MacRet(GM_NULL); } } i = _Sq5UnsTo4Uns(pt); if(i!=GM_SUCCESS) { _MacErr(GM_OVERFLOW); _MacRet(GM_NULL); } if (_MacIsDecZ(pt)) { _MacErr(GM_UNDERFLOW); } _MacDCopy(pDst,pt); _MacRet(pDst); }