/* ------------------------------------------------------------------ */ decContext * decContextDefault (decContext * context, Int kind) { /* set defaults... */ context->digits = 9; /* 9 digits */ context->emax = DEC_MAX_EMAX; /* 9-digit exponents */ context->emin = DEC_MIN_EMIN; /* .. balanced */ context->round = DEC_ROUND_HALF_UP; /* 0.5 rises */ context->traps = DEC_Errors; /* all but informational */ context->status = 0; /* cleared */ context->clamp = 0; /* no clamping */ #if DECSUBSET context->extended = 0; /* cleared */ #endif switch (kind) { case DEC_INIT_BASE: /* [use defaults] */ break; case DEC_INIT_DECIMAL32: context->digits = 7; /* digits */ context->emax = 96; /* Emax */ context->emin = -95; /* Emin */ context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ context->traps = 0; /* no traps set */ context->clamp = 1; /* clamp exponents */ #if DECSUBSET context->extended = 1; /* set */ #endif break; case DEC_INIT_DECIMAL64: context->digits = 16; /* digits */ context->emax = 384; /* Emax */ context->emin = -383; /* Emin */ context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ context->traps = 0; /* no traps set */ context->clamp = 1; /* clamp exponents */ #if DECSUBSET context->extended = 1; /* set */ #endif break; case DEC_INIT_DECIMAL128: context->digits = 34; /* digits */ context->emax = 6144; /* Emax */ context->emin = -6143; /* Emin */ context->round = DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ context->traps = 0; /* no traps set */ context->clamp = 1; /* clamp exponents */ #if DECSUBSET context->extended = 1; /* set */ #endif break; default: /* invalid Kind */ /* use defaults, and .. */ decContextSetStatus (context, DEC_Invalid_operation); /* trap */ } return context; } /* decContextDefault */
/* ------------------------------------------------------------------ */ decContext * decContextDefault(decContext *context, Int kind) { // set defaults... context->digits=9; // 9 digits context->emax=DEC_MAX_EMAX; // 9-digit exponents context->emin=DEC_MIN_EMIN; // .. balanced context->round=DEC_ROUND_HALF_UP; // 0.5 rises context->traps=DEC_Errors; // all but informational context->status=0; // cleared context->clamp=0; // no clamping #if DECSUBSET context->extended=0; // cleared #endif switch (kind) { case DEC_INIT_BASE: // [use defaults] break; case DEC_INIT_DECIMAL32: context->digits=7; // digits context->emax=96; // Emax context->emin=-95; // Emin context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even context->traps=0; // no traps set context->clamp=1; // clamp exponents #if DECSUBSET context->extended=1; // set #endif break; case DEC_INIT_DECIMAL64: context->digits=16; // digits context->emax=384; // Emax context->emin=-383; // Emin context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even context->traps=0; // no traps set context->clamp=1; // clamp exponents #if DECSUBSET context->extended=1; // set #endif break; case DEC_INIT_DECIMAL128: context->digits=34; // digits context->emax=6144; // Emax context->emin=-6143; // Emin context->round=DEC_ROUND_HALF_EVEN; // 0.5 to nearest even context->traps=0; // no traps set context->clamp=1; // clamp exponents #if DECSUBSET context->extended=1; // set #endif break; default: // invalid Kind // use defaults, and .. decContextSetStatus(context, DEC_Invalid_operation); // trap } return context;} // decContextDefault
/* ------------------------------------------------------------------ */ decimal64 * decimal64FromString (decimal64 * result, const char *string, decContext * set) { decContext dc; decNumber dn; decContextDefault (&dc, DEC_INIT_DECIMAL64); dc.round = set->round; decNumberFromString (&dn, string, &dc); decimal64FromNumber (result, &dn, &dc); if (dc.status != 0) decContextSetStatus (set, dc.status); return result; }
decimal32 * decimal32FromString (decimal32 *result, const char *string, decContext *set) { decContext dc; /* work */ decNumber dn; /* .. */ decContextDefault (&dc, DEC_INIT_DECIMAL32); /* no traps, please */ dc.round = set->round; /* use supplied rounding */ decNumberFromString (&dn, string, &dc); /* will round if needed */ decimal32FromNumber (result, &dn, &dc); if (dc.status != 0) { /* something happened */ decContextSetStatus (set, dc.status); /* .. pass it on */ } return result; }
/* ------------------------------------------------------------------ */ decContext * decContextSetStatusFromString (decContext * context, const char *string) { if (strcmp (string, DEC_Condition_CS) == 0) return decContextSetStatus (context, DEC_Conversion_syntax); if (strcmp (string, DEC_Condition_DZ) == 0) return decContextSetStatus (context, DEC_Division_by_zero); if (strcmp (string, DEC_Condition_DI) == 0) return decContextSetStatus (context, DEC_Division_impossible); if (strcmp (string, DEC_Condition_DU) == 0) return decContextSetStatus (context, DEC_Division_undefined); if (strcmp (string, DEC_Condition_IE) == 0) return decContextSetStatus (context, DEC_Inexact); if (strcmp (string, DEC_Condition_IS) == 0) return decContextSetStatus (context, DEC_Insufficient_storage); if (strcmp (string, DEC_Condition_IC) == 0) return decContextSetStatus (context, DEC_Invalid_context); if (strcmp (string, DEC_Condition_IO) == 0) return decContextSetStatus (context, DEC_Invalid_operation); #if DECSUBSET if (strcmp (string, DEC_Condition_LD) == 0) return decContextSetStatus (context, DEC_Lost_digits); #endif if (strcmp (string, DEC_Condition_OV) == 0) return decContextSetStatus (context, DEC_Overflow); if (strcmp (string, DEC_Condition_PA) == 0) return decContextSetStatus (context, DEC_Clamped); if (strcmp (string, DEC_Condition_RO) == 0) return decContextSetStatus (context, DEC_Rounded); if (strcmp (string, DEC_Condition_SU) == 0) return decContextSetStatus (context, DEC_Subnormal); if (strcmp (string, DEC_Condition_UN) == 0) return decContextSetStatus (context, DEC_Underflow); if (strcmp (string, DEC_Condition_ZE) == 0) return context; return NULL; /* Multiple status, or unknown */ } /* decContextSetStatusFromString */
/* ------------------------------------------------------------------ */ decimal64 * decimal64FromNumber (decimal64 * d64, const decNumber *dn, decContext *set) { uInt status = 0; Int ae; /* adjusted exponent */ decNumber dw; decContext dc; uInt exp; uInt uiwork; uInt targhi = 0; uInt targlo = 0; Int shift; /* If the number has too many digits, or the exponent could be out of range then reduce the number under the appropriate constraints. This could push the number to Infinity or zero, so this check and rounding must be done before generating the decimal64. */ ae = dn->exponent + dn->digits - 1; /* [0 if special] */ if (dn->digits > DECIMAL64_Pmax /* too many digits */ || ae > DECIMAL64_Emax /* likely overflow */ || ae < DECIMAL64_Emin) { /* likely underflow */ decContextDefault (&dc, DEC_INIT_DECIMAL64); dc.round = set->round; decNumberPlus (&dw, dn, &dc); /* (round and check) */ /* [this changes -0 to 0, so enforce the sign...] */ dw.bits |= dn->bits & DECNEG; status = dc.status; dn = &dw; } if (dn->bits & DECSPECIAL) { if (dn->bits & DECINF) targhi = DECIMAL_Inf << 24; else { /* sNaN or qNaN */ if ((*dn->lsu != 0 || dn->digits > 1) /* non-zero coefficient */ && (dn->digits < DECIMAL64_Pmax)) decDigitsToBID (dn, &targhi, &targlo); if (dn->bits & DECNAN) targhi |= DECIMAL_NaN << 24; else targhi |= DECIMAL_sNaN << 24; } } else { /* is finite */ if (decNumberIsZero (dn)) { /* set and clamp exponent */ if (dn->exponent < -DECIMAL64_Bias) { exp = 0; status |= DEC_Clamped; } else { exp = dn->exponent + DECIMAL64_Bias; if (exp > DECIMAL64_Ehigh) { exp = DECIMAL64_Ehigh; status |= DEC_Clamped; } } } else { /* non-zero finite number */ exp = (uInt) (dn->exponent + DECIMAL64_Bias); if (exp > DECIMAL64_Ehigh) { exp = DECIMAL64_Ehigh; status |= DEC_Clamped; } decDigitsToBID (dn, &targhi, &targlo); } /* Exponent is enconded as: - If coefficient fits in 53 bits: | sign - 1bit | exponent - 10 bits | coefficient - 53 bits | - Otherwise | sign - 1bit | 11 | exponent - 10 bits | coefficient - 51 bits | Since decDigitsToBID will set '11' mask if coefficient does not fit 53 bits, we check it to adjust the exponent shift in higher word. */ if ((targhi & BID_EXPONENT_ENC_MASK) == BID_EXPONENT_ENC_MASK) shift = BID_EXP_SHIFT_LARGE64; else shift = BID_EXP_SHIFT_SMALL64; targhi |= (exp & BID_EXP_MASK64) << shift; } if (dn->bits & DECNEG) targhi |= BID_SIGN_MASK; /* now write to storage; this is now always endian */ UBFROMUIBW (d64->bytes, targhi); UBFROMUIBW (d64->bytes + 4, targlo); if (status != 0) decContextSetStatus (set, status); /*decimal64Show(d64);*/ return d64; }
/* ------------------------------------------------------------------ */ decContext * decContextDefault(decContext *context, Int kind) { /* set defaults... */ context->digits=9; /* 9 digits */ context->emax=DEC_MAX_EMAX; /* 9-digit exponents */ context->emin=DEC_MIN_EMIN; /* .. balanced */ context->round=DEC_ROUND_HALF_UP; /* 0.5 rises */ context->traps=DEC_Errors; /* all but informational */ context->status=0; /* cleared */ context->clamp=0; /* no clamping */ #if DECSUBSET context->extended=0; /* cleared */ #endif switch (kind) { case DEC_INIT_BASE: /* [use defaults] */ break; case DEC_INIT_DECIMAL32: context->digits=7; /* digits */ context->emax=96; /* Emax */ context->emin=-95; /* Emin */ context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ context->traps=0; /* no traps set */ context->clamp=1; /* clamp exponents */ #if DECSUBSET context->extended=1; /* set */ #endif break; case DEC_INIT_DECIMAL64: context->digits=16; /* digits */ context->emax=384; /* Emax */ context->emin=-383; /* Emin */ context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ context->traps=0; /* no traps set */ context->clamp=1; /* clamp exponents */ #if DECSUBSET context->extended=1; /* set */ #endif break; case DEC_INIT_DECIMAL128: context->digits=34; /* digits */ context->emax=6144; /* Emax */ context->emin=-6143; /* Emin */ context->round=DEC_ROUND_HALF_EVEN; /* 0.5 to nearest even */ context->traps=0; /* no traps set */ context->clamp=1; /* clamp exponents */ #if DECSUBSET context->extended=1; /* set */ #endif break; default: /* invalid Kind */ /* use defaults, and .. */ decContextSetStatus(context, DEC_Invalid_operation); /* trap */ } #if DECCHECK if (LITEND!=DECLITEND) { const char *adj; if (LITEND) adj="little"; else adj="big"; printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n", DECLITEND, adj); } #endif return context;} /* decContextDefault */