void decimal_real_from_string (REAL_VALUE_TYPE *r, const char *s) { decNumber dn; decContext set; decContextDefault (&set, DEC_INIT_DECIMAL128); set.traps = 0; decNumberFromString (&dn, (char *) s, &set); /* It would be more efficient to store directly in decNumber format, but that is impractical from current data structure size. Encoding as a decimal128 is much more compact. */ decimal_from_decnumber (r, &dn, &set); }
/* Use decNumber to convert directly from _Decimal128 to _Decimal64. */ _Decimal64 DFP_TO_DFP (_Decimal128 f_from) { union { _Decimal64 c; decDouble f; } to; union { _Decimal128 c; decQuad f; } from; decContext context; decContextDefault (&context, CONTEXT_INIT); DFP_INIT_ROUNDMODE (context.round); from.c = f_from; to.f = *decDoubleFromWider (&to.f, &from.f, &context); if (DFP_EXCEPTIONS_ENABLED && context.status != 0) dfp_conversion_exceptions (context.status); return to.c; }
/* ------------------------------------------------------------------ */ 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; }
/* Use decNumber to convert directly from decimal float to integer types. */ INT_TYPE DFP_TO_INT (DFP_C_TYPE x) { union { DFP_C_TYPE c; decFloat f; } u; decContext context; INT_TYPE i; decContextDefault (&context, DEC_INIT_DECIMAL128); context.round = DEC_ROUND_DOWN; u.c = x; i = DEC_FLOAT_TO_INT (&u.f, &context, context.round); if (DFP_EXCEPTIONS_ENABLED && context.status != 0) dfp_conversion_exceptions (context.status); return i; }
int main(int argc, char *argv[]) { { // excerpt for User's Guide starts here--------------------------| decNumber one, mtwo, hundred; // constants decNumber start, rate, years; // parameters decNumber total; // result decContext set; // working context uint8_t startpack[]={0x01, 0x00, 0x00, 0x0C}; // investment=100000 int32_t startscale=0; uint8_t ratepack[]={0x06, 0x5C}; // rate=6.5% int32_t ratescale=1; uint8_t yearspack[]={0x02, 0x0C}; // years=20 int32_t yearsscale=0; uint8_t respack[16]; // result, packed int32_t resscale; // .. char hexes[49]; // for packed->hex int i; // counter if (argc<0) printf("%s", argv[1]); // noop for warning decContextDefault(&set, DEC_INIT_BASE); // initialize set.traps=0; // no traps set.digits=25; // precision 25 decNumberFromString(&one, "1", &set); // set constants decNumberFromString(&mtwo, "-2", &set); decNumberFromString(&hundred, "100", &set); decPackedToNumber(startpack, sizeof(startpack), &startscale, &start); decPackedToNumber(ratepack, sizeof(ratepack), &ratescale, &rate); decPackedToNumber(yearspack, sizeof(yearspack), &yearsscale, &years); decNumberDivide(&rate, &rate, &hundred, &set); // rate=rate/100 decNumberAdd(&rate, &rate, &one, &set); // rate=rate+1 decNumberPower(&rate, &rate, &years, &set); // rate=rate^years decNumberMultiply(&total, &rate, &start, &set); // total=rate*start decNumberRescale(&total, &total, &mtwo, &set); // two digits please decPackedFromNumber(respack, sizeof(respack), &resscale, &total); // lay out the total as sixteen hexadecimal pairs for (i=0; i<16; i++) { sprintf(&hexes[i*3], "%02x ", respack[i]); } printf("Result: %s (scale=%ld)\n", hexes, (long int)resscale); } //---------------------------------------------------------------| return 0; } // main
_Decimal32 /* Use decNumber to convert directly from integer to decimal float types. */ INT_TO_DFP (INT_TYPE i) { union { _Decimal32 c; decSingle f; } u32; decDouble f64; decContext context; decContextDefault (&context, DEC_INIT_DECIMAL128); context.round = DEC_ROUND_DOWN; f64 = *DEC_FLOAT_FROM_INT (&f64, i); u32.f = *decSingleFromWider (&u32.f, &f64, &context); if (DFP_EXCEPTIONS_ENABLED && context.status != 0) dfp_conversion_exceptions (context.status); return u32.c; }
int PREFIXED_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y) { decNumber dn_x, dn_y, result; decContext context; decContextDefault(&context, DEFAULT_CONTEXT); FUNC_CONVERT_TO_DN(&x, &dn_x); FUNC_CONVERT_TO_DN(&y, &dn_y); if(decNumberIsNaN(&dn_x) || decNumberIsNaN(&dn_y)) return -1; decNumberCompare(&result, &dn_x, &dn_y, &context); return !decNumberIsNegative(&result) && !decNumberIsZero(&result); }
/* Use decNumber to convert directly from decimal float to integer types. */ INT_TYPE DFP_TO_INT (_Decimal32 x) { union { _Decimal32 c; decSingle f; } u32; decDouble f64; decContext context; INT_TYPE i; decContextDefault (&context, DEC_INIT_DECIMAL128); context.round = DEC_ROUND_DOWN; u32.c = x; f64 = *decSingleToWider (&u32.f, &f64); i = DEC_FLOAT_TO_INT (&f64, &context, context.round); if (DFP_EXCEPTIONS_ENABLED && context.status != 0) dfp_conversion_exceptions (context.status); return i; }
DecimalDecNumber::DecimalDecNumber(uint64 rhs) { decContextDefault(&m_context, DEC_INIT_BASE); // initialize m_context.traps = 0; // no traps, thank you m_context.digits = DECNUMDIGITS; // set precision if (rhs <= std::numeric_limits<uint>::max()) { decNumberFromUInt32(&m_value, static_cast<uint>(rhs)); } else { char buffer[64]; uint64_to_string(rhs, buffer); decNumberFromString(&m_value, buffer, &m_context); } }
DEC_TYPE INTERNAL_FUNCTION_NAME (DEC_TYPE x) { decContext context; decNumber dn_result; DEC_TYPE result; decNumber dn_x; FUNC_CONVERT_TO_DN(&x, &dn_x); decContextDefault(&context, DEFAULT_CONTEXT); context.round = DEC_ROUND_DOWN; decNumberToIntegralValue(&dn_result, &dn_x, &context); FUNC_CONVERT_FROM_DN(&dn_result, &result, &context); 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; }
static VALUE con_initialize(int argc, VALUE *argv, VALUE self) { decContext *self_ptr; VALUE digits; rb_scan_args( argc, argv, "01", &digits ); Data_Get_Struct(self, decContext, self_ptr); decContextDefault(self_ptr, DEC_INIT_BASE); self_ptr->traps = 0; /* no traps TODO: error handling */ if ( NIL_P(digits) ) { self_ptr->digits = DECNUMDIGITS; } else { con_set_digits(self,digits); } /* TODO: Handle arguments */ return self; }
DEC_TYPE INTERNAL_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y) { decContext context; decNumber dn_result; DEC_TYPE result; decNumber dn_x; decNumber dn_y; FUNC_CONVERT_TO_DN(&x, &dn_x); FUNC_CONVERT_TO_DN(&y, &dn_y); decContextDefault(&context, DEFAULT_CONTEXT); decNumberMax(&dn_result, &dn_x, &dn_y, &context); FUNC_CONVERT_FROM_DN(&dn_result, &result, &context); return result; }
int testDecQuad() { int i; decQuad a, b; decContext set; char string[DECQUAD_String]; decContextDefault(&set, DEC_INIT_DECQUAD); // initialize decQuadFromString(&a, "0.13", &set); decQuadFromString(&b, "8.7", &set); for (i = 0; i < 10; i++) decQuadAdd(&b, &a, &b, &set); // b += a; decQuadToString(&b, string); printf("dec128: 8.7 + 0.13 * 10 => %s\n", string); return 0; }
int testDecDouble() { int i; decDouble a, b; decContext set; char string[DECDOUBLE_String]; decContextDefault(&set, DEC_INIT_DECDOUBLE); // initialize decDoubleFromString(&a, "0.13", &set); decDoubleFromString(&b, "8.7", &set); for (i = 0; i < 10; i++) decDoubleAdd(&b, &a, &b, &set); // b += a; decDoubleToString(&b, string); printf("dec064: 8.7 + 0.13 * 10 => %s\n", string); return 0; }
DEST_TYPE PREFIXED_FUNCTION_NAME (SRC_TYPE a) { /* decNumber's decimal* types have the same format as C's _Decimal* types, but they have different calling conventions. */ char buf[BUFMAX]; decNumber n; decContext context; IEEE_SRC_TYPE e; decContextDefault (&context, CONTEXT_INIT); PASTE(___host_to_ieee_,SRC) ((&a), &e); PASTE(decimal,PASTE(SRC,ToNumber))(&e, &n); decNumberToString (&n, buf); /* Use a C library function to convert to the integral type. */ return strtold (buf, NULL); }
DFP_C_TYPE INT_TO_DFP (INT_TYPE i) { DFP_C_TYPE f; IEEE_TYPE s; char buf[BUFMAX]; decContext context; decContextDefault (&context, CONTEXT_INIT); context.round = CONTEXT_ROUND; /* Use a C library function to get a floating point string. */ sprintf (buf, INT_FMT ".0", CAST_FOR_FMT(i)); /* Convert from the floating point string to a decimal* type. */ FROM_STRING (&s, buf, &context); IEEE_TO_HOST (s, &f); if (CONTEXT_TRAPS && (context.status & DEC_Inexact) != 0) DFP_RAISE (DEC_Inexact); return f; }
DEC_TYPE FUNC_NAME (_Decimal128 hi, _Decimal128 mid, _Decimal128 low) { DEC_TYPE result; /* hi = m_hi * 10^34 * mid = m_mid * 10^17 * low = m_low * 10^0 * * Note, m_hi is only at most 5 digits for int128. */ decNumber dn_hi, dn_mid, dn_low, dn_result; decNumber dn_hi_s, dn_mid_s, dn_result_s; decNumber dn_17, dn_34; decContext context; decContextDefault (&context, DEC_INIT_DECIMAL128); /* Hack, we're using 39 digits here. */ context.digits = 39; decNumberFromInt32(&dn_17, 17); decNumberFromInt32(&dn_34, 34); __DECIMAL_TO_DECNUMBER (&hi, &dn_hi, 128); __DECIMAL_TO_DECNUMBER (&mid, &dn_mid, 128); __DECIMAL_TO_DECNUMBER (&low, &dn_low, 128); /* Rotate addends into proper position. */ decNumberShift(&dn_hi_s,&dn_hi,&dn_34,&context); decNumberShift(&dn_mid_s,&dn_mid,&dn_17,&context); /* Sum the three components. */ decNumberAdd(&dn_result_s, &dn_hi_s, &dn_mid_s, &context); decNumberAdd(&dn_result, &dn_result_s, &dn_low, &context); /* Convert to the destination format. */ FUNC_CONVERT_FROM_DN (&dn_result, &result, &context); /* Don't care about exceptions here... I don't think. */ return result; }
bool cmoney_t::operator<(const cmoney_t& in ) const { decContext set; decContextDefault(&set, DEC_INIT_DECQUAD); // initialize4. decQuad result; decQuadCompare (&result,&v->impl,&in.v->impl,&set); int intresult=decQuadToInt32(&result, &set, DEC_ROUND_UP); if (intresult==-1) { return true; } else { return false; } }
DFP_C_TYPE_TO DFP_TO_DFP (DFP_C_TYPE f_from) { DFP_C_TYPE_TO f_to; IEEE_TYPE s_from; IEEE_TYPE_TO s_to; decNumber d; decContext context; decContextDefault (&context, CONTEXT_INIT); context.round = CONTEXT_ROUND; HOST_TO_IEEE (f_from, &s_from); TO_INTERNAL (&s_from, &d); TO_ENCODED_TO (&s_to, &d, &context); if (CONTEXT_TRAPS && (context.status & DEC_Inexact) != 0) DFP_RAISE (DEC_Inexact); IEEE_TO_HOST_TO (s_to, &f_to); return f_to; }
/* decNumber doesn't provide support for conversions from 64-bit integer types, so do it the hard way. */ DFP_C_TYPE INT_TO_DFP (INT_TYPE i) { DFP_C_TYPE f; IEEE_TYPE s; char buf[BUFMAX]; decContext context; decContextDefault (&context, CONTEXT_INIT); DFP_INIT_ROUNDMODE (context.round); /* Use a C library function to get a floating point string. */ sprintf (buf, INT_FMT ".0", CAST_FOR_FMT(i)); /* Convert from the floating point string to a decimal* type. */ FROM_STRING (&s, buf, &context); IEEE_TO_HOST (s, &f); if (DFP_EXCEPTIONS_ENABLED && context.status != 0) dfp_conversion_exceptions (context.status); return f; }
int main(int argc, char *argv[]) { int need=3; if (argc<need+1) { // not enough words printf("Please supply %d number(s).\n", need); return 1; } { // excerpt for User's Guide starts here--------------------------| decNumber one, mtwo, hundred; // constants decNumber start, rate, years; // parameters decNumber total; // result decContext set; // working context char string[DECNUMDIGITS+14]; // conversion buffer decContextDefault(&set, DEC_INIT_BASE); // initialize set.traps=0; // no traps set.digits=25; // precision 25 decNumberFromString(&one, "1", &set); // set constants decNumberFromString(&mtwo, "-2", &set); decNumberFromString(&hundred, "100", &set); decNumberFromString(&start, argv[1], &set); // parameter words decNumberFromString(&rate, argv[2], &set); decNumberFromString(&years, argv[3], &set); decNumberDivide(&rate, &rate, &hundred, &set); // rate=rate/100 decNumberAdd(&rate, &rate, &one, &set); // rate=rate+1 decNumberPower(&rate, &rate, &years, &set); // rate=rate^years decNumberMultiply(&total, &rate, &start, &set); // total=rate*start decNumberRescale(&total, &total, &mtwo, &set); // two digits please decNumberToString(&total, string); printf("%s at %s%% for %s years => %s\n", argv[1], argv[2], argv[3], string); } //---------------------------------------------------------------| return 0; } // main
static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE x) { decContext context; decNumber dn_result; DEC_TYPE result; decNumber dn_x; decNumber dn_sum; decNumber dn_one; DEC_TYPE one = DFP_CONSTANT(1.0); FUNC_CONVERT_TO_DN (&x, &dn_x); FUNC_CONVERT_TO_DN (&one, &dn_one); /* For NaN, 0, or +Inf, just return x */ if (decNumberIsNaN (&dn_x) || decNumberIsZero (&dn_x) || (decNumberIsInfinite (&dn_x) && !decNumberIsNegative (&dn_x))) return x+x; decContextDefault(&context, DEFAULT_CONTEXT); decNumberAdd(&dn_sum, &dn_x, &dn_one, &context); if (decNumberIsZero(&dn_sum)) /* Pole Error if x was -1 */ { DFP_EXCEPT (FE_DIVBYZERO); return -DFP_HUGE_VAL; } if (decNumberIsNegative(&dn_sum)) /* Domain Error if x < -1 */ { DFP_EXCEPT (FE_INVALID); return DFP_NAN; } decNumberLn(&dn_result, &dn_sum, &context); FUNC_CONVERT_FROM_DN(&dn_result, &result, &context); return result; }
void cmoney_t::from_wstr (const std::wstring& in) { char utf8ASCIIstr[DECQUAD_String]; #ifdef WIN32 /* int WideCharToMultiByte( UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar ); */ ::WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)in.c_str(), in.length(), utf8ASCIIstr, DECQUAD_String,NULL,NULL); decContext set; decContextDefault(&set, DEC_INIT_DECQUAD); // initialize4. decQuadFromString( &v->impl,utf8ASCIIstr,&set); #else assert(0); std::cerr<<"cannot convert to decQuad from widechar "<<endl; #endif }
DEC_TYPE INTERNAL_FUNCTION_NAME (DEC_TYPE x) { decContext context; decNumber dn_result; DEC_TYPE result; decNumber dn_x; FUNC_CONVERT_TO_DN (&x, &dn_x); if (decNumberIsNaN (&dn_x) || decNumberIsInfinite (&dn_x) || decNumberIsZero (&dn_x)) return x+x; decContextDefault (&context, DEFAULT_CONTEXT); context.round = __ROUND_MODE; decNumberToIntegralValue (&dn_result, &dn_x, &context); FUNC_CONVERT_FROM_DN (&dn_result, &result, &context); if (context.status & DEC_Overflow) DFP_EXCEPT (FE_OVERFLOW); return result; }
int main(int argc, char *argv[]) { decQuad a; // working decQuad decNumber numa, numb; // working decNumbers decContext set; // working context char string[DECQUAD_String]; // number->string buffer if (argc<3) { // not enough words printf("Please supply two numbers for power(2*a, b).\n"); return 1; } decContextDefault(&set, DEC_INIT_DECQUAD); // initialize decQuadFromString(&a, argv[1], &set); // get a decQuadAdd(&a, &a, &a, &set); // double a decQuadToNumber(&a, &numa); // convert to decNumber decNumberFromString(&numb, argv[2], &set); decNumberPower(&numa, &numa, &numb, &set); // numa=numa**numb decQuadFromNumber(&a, &numa, &set); // back via a Quad decQuadToString(&a, string); // .. printf("power(2*%s, %s) => %s\n", argv[1], argv[2], string); return 0; } // main
/* decNumber doesn't provide support for conversions to 64-bit integer types, so do it the hard way. */ INT_TYPE DFP_TO_INT (DFP_C_TYPE x) { /* decNumber's decimal* types have the same format as C's _Decimal* types, but they have different calling conventions. */ /* TODO: Decimal float to integer conversions should raise FE_INVALID if the result value does not fit into the result type. */ IEEE_TYPE s; char buf[BUFMAX]; char *pos; decNumber qval, n1, n2; decContext context; /* Use a large context to avoid losing precision. */ decContextDefault (&context, DEC_INIT_DECIMAL128); /* Need non-default rounding mode here. */ context.round = DEC_ROUND_DOWN; HOST_TO_IEEE (x, &s); TO_INTERNAL (&s, &n1); /* Rescale if the exponent is less than zero. */ decNumberToIntegralValue (&n2, &n1, &context); /* Get a value to use for the quantize call. */ decNumberFromString (&qval, (char *) "1.", &context); /* Force the exponent to zero. */ decNumberQuantize (&n1, &n2, &qval, &context); /* Get a string, which at this point will not include an exponent. */ decNumberToString (&n1, buf); /* Ignore the fractional part. */ pos = strchr (buf, '.'); if (pos) *pos = 0; /* Use a C library function to convert to the integral type. */ return STR_TO_INT (buf, NULL, 10); }
static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y) { decContext context; decNumber dn_result; DEC_TYPE result; decNumber dn_x; decNumber dn_y; decNumber dn_diff; DEC_TYPE temp_diff; DEC_TYPE temp_result; FUNC_CONVERT_TO_DN (&x, &dn_x); FUNC_CONVERT_TO_DN (&y, &dn_y); if(decNumberIsNaN (&dn_x) || decNumberIsNaN (&dn_y)) return x; decContextDefault (&context, DEFAULT_CONTEXT); decNumberSubtract (&dn_diff, &dn_x, &dn_y, &context); decNumberSubtract (&dn_result, &dn_x, &dn_x, &context); FUNC_CONVERT_FROM_DN (&dn_diff, &temp_diff, &context); FUNC_CONVERT_FROM_DN (&dn_result, &temp_result, &context); if(temp_diff>temp_result) decNumberAdd (&dn_result,&dn_result,&dn_diff,&context); /* if(decCompare (&dn_diff,&dn_result) == 1) decNumberAdd (&dn_result,&dn_result,&dn_diff,&context); */ FUNC_CONVERT_FROM_DN (&dn_result, &result, &context); if (context.status & DEC_Overflow) DFP_EXCEPT (FE_OVERFLOW); return result; }
int main(int argc, char *argv[]) { decNumber a, b; // working numbers decContext set; // working context char string[DECNUMDIGITS+14]; // conversion buffer decContextTestEndian(0); // warn if DECLITEND is wrong if (argc<3) { // not enough words printf("Please supply two numbers to add.\n"); return 1; } decContextDefault(&set, DEC_INIT_BASE); // initialize set.traps=0; // no traps, thank you set.digits=DECNUMDIGITS; // set precision decNumberFromString(&a, argv[1], &set); decNumberFromString(&b, argv[2], &set); decNumberAdd(&a, &a, &b, &set); // a=a+b decNumberToString(&a, string); printf("%s + %s => %s\n", argv[1], argv[2], string); return 0; } // main
static void decimal_from_decnumber (REAL_VALUE_TYPE *r, decNumber *dn, decContext *context) { memset (r, 0, sizeof (REAL_VALUE_TYPE)); r->cl = rvc_normal; if (decNumberIsNaN (dn)) r->cl = rvc_nan; if (decNumberIsInfinite (dn)) r->cl = rvc_inf; if (context->status & DEC_Overflow) r->cl = rvc_inf; if (decNumberIsNegative (dn)) r->sign = 1; r->decimal = 1; if (r->cl != rvc_normal) return; decContextDefault (context, DEC_INIT_DECIMAL128); context->traps = 0; decimal128FromNumber ((decimal128 *) r->sig, dn, context); }