static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE x) { decContext context; decNumber dn_result; DEC_TYPE result, one, temp; decNumber dn_x, dn_temp, dn_one; /* int comp;*/ one=DFP_CONSTANT(1.0); FUNC_CONVERT_TO_DN (&one, &dn_one); FUNC_CONVERT_TO_DN (&x, &dn_x); /* Handle NaN and early exit for x==0 */ if (decNumberIsNaN (&dn_x) || decNumberIsZero (&dn_x)) return x + x; decContextDefault (&context, DEFAULT_CONTEXT); decNumberAbs (&dn_temp, &dn_x, &context); FUNC_CONVERT_FROM_DN (&dn_temp, &temp, &context); if(temp==one) { /* |x| == 1 -> Pole Error */ DFP_EXCEPT (FE_DIVBYZERO); return decNumberIsNegative(&dn_x) ? -DFP_HUGE_VAL:DFP_HUGE_VAL; } else if (temp>one) { /* |x| > 1 -> Domain Error (this handles +-Inf too) */ DFP_EXCEPT (FE_INVALID); return DFP_NAN; } // comp = decCompare (&dn_temp, &dn_one); // switch (comp) // { // case 0: /* |x| == 1 -> Pole Error */ // DFP_EXCEPT (FE_DIVBYZERO); // return decNumberIsNegative(&dn_x) ? -DFP_HUGE_VAL:DFP_HUGE_VAL; // case 1: /* |x| > 1 -> Domain Error (this handles +-Inf too) */ // DFP_EXCEPT (FE_INVALID); // return DFP_NAN; // } /* Using trig identity: atanh(x) = 1/2 * log((1+x)/(1-x)) */ decNumberAdd (&dn_result, &dn_one, &dn_x, &context); decNumberSubtract (&dn_temp, &dn_one, &dn_x, &context); decNumberDivide (&dn_result, &dn_result, &dn_temp, &context); decNumberLn (&dn_result, &dn_result, &context); decNumberAdd (&dn_temp, &dn_one, &dn_one, &context); /* 2 */ decNumberDivide (&dn_result, &dn_result, &dn_temp, &context); FUNC_CONVERT_FROM_DN (&dn_result, &result, &context); return result; }
void zetadk(decNumber *dk, int n, int k, decContext *ctx) { int i; decNumber t, r, s, v, sum, const_4; int_to_dn(&const_4, 4, ctx); decNumberZero(&sum); for (i=0; i<=k; i++) { int_to_dn(&t, n+i-1, ctx); decNumberFactorial(&s, &t, ctx); int_to_dn(&t, i, ctx); decNumberPower(&r, &const_4, &t, ctx); decNumberMultiply(&v, &s, &r, ctx); int_to_dn(&t, n-i, ctx); decNumberFactorial(&s, &t, ctx); int_to_dn(&t, 2*i, ctx); decNumberFactorial(&r, &t, ctx); decNumberMultiply(&t, &r, &s, ctx); decNumberDivide(&r, &v, &t, ctx); decNumberAdd(&sum, &sum, &r, ctx); } int_to_dn(&t, n, ctx); #if 1 // Don't bother rounding to int, the conversion in compile_consts // will do this if required due to the extra precision being carries. decNumberMultiply(dk, &t, &sum, ctx); #else // We can round this to integers this way.... decNumberMultiply(&s, &t, &sum, ctx); decNumberToIntegralValue(dk, &s, ctx); #endif }
void* decSingleDivide (decSingle* _0, const decSingle* _1, const decSingle* _2, decContext* ctx) noexcept { decNumber _0num; decNumber _1num; decNumber _2num; decSingleToNumber (_1, &_1num); decSingleToNumber (_2, &_2num); decNumberDivide (&_0num, &_1num, &_2num, ctx); return decSingleFromNumber (_0, &_0num, ctx); }
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
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
const DecimalDecNumber &DecimalDecNumber::operator /=(const DecimalDecNumber &rhs) { if (decNumberIsNaN(&m_value) || decNumberIsNaN(&rhs.m_value)) { // FTHROW(InvalidStateException, "Performing arithmetic on uninitialised decimal [Nan]"); throw("Performing arithmetic on uninitialised decimal [Nan]"); } if (decNumberIsZero(&rhs.m_value)) { // FTHROW(LogicError, "Division by zero"); throw("Division by zero"); } if (decNumberIsInfinite(&m_value) || decNumberIsInfinite(&rhs.m_value)) { throw("Cannot divide infinity by infinity"); } decNumberDivide(&m_value, &m_value, &rhs.m_value, &m_context); return *this; }
static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y) { decContext context; decNumber dn_result; DEC_TYPE result; DEC_TYPE absx; decNumber dn_x; decNumber dn_absx; decNumber dn_y; decNumber dn_one; decNumber dn_two; decNumber dn_temp; decNumber dn_temp2; decNumber dn_temp3; int y_is_int; int y_is_oddint=0; int abs_x_vs_1; DEC_TYPE one = DFP_CONSTANT(1.0); DEC_TYPE two = DFP_CONSTANT(2.0); FUNC_CONVERT_TO_DN (&x, &dn_x); FUNC_CONVERT_TO_DN (&y, &dn_y); FUNC_CONVERT_TO_DN (&one, &dn_one); decContextDefault (&context, DEFAULT_CONTEXT); if (decNumberIsZero (&dn_y)) return one; if (decNumberIsNaN (&dn_x)) return x+x; decNumberAbs (&dn_absx, &dn_x, &context); FUNC_CONVERT_FROM_DN (&dn_absx, &absx, &context); if(absx<one) abs_x_vs_1 = -1; else if (absx==one) abs_x_vs_1 = 0; else abs_x_vs_1 = 1; /* abs_x_vs_1 = decCompare(&dn_absx, &dn_one); */ if(abs_x_vs_1 == 0 && !decNumberIsNegative (&dn_x)) /* If x == +1 */ return one; if (decNumberIsNaN (&dn_y)) return y+y; /* Detect if y is odd/an integer */ decNumberToIntegralValue (&dn_temp, &dn_y, &context); decNumberSubtract (&dn_temp2, &dn_temp, &dn_y, &context); y_is_int = decNumberIsZero (&dn_temp2); if (y_is_int) { FUNC_CONVERT_TO_DN (&two, &dn_two); decNumberDivide (&dn_temp, &dn_y, &dn_two, &context); decNumberToIntegralValue (&dn_temp2, &dn_temp, &context); decNumberSubtract (&dn_temp3, &dn_temp2, &dn_temp, &context); y_is_oddint = !decNumberIsZero (&dn_temp3); } /* Handle all special cases for which x = +-0 */ if (decNumberIsZero (&dn_x)) { if(decNumberIsNegative (&dn_y)) { if (decNumberIsInfinite (&dn_y)) /* +-0^-Inf = +Inf */ return -y; /* Pole Error for x = +-0, y < 0 */ DFP_EXCEPT (FE_DIVBYZERO); return decNumberIsNegative(&dn_x) && y_is_oddint ? -DFP_HUGE_VAL : DFP_HUGE_VAL; } return decNumberIsNegative(&dn_x) && y_is_oddint ? -DFP_CONSTANT(0.0) : DFP_CONSTANT(0.0); } /* Handle remaining special cases for x = +-Inf or y = +-Inf */ if (decNumberIsInfinite (&dn_x) || decNumberIsInfinite (&dn_y)) { if (abs_x_vs_1 == 0) /* If (-1)^(+-Inf) */ return one; if (abs_x_vs_1 < 0) /* x^(+-Inf), where 0<x<1 */ return decNumberIsNegative (&dn_y) ? DFP_HUGE_VAL : DFP_CONSTANT(0.0); if (decNumberIsNegative (&dn_y)) result = DFP_CONSTANT(0.0); else result = (DEC_TYPE)DEC_INFINITY; if (y_is_oddint && decNumberIsNegative(&dn_x)) result = -result; return result; } /* Domain Error: x < 0 && y is a finite non-int */ if (decNumberIsNegative (&dn_x) && !y_is_int) { DFP_EXCEPT (FE_INVALID); return DFP_NAN; } decNumberPower (&dn_result, &dn_x, &dn_y, &context); FUNC_CONVERT_FROM_DN (&dn_result, &result, &context); if (context.status & DEC_Overflow) DFP_EXCEPT (FE_OVERFLOW); if (context.status & DEC_Underflow) DFP_EXCEPT (FE_UNDERFLOW); return result; }
const DecimalDecNumber DecimalDecNumber::round(uint32 decimalPlaces, RoundingMode mode, RoundIncrement roundIncrement) { if (isZero()) return *this; if (roundIncrement == RoundIncrement::HALF) decNumberMultiply(&m_value, &m_value, &DecimalDecNumber::TWO.m_value, &m_context); else if (roundIncrement == RoundIncrement::QUARTER) decNumberMultiply(&m_value, &m_value, &DecimalDecNumber::FOUR.m_value, &m_context); static const int BUFFER_SIZE = 256; char buffer[BUFFER_SIZE]; decNumberToString(&m_value, buffer); char * b = buffer; char * e = buffer + strlen(buffer); char * f = std::find(b, e, 'E'); if (f != e && (f+1) != e) { unpackScientificFormat(b, e, BUFFER_SIZE, 48); e = buffer + strlen(buffer); } const char * point = std::find(buffer, e, '.'); const char * firstNonZeroDigitAfterDecimal = point; while (firstNonZeroDigitAfterDecimal != e && (*firstNonZeroDigitAfterDecimal < '1' || *firstNonZeroDigitAfterDecimal > '9')) { ++firstNonZeroDigitAfterDecimal; } if (firstNonZeroDigitAfterDecimal != e) { decContext tempContext; decContextDefault(&tempContext, DEC_INIT_BASE); tempContext.traps = 0; // DecNumber rounding is expressed in significant figures; we want to round to a fixed number of decimal places. const char * firstDigit = *buffer == '-' ? (buffer+1) : buffer; const bool absValueLessThanOne = *firstDigit == '0'; if (absValueLessThanOne) { tempContext.digits = decimalPlaces - (firstNonZeroDigitAfterDecimal - point - 1); } else { tempContext.digits = decimalPlaces + (point - firstDigit); } if (tempContext.digits < 0) { decNumberFromInt32(&m_value, 0); return *this; } switch (mode) { case RoundingMode::ROUND_HALF_TO_POSITIVE_INFINITY: tempContext.round = isNegative() ? DEC_ROUND_HALF_DOWN : DEC_ROUND_HALF_UP; break; case RoundingMode::ROUND_HALF_TO_NEGATIVE_INFINITY: tempContext.round = isNegative() ? DEC_ROUND_HALF_UP : DEC_ROUND_HALF_DOWN; break; case RoundingMode::ROUND_TO_POSITIVE_INFINITY: tempContext.round = isNegative() ? DEC_ROUND_DOWN : DEC_ROUND_UP; break; case RoundingMode::ROUND_TO_NEGATIVE_INFINITY: tempContext.round = isNegative() ? DEC_ROUND_UP : DEC_ROUND_DOWN; break; case RoundingMode::ROUND_AWAY_FROM_ZERO: tempContext.round = DEC_ROUND_UP; break; case RoundingMode::ROUND_TO_ZERO: tempContext.round = DEC_ROUND_DOWN; break; case RoundingMode::ROUND_HALF_AWAY_FROM_ZERO: tempContext.round = DEC_ROUND_HALF_UP; break; case RoundingMode::ROUND_HALF_TO_ZERO: tempContext.round = DEC_ROUND_HALF_DOWN; break; case RoundingMode::ROUND_HALF_TO_EVEN: tempContext.round = DEC_ROUND_HALF_EVEN; break; default : throw("Rounding mode is not supported - rounding using default mode which is DEC_ROUND_HALF_AWAY_FROM_ZERO"); // LCRIT("Rounding mode[%d] is not supported - rounding using default mode which is DEC_ROUND_HALF_AWAY_FROM_ZERO", mode); // tempContext.round = DEC_ROUND_HALF_UP; } decNumberFromString(&m_value, buffer, &tempContext); } if (roundIncrement == RoundIncrement::HALF) decNumberDivide(&m_value, &m_value, &DecimalDecNumber::TWO.m_value, &m_context); else if (roundIncrement == RoundIncrement::QUARTER) decNumberDivide(&m_value, &m_value, &DecimalDecNumber::FOUR.m_value, &m_context); return *this; }