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 }
DEC_TYPE INTERNAL_FUNCTION_NAME (DEC_TYPE x) { decContext context; decNumber dn_result; DEC_TYPE result, one; decNumber dn_x, dn_one; one = DFP_CONSTANT(1.0); FUNC_CONVERT_TO_DN (&one, &dn_one); FUNC_CONVERT_TO_DN (&x, &dn_x); if (decNumberIsNaN (&dn_x) || decNumberIsZero (&dn_x) || decNumberIsInfinite (&dn_x)) { return x + x; } decContextDefault (&context, DEFAULT_CONTEXT); /* using trig identity: acosh(x) = log(x+sqrt(x*x-1)) */ decNumberMultiply (&dn_result, &dn_x, &dn_x, &context); decNumberAdd (&dn_result, &dn_result, &dn_one, &context); decNumberSquareRoot (&dn_result, &dn_result, &context); decNumberAdd (&dn_result, &dn_result, &dn_x, &context); decNumberLn (&dn_result, &dn_result, &context); FUNC_CONVERT_FROM_DN (&dn_result, &result, &context); return result; }
void* decSingleMultiply (decSingle* _0, const decSingle* _1, const decSingle* _2, decContext* ctx) noexcept { decNumber _0num; decNumber _1num; decNumber _2num; decSingleToNumber (_1, &_1num); decSingleToNumber (_2, &_2num); decNumberMultiply (&_0num, &_1num, &_2num, ctx); return decSingleFromNumber (_0, &_0num, ctx); }
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]"); } decNumberMultiply(&m_value, &m_value, &rhs.m_value, &m_context); return *this; }
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
/* Compute a factorial. * Currently, only for positive integer arguments. Needs to be extended * to a full gamma function. */ decNumber *decNumberFactorial(decNumber *r, const decNumber *x, decContext *ctx) { decNumber y, const_1; int_to_dn(&const_1, 1, ctx); decNumberCopy(&y, x); if (!decNumberIsNegative(x) || decNumberIsZero(x)) { decNumberCopy(r, &const_1); for (;;) { if (decNumberIsZero(&y)) break; if (decNumberIsInfinite(r)) break; decNumberMultiply(r, r, &y, ctx); decNumberSubtract(&y, &y, &const_1, ctx); } } return r; }
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::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; }