/* DEC *ConvDoubleToDecimal( x, f) * * ARGUMENT * DEC *x; * double f; * * DESCRIPTION * Converts a double to a DEC with maximum implied decimal. Uses * eTwoTo32 (2^32), eTwoTo63 (2^63), and ergGMPowersOfTenDouble * (powers of ten), all global double variables. * * SIDE EFFECTS * None. * * RETURNS * The DEC if the conversion is successful, and GM_NULL otherwise. * * POSSIBLE ERROR CODES * * GM_NOMEMORY * GM_CNVRE * * AUTHOR * Jared Levy Feb. 9, 1987 * Copyright (C) 1987-1990 Greenleaf Software Inc. All rights reserved. * * MODIFICATIONS * */ #include #include "gm.h" #include "gmsystem.h" #include "math.h" DEC *ConvDoubleToDecimal( x, f) DEC *x; double f; { int nid; mbool wfIsNeg=FALSE; double g; _MacStart(GM_DFTOD); _MacOutVarD(x); /* take absolute value of negative values */ if (f<0.0) { wfIsNeg = TRUE; f = -f; } /* f = 0 */ if (f == 0.0) { _MacDZero(x); _MacRet(x); } /* overflow & underflow (MAXID = 18, MINID = 0) */ if ((f>=eTwoTo63) || (f<.5e-18)) { if (x) _MacDZero(x); _MacErr(GM_CNVRE); _MacRet(GM_NULL); } /* take absolute value of negative values */ if (f<0.0) { wfIsNeg = TRUE; f = -f; } _MacDZero(x); /* calculate implied decimal of DEC */ g = eTwoTo63/f; nid = 0; while ((nid <= 17) && (ergGMPowersOfTenDouble[nid+1] <= g)) nid++; /* adjust by power of 10 */ f = f * ergGMPowersOfTenDouble[nid]; /* add .5 to round rather than truncate */ f+= 0.5; /* change float to 64 bit integer */ if (f >= eTwoTo32 - 1) { #ifdef ZORTECH if ( (f / eTwoTo32) > eTwoTo31 ) { x->ls.lsl[1] = (unsigned long) ((f / eTwoTo32) - eTwoTo31 ); x->ls.lsl[1] += (unsigned long) eTwoTo31; } else x->ls.lsl[1] = (unsigned long) (f / eTwoTo32); #else x->ls.lsl[1] = (unsigned long) (f / eTwoTo32); #endif g = (double) x->ls.lsl[1]; f-= g * eTwoTo32; while (f<0.0) { x->ls.lsl[1]--; f+= eTwoTo32; } while (f>= eTwoTo32) { x->ls.lsl[1]++; f-= eTwoTo32; } } else x->ls.lsl[1] = 0; #ifdef ZORTECH if ( f > eTwoTo31 ) { x->ls.lsl[0] = f - eTwoTo31; x->ls.lsl[0] += (unsigned long) eTwoTo31; } else x->ls.lsl[0] = (unsigned long) f; #else x->ls.lsl[0] = (unsigned long) f; #endif x->ls.lid = nid; x->dc.msd = 0; /* msd can't be set either */ if (wfIsNeg) { _MacDChgs(x); } _MacRet(x); }