bool CodeInterval::update(const Interval& symbol) throw(not_normalized, invalid_symbol) { if(!is_normalized()) { throw not_normalized("Interval must be normalized before update."); } if(symbol.range < 3 || symbol.base + symbol.range < symbol.base) { throw invalid_symbol("Invalid symbol interval."); } // Calculate the new base uint64 h, l; std::tie(h, l) = mul128(symbol.base, range); std::tie(h, l) = add128(h, l, symbol.base); const uint64 t = h + (l > 0 ? 1 : 0); base += t; // Calculate the new range std::tie(h, l) = mul128(symbol.base + symbol.range, range); std::tie(h, l) = add128(h, l, symbol.base + symbol.range); std::tie(h, l) = add128(h, l, range); std::tie(h, l) = add128(h, l, 1); range = h - t - 1; // Return carry return base < t; }
void float128_rem () { signed int expDiff; long long int aSig1; long long int sigMean1; if (-64 < expDiff) shift128Right (-expDiff, &aSig1); add128 (&sigMean1); }
/* * When decoding, this routine is called to figure out which symbol * is presently waiting to be decoded. This routine expects to get * the current model scale in the s->scale parameter, and it returns * a count that corresponds to the present floating point code: * * code = count / s->scale */ unsigned long long get_current_count( SYMBOL *s ) { unsigned long long range = (unsigned long long) ( high - low ) + 1; unsigned long long z = (unsigned long long)(code - low) + 1; qofint128 one = {0, 1, 1, 0}; qofint128 a = mult128(z, s->scale); qofint128 b = add128(a, one); qofint128 c = div128(b, range); return c.lo; }
/* executes single exponent reduction cycle */ static Bit64u remainder_kernel(Bit64u aSig0, Bit64u bSig, int expDiff, Bit64u *zSig0, Bit64u *zSig1) { Bit64u term0, term1; Bit64u aSig1 = 0; shortShift128Left(aSig1, aSig0, expDiff, &aSig1, &aSig0); Bit64u q = estimateDiv128To64(aSig1, aSig0, bSig); mul64To128(bSig, q, &term0, &term1); sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); while ((Bit64s)(*zSig1) < 0) { --q; add128(*zSig1, *zSig0, 0, bSig, zSig1, zSig0); } return q; }
void atoi128(const char* s, number &numlo, number &numhi) { numlo = 0; numhi = 0; for (;;) { const unsigned char d = static_cast<unsigned char>(*(s++) - '0'); if (d > 9) { break; } number k[2]; k[0] = _umul128(numlo, 10, &k[1]); k[1] += numhi * 10; add128(k[0], k[1], d, 0, k, k + 1); numlo = k[0]; numhi = k[1]; } }
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how) { gnc_numeric sum; if (gnc_numeric_check(a) || gnc_numeric_check(b)) { return gnc_numeric_error(GNC_ERROR_ARG); } if ((denom == GNC_DENOM_AUTO) && (how & GNC_NUMERIC_DENOM_MASK) == GNC_HOW_DENOM_FIXED) { if (a.denom == b.denom) { denom = a.denom; } else if (b.num == 0) { denom = a.denom; b.denom = a.denom; } else if (a.num == 0) { denom = b.denom; a.denom = b.denom; } else { return gnc_numeric_error(GNC_ERROR_DENOM_DIFF); } } if (a.denom < 0) { a.num *= -a.denom; /* BUG: overflow not handled. */ a.denom = 1; } if (b.denom < 0) { b.num *= -b.denom; /* BUG: overflow not handled. */ b.denom = 1; } /* Get an exact answer.. same denominator is the common case. */ if (a.denom == b.denom) { sum.num = a.num + b.num; /* BUG: overflow not handled. */ sum.denom = a.denom; } else { /* We want to do this: * sum.num = a.num*b.denom + b.num*a.denom; * sum.denom = a.denom*b.denom; * but the multiply could overflow. * Computing the LCD minimizes likelihood of overflow */ gint64 lcd; qofint128 ca, cb, cab; lcd = gnc_numeric_lcd(a, b); if (GNC_ERROR_ARG == lcd) { return gnc_numeric_error(GNC_ERROR_OVERFLOW); } ca = mult128 (a.num, lcd / a.denom); if (ca.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW); cb = mult128 (b.num, lcd / b.denom); if (cb.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW); cab = add128 (ca, cb); if (cab.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW); sum.num = cab.lo; if (cab.isneg) sum.num = -sum.num; sum.denom = lcd; } if ((denom == GNC_DENOM_AUTO) && ((how & GNC_NUMERIC_DENOM_MASK) == GNC_HOW_DENOM_LCD)) { denom = gnc_numeric_lcd(a, b); how = how & GNC_NUMERIC_RND_MASK; } return gnc_numeric_convert(sum, denom, how); }
static void neg128 (uint64_t *plow, uint64_t *phigh) { *plow = ~*plow; *phigh = ~*phigh; add128(plow, phigh, 1, 0); }