/* int _ExpDec80Bit(pDst,pSrc) * * ARGUMENT * DEC *pDst, *pSrc; * * DESCRIPTION * Calculates e^pSrc, stores result in pDst. * * SIDE EFFECTS * None. * * RETURNS * GM_SUCCESS if calculation is successful, * otherwise the error code (which could be underflow) * * ALGORITHM * pSrc = a * ln 2 + b |b| < (ln 2) / 2 * e^pSrc = (2^a) * (e^b) * Using the Taylor series, * e^b = 1 + b + (b^2)/2! + (b^3)/3! + ... * * AUTHOR * Jared Levy April 7, 1987 * Copyright (C) 1987-1990 Greenleaf Software Inc. All rights reserved. * * MODIFICATIONS * */ #include #include "gm.h" #include "gmsystem.h" int _ExpDec80Bit(pDst,pSrc) DEC *pDst, *pSrc; { int a, i; DEC da, dpow2, db, dt, dfact, dterm; DEC *pow2, *b, *fact, *pt, *term; if (CompareDecimal(pSrc,&decMaxExp) == 1) { return(GM_OVERFLOW); } if (CompareDecimal(pSrc,&decMinExp) == -1) { _MacDZero(pDst); return(GM_UNDERFLOW); } /* calculate a = pSrc * (1/(ln 2)) */ (void) _MulDec80Bit(&da, pSrc, &decReciprocalOfLn2); (void) _ScaleDec80Bit(&da,&da,0); a = ConvDecimalToInt(&da); /* calculate b = pSrc - a * ln 2 */ b=&db; if (a == 0) { _MacDCopy(b,pSrc); } else { (void) _MulDec80Bit(&dt, &da, &decLn2); (void) _SubDec80Bit(b, pSrc, &dt); } /* calculate pSrc = (2^a) * (e^b) */ fact = &dfact; pt = &decOne; term = &dterm; _MacDCopy(fact,pt); _MacDCopy(pDst,pt); _AddDec80Bit(pDst, pDst, b); _MacDCopy(term, b); do { /* calulate next term */ fact->dc.sl[0]++; (void) _MulDec80Bit(term, b, term); (void) _DivRndDec80Bit(term, term, fact, 23); /* add term to series */ (void) _AddDec80Bit(pDst, pDst, term); /* calc next factorial term in divisor */ } while (!(_MacIsDecZ(term))); if (a>0) { pow2 = &dpow2; /* * I used to use the _MacDZero statement here, but Lattice C 6.0 * pointed out that it had a single redundant line in the * macro, so I expanded it and remove the redundant line. * _MacDZero(pow2); */ pow2->dc.attr=0; pow2->ls.lsl[0]=0; pow2->ls.lsl[1]=0; pow2->dc.msd=0; pow2->dc.id = 0; pow2->dc.sl[a/16] = 1 << (a % 16); i =_MulDec80Bit(pDst, pDst, pow2); return(i); } while (a<0) { _HalveUnsArr(pDst->dc.sl, 5); a++; } if (_MacIsDecZ(pDst)) return(GM_UNDERFLOW); return(GM_SUCCESS); }