#include "mpdecimal.h"
#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "basearith.h"
#include "bits.h"
#include "constants.h"
#include "convolute.h"
#include "crt.h"
#include "mpalloc.h"
#include "typearith.h"
#ifdef PPRO
#if defined(_MSC_VER)
#include <float.h>
#pragma float_control(precise, on)
#pragma fenv_access(on)
#elif !defined(__OpenBSD__) && !defined(__NetBSD__)
#include <fenv.h>
#pragma STDC FENV_ACCESS ON
#endif
#endif
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && __GNUC__ >= 7
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
#if defined(_MSC_VER)
#define ALWAYS_INLINE …
#elif defined (__IBMC__) || defined(LEGACY_COMPILER)
#define ALWAYS_INLINE
#undef inline
#define inline
#else
#ifdef TEST_COVERAGE
#define ALWAYS_INLINE
#else
#define ALWAYS_INLINE …
#endif
#endif
#if defined(__SIZEOF_INT128__) && defined(__clang__) && defined(_MSC_VER)
#undef __SIZEOF_INT128__
#endif
#define MPD_NEWTONDIV_CUTOFF …
#define MPD_NEW_STATIC(name, flags, exp, digits, len) …
#define MPD_NEW_CONST(name, flags, exp, digits, len, alloc, initval) …
#define MPD_NEW_SHARED(name, a) …
static mpd_uint_t data_one[1] = …;
static mpd_uint_t data_zero[1] = …;
static const mpd_t one = …;
static const mpd_t minus_one = …;
static const mpd_t zero = …;
static inline void _mpd_check_exp(mpd_t *dec, const mpd_context_t *ctx,
uint32_t *status);
static void _settriple(mpd_t *result, uint8_t sign, mpd_uint_t a,
mpd_ssize_t exp);
static inline mpd_ssize_t _mpd_real_size(mpd_uint_t *data, mpd_ssize_t size);
static int _mpd_cmp_abs(const mpd_t *a, const mpd_t *b);
static void _mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status);
static inline void _mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status);
static void _mpd_base_ndivmod(mpd_t *q, mpd_t *r, const mpd_t *a,
const mpd_t *b, uint32_t *status);
static inline void _mpd_qpow_uint(mpd_t *result, const mpd_t *base,
mpd_uint_t exp, uint8_t resultsign,
const mpd_context_t *ctx, uint32_t *status);
static mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n);
const char *
mpd_version(void)
{ … }
#ifdef CONFIG_64
ALWAYS_INLINE int
mpd_word_digits(mpd_uint_t word)
{ … }
#else
ALWAYS_INLINE int
mpd_word_digits(mpd_uint_t word)
{
if (word < mpd_pow10[4]) {
if (word < mpd_pow10[2]) {
return (word < mpd_pow10[1]) ? 1 : 2;
}
return (word < mpd_pow10[3]) ? 3 : 4;
}
if (word < mpd_pow10[6]) {
return (word < mpd_pow10[5]) ? 5 : 6;
}
if (word < mpd_pow10[8]) {
return (word < mpd_pow10[7]) ? 7 : 8;
}
return (word < mpd_pow10[9]) ? 9 : 10;
}
#endif
ALWAYS_INLINE mpd_ssize_t
mpd_adjexp(const mpd_t *dec)
{ … }
ALWAYS_INLINE mpd_ssize_t
mpd_etiny(const mpd_context_t *ctx)
{ … }
ALWAYS_INLINE mpd_ssize_t
mpd_etop(const mpd_context_t *ctx)
{ … }
ALWAYS_INLINE mpd_uint_t
mpd_msword(const mpd_t *dec)
{ … }
inline mpd_uint_t
mpd_msd(mpd_uint_t word)
{ … }
ALWAYS_INLINE mpd_uint_t
mpd_lsd(mpd_uint_t word)
{ … }
mpd_ssize_t
mpd_digits_to_size(mpd_ssize_t digits)
{ … }
inline int
mpd_exp_digits(mpd_ssize_t exp)
{ … }
ALWAYS_INLINE int
mpd_iscanonical(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_isfinite(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_isinfinite(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_isnan(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_isnegative(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_ispositive(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_isqnan(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_issigned(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_issnan(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_isspecial(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_iszero(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_iszerocoeff(const mpd_t *dec)
{ … }
inline int
mpd_isnormal(const mpd_t *dec, const mpd_context_t *ctx)
{ … }
inline int
mpd_issubnormal(const mpd_t *dec, const mpd_context_t *ctx)
{ … }
ALWAYS_INLINE int
mpd_isoddword(mpd_uint_t word)
{ … }
ALWAYS_INLINE int
mpd_isoddcoeff(const mpd_t *dec)
{ … }
ALWAYS_INLINE uint8_t
mpd_sign(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_arith_sign(const mpd_t *dec)
{ … }
ALWAYS_INLINE long
mpd_radix(void)
{ … }
ALWAYS_INLINE int
mpd_isdynamic(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_isstatic(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_isdynamic_data(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_isstatic_data(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_isshared_data(const mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_isconst_data(const mpd_t *dec)
{ … }
ALWAYS_INLINE void
mpd_uint_zero(mpd_uint_t *dest, mpd_size_t len)
{ … }
ALWAYS_INLINE void
mpd_del(mpd_t *dec)
{ … }
ALWAYS_INLINE int
mpd_qresize(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
{ … }
static ALWAYS_INLINE int
mpd_qresize_cxx(mpd_t *result, mpd_ssize_t nwords)
{ … }
ALWAYS_INLINE int
mpd_qresize_zero(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
{ … }
ALWAYS_INLINE void
mpd_minalloc(mpd_t *result)
{ … }
int
mpd_resize(mpd_t *result, mpd_ssize_t nwords, mpd_context_t *ctx)
{ … }
int
mpd_resize_zero(mpd_t *result, mpd_ssize_t nwords, mpd_context_t *ctx)
{ … }
inline void
mpd_setdigits(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_sign(mpd_t *result, uint8_t sign)
{ … }
ALWAYS_INLINE void
mpd_signcpy(mpd_t *result, const mpd_t *a)
{ … }
ALWAYS_INLINE void
mpd_set_infinity(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_qnan(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_snan(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_negative(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_positive(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_dynamic(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_static(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_dynamic_data(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_static_data(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_shared_data(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_const_data(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_clear_flags(mpd_t *result)
{ … }
ALWAYS_INLINE void
mpd_set_flags(mpd_t *result, uint8_t flags)
{ … }
ALWAYS_INLINE void
mpd_copy_flags(mpd_t *result, const mpd_t *a)
{ … }
static inline void
mpd_workcontext(mpd_context_t *workctx, const mpd_context_t *ctx)
{ … }
static inline void
_mpd_negate(mpd_t *dec)
{ … }
void
mpd_zerocoeff(mpd_t *result)
{ … }
void
mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status)
{ … }
static void
_mpd_cap(mpd_t *result, const mpd_context_t *ctx)
{ … }
static void
_mpd_fix_nan(mpd_t *result, const mpd_context_t *ctx)
{ … }
static inline void
_mpd_get_msdigits(mpd_uint_t *hi, mpd_uint_t *lo, const mpd_t *dec,
unsigned int n)
{ … }
static inline mpd_ssize_t
_mpd_real_size(mpd_uint_t *data, mpd_ssize_t size)
{ … }
mpd_ssize_t
mpd_trail_zeros(const mpd_t *dec)
{ … }
static int
_mpd_isint(const mpd_t *dec)
{ … }
int
mpd_isinteger(const mpd_t *dec)
{ … }
static int
mpd_word_ispow10(mpd_uint_t word)
{ … }
static int
mpd_coeff_ispow10(const mpd_t *dec)
{ … }
static int
mpd_word_isallnine(mpd_uint_t word)
{ … }
static int
mpd_coeff_isallnine(const mpd_t *dec)
{ … }
int
mpd_isodd(const mpd_t *dec)
{ … }
int
mpd_iseven(const mpd_t *dec)
{ … }
static void
_ssettriple(mpd_t *result, uint8_t sign, mpd_uint_t a, mpd_ssize_t exp)
{ … }
static void
_settriple(mpd_t *result, uint8_t sign, mpd_uint_t a, mpd_ssize_t exp)
{ … }
void
mpd_setspecial(mpd_t *result, uint8_t sign, uint8_t type)
{ … }
void
mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status)
{ … }
void
mpd_qsset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qsset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qsset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qsset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
#ifdef CONFIG_64
void
mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
#endif
void
mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
#if defined(CONFIG_32) && !defined(LEGACY_COMPILER)
static void
_c32setu64(mpd_t *result, uint64_t u, uint8_t sign, uint32_t *status)
{
mpd_uint_t w[3];
uint64_t q;
int i, len;
len = 0;
do {
q = u / MPD_RADIX;
w[len] = (mpd_uint_t)(u - q * MPD_RADIX);
u = q; len++;
} while (u != 0);
if (!mpd_qresize(result, len, status)) {
return;
}
for (i = 0; i < len; i++) {
result->data[i] = w[i];
}
mpd_set_flags(result, sign);
result->exp = 0;
result->len = len;
mpd_setdigits(result);
}
static void
_c32_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx,
uint32_t *status)
{
_c32setu64(result, a, MPD_POS, status);
mpd_qfinalize(result, ctx, status);
}
static void
_c32_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx,
uint32_t *status)
{
uint64_t u;
uint8_t sign = MPD_POS;
if (a < 0) {
if (a == INT64_MIN) {
u = (uint64_t)INT64_MAX + (-(INT64_MIN+INT64_MAX));
}
else {
u = -a;
}
sign = MPD_NEG;
}
else {
u = a;
}
_c32setu64(result, u, sign, status);
mpd_qfinalize(result, ctx, status);
}
#endif
#ifndef LEGACY_COMPILER
void
mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qset_i64_exact(mpd_t *result, int64_t a, uint32_t *status)
{ … }
void
mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qset_u64_exact(mpd_t *result, uint64_t a, uint32_t *status)
{ … }
#endif
static mpd_uint_t
_mpd_qget_uint(int use_sign, const mpd_t *a, uint32_t *status)
{ … }
mpd_uint_t
mpd_qget_uint(const mpd_t *a, uint32_t *status)
{ … }
mpd_uint_t
mpd_qabs_uint(const mpd_t *a, uint32_t *status)
{ … }
mpd_ssize_t
mpd_qget_ssize(const mpd_t *a, uint32_t *status)
{ … }
#if defined(CONFIG_32) && !defined(LEGACY_COMPILER)
static uint64_t
_c32_qget_u64(int use_sign, const mpd_t *a, uint32_t *status)
{
MPD_NEW_STATIC(tmp,0,0,20,3);
mpd_context_t maxcontext;
uint64_t ret;
tmp_data[0] = 709551615;
tmp_data[1] = 446744073;
tmp_data[2] = 18;
if (mpd_isspecial(a)) {
*status |= MPD_Invalid_operation;
return UINT64_MAX;
}
if (mpd_iszero(a)) {
return 0;
}
if (use_sign && mpd_isnegative(a)) {
*status |= MPD_Invalid_operation;
return UINT64_MAX;
}
if (!_mpd_isint(a)) {
*status |= MPD_Invalid_operation;
return UINT64_MAX;
}
if (_mpd_cmp_abs(a, &tmp) > 0) {
*status |= MPD_Invalid_operation;
return UINT64_MAX;
}
mpd_maxcontext(&maxcontext);
mpd_qrescale(&tmp, a, 0, &maxcontext, &maxcontext.status);
maxcontext.status &= ~MPD_Rounded;
if (maxcontext.status != 0) {
*status |= (maxcontext.status|MPD_Invalid_operation);
return UINT64_MAX;
}
ret = 0;
switch (tmp.len) {
case 3:
ret += (uint64_t)tmp_data[2] * 1000000000000000000ULL;
case 2:
ret += (uint64_t)tmp_data[1] * 1000000000ULL;
case 1:
ret += tmp_data[0];
break;
default:
abort();
}
return ret;
}
static int64_t
_c32_qget_i64(const mpd_t *a, uint32_t *status)
{
uint64_t u;
int isneg;
u = _c32_qget_u64(0, a, status);
if (*status&MPD_Invalid_operation) {
return INT64_MAX;
}
isneg = mpd_isnegative(a);
if (u <= INT64_MAX) {
return isneg ? -((int64_t)u) : (int64_t)u;
}
else if (isneg && u+(INT64_MIN+INT64_MAX) == INT64_MAX) {
return INT64_MIN;
}
*status |= MPD_Invalid_operation;
return INT64_MAX;
}
#endif
#ifdef CONFIG_64
uint64_t
mpd_qget_u64(const mpd_t *a, uint32_t *status)
{ … }
int64_t
mpd_qget_i64(const mpd_t *a, uint32_t *status)
{ … }
uint32_t
mpd_qget_u32(const mpd_t *a, uint32_t *status)
{ … }
int32_t
mpd_qget_i32(const mpd_t *a, uint32_t *status)
{ … }
#else
#ifndef LEGACY_COMPILER
uint64_t
mpd_qget_u64(const mpd_t *a, uint32_t *status)
{
uint32_t workstatus = 0;
uint64_t x = _c32_qget_u64(1, a, &workstatus);
*status |= workstatus;
return x;
}
int64_t
mpd_qget_i64(const mpd_t *a, uint32_t *status)
{
uint32_t workstatus = 0;
int64_t x = _c32_qget_i64(a, &workstatus);
*status |= workstatus;
return x;
}
#endif
uint32_t
mpd_qget_u32(const mpd_t *a, uint32_t *status)
{
return mpd_qget_uint(a, status);
}
int32_t
mpd_qget_i32(const mpd_t *a, uint32_t *status)
{
return mpd_qget_ssize(a, status);
}
#endif
int
mpd_qcheck_nan(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
int
mpd_qcheck_nans(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static int
mpd_qcheck_3nans(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static inline int
_mpd_rnd_incr(const mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx)
{ … }
static inline void
_mpd_apply_round(mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx,
uint32_t *status)
{ … }
static inline void
_mpd_apply_round_excess(mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx,
uint32_t *status)
{ … }
static inline int
_mpd_apply_round_fit(mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx,
uint32_t *status)
{ … }
static inline void
_mpd_check_exp(mpd_t *dec, const mpd_context_t *ctx, uint32_t *status)
{ … }
static inline void
mpd_check_underflow(mpd_t *dec, const mpd_context_t *ctx, uint32_t *status)
{ … }
static inline void
_mpd_check_round(mpd_t *dec, const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qfinalize(mpd_t *result, const mpd_context_t *ctx, uint32_t *status)
{ … }
static inline void
_mpd_copy_shared(mpd_t *dest, const mpd_t *src)
{ … }
int
mpd_qcopy(mpd_t *result, const mpd_t *a, uint32_t *status)
{ … }
int
mpd_qcopy_cxx(mpd_t *result, const mpd_t *a)
{ … }
static void
mpd_qcopy_static(mpd_t *result, const mpd_t *a)
{ … }
mpd_t *
mpd_qncopy(const mpd_t *a)
{ … }
int
mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status)
{ … }
int
mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status)
{ … }
int
mpd_qcopy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status)
{ … }
#define CMP_EQUAL_OR_RETURN(a, b) …
static int
_mpd_basecmp(mpd_uint_t *big, mpd_uint_t *small, mpd_size_t n, mpd_size_t m,
mpd_size_t shift)
{ … }
static int
_mpd_cmp_same_adjexp(const mpd_t *a, const mpd_t *b)
{ … }
static int
_mpd_cmp(const mpd_t *a, const mpd_t *b)
{ … }
static int
_mpd_cmp_abs(const mpd_t *a, const mpd_t *b)
{ … }
int
mpd_qcmp(const mpd_t *a, const mpd_t *b, uint32_t *status)
{ … }
int
mpd_qcompare(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
int
mpd_qcompare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
int
mpd_cmp_total(const mpd_t *a, const mpd_t *b)
{ … }
int
mpd_compare_total(mpd_t *result, const mpd_t *a, const mpd_t *b)
{ … }
int
mpd_cmp_total_mag(const mpd_t *a, const mpd_t *b)
{ … }
int
mpd_compare_total_mag(mpd_t *result, const mpd_t *a, const mpd_t *b)
{ … }
static inline int
_mpd_cmp_numequal(const mpd_t *a, const mpd_t *b)
{ … }
int
mpd_qshiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status)
{ … }
static mpd_uint_t
_mpd_get_rnd(const mpd_uint_t *data, mpd_ssize_t len, int use_msd)
{ … }
static mpd_uint_t
mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n)
{ … }
mpd_uint_t
mpd_qshiftr_inplace(mpd_t *result, mpd_ssize_t n)
{ … }
mpd_uint_t
mpd_qshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status)
{ … }
void
mpd_qand(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
const char *
mpd_class(const mpd_t *a, const mpd_context_t *ctx)
{ … }
void
mpd_qinvert(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qlogb(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qor(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qrotate(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qscaleb(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qshiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qshift(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qxor(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qabs(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
static inline void
_mpd_ptrswap(const mpd_t **a, const mpd_t **b)
{ … }
static void
_mpd_qaddsub_inf(mpd_t *result, const mpd_t *a, const mpd_t *b, uint8_t sign_b,
uint32_t *status)
{ … }
static void
_mpd_qaddsub(mpd_t *result, const mpd_t *a, const mpd_t *b, uint8_t sign_b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static void
_mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static void
_mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static void
_mpd_qadd_exact(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static void
_mpd_qsub_exact(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qadd_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qadd_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qsub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qsub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qadd_i32(mpd_t *result, const mpd_t *a, int32_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qadd_u32(mpd_t *result, const mpd_t *a, uint32_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
#ifdef CONFIG_64
void
mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
#elif !defined(LEGACY_COMPILER)
void
mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_i64(&bb, b, &maxcontext, status);
mpd_qadd(result, a, &bb, ctx, status);
mpd_del(&bb);
}
void
mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_u64(&bb, b, &maxcontext, status);
mpd_qadd(result, a, &bb, ctx, status);
mpd_del(&bb);
}
#endif
void
mpd_qsub_i32(mpd_t *result, const mpd_t *a, int32_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qsub_u32(mpd_t *result, const mpd_t *a, uint32_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
#ifdef CONFIG_64
void
mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
#elif !defined(LEGACY_COMPILER)
void
mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_i64(&bb, b, &maxcontext, status);
mpd_qsub(result, a, &bb, ctx, status);
mpd_del(&bb);
}
void
mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_u64(&bb, b, &maxcontext, status);
mpd_qsub(result, a, &bb, ctx, status);
mpd_del(&bb);
}
#endif
static void
_mpd_qdiv_inf(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
enum { … };
static void
_mpd_qdiv(int action, mpd_t *q, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static void
_mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qdivint(mpd_t *q, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qdiv_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qdiv_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qdiv_i32(mpd_t *result, const mpd_t *a, int32_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qdiv_u32(mpd_t *result, const mpd_t *a, uint32_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
#ifdef CONFIG_64
void
mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
#elif !defined(LEGACY_COMPILER)
void
mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_i64(&bb, b, &maxcontext, status);
mpd_qdiv(result, a, &bb, ctx, status);
mpd_del(&bb);
}
void
mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_u64(&bb, b, &maxcontext, status);
mpd_qdiv(result, a, &bb, ctx, status);
mpd_del(&bb);
}
#endif
static void
_mpd_zeropad(mpd_t *result, const mpd_context_t *ctx, uint32_t *status)
{ … }
static int
_mpd_qexp_check_one(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
static inline mpd_ssize_t
_mpd_get_exp_iterations(const mpd_t *r, mpd_ssize_t p)
{ … }
static void
_mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qfma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static inline int
ln_schedule_prec(mpd_ssize_t klist[MPD_MAX_PREC_LOG2], mpd_ssize_t maxprec,
mpd_ssize_t initprec)
{ … }
#ifdef CONFIG_64
#if MPD_RDIGITS != 19
#error "mpdecimal.c: MPD_RDIGITS must be 19."
#endif
static const mpd_uint_t mpd_ln10_data[MPD_MINALLOC_MAX] = …;
#else
#if MPD_RDIGITS != 9
#error "mpdecimal.c: MPD_RDIGITS must be 9."
#endif
static const mpd_uint_t mpd_ln10_data[MPD_MINALLOC_MAX] = {
401682692UL, 708474699UL, 720754403UL, 30896345UL, 602301057UL, 765871416UL,
192920333UL, 763113569UL, 589402567UL, 956890167UL, 82413146UL, 589257242UL,
245544057UL, 811364292UL, 734206705UL, 868569356UL, 167465505UL, 775026849UL,
706480002UL, 18064450UL, 636167921UL, 569476834UL, 734507478UL, 156591213UL,
148046637UL, 283552201UL, 677432162UL, 470806855UL, 880840126UL, 417480036UL,
210510171UL, 940440022UL, 939147961UL, 893431493UL, 436515504UL, 440424327UL,
654366747UL, 821988674UL, 622228769UL, 884616336UL, 537773262UL, 350530896UL,
319852839UL, 989482623UL, 468084379UL, 720832555UL, 168948290UL, 736909878UL,
675666628UL, 546508280UL, 863340952UL, 404228624UL, 834196778UL, 508959829UL,
23599720UL, 967735248UL, 96757260UL, 603332790UL, 862877297UL, 760110148UL,
468436420UL, 401799145UL, 299404568UL, 230258509UL
};
#endif
static const mpd_t _mpd_ln10 = …;
void
mpd_qln10(mpd_t *result, mpd_ssize_t prec, uint32_t *status)
{ … }
static const uint16_t lnapprox[900] = …;
static void
_mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
enum { … };
static void
_mpd_qlog10(int action, mpd_t *result, const mpd_t *a,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qmax(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qmax_mag(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qmin(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qmin_mag(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static inline mpd_size_t
_kmul_resultsize(mpd_size_t la, mpd_size_t lb)
{ … }
static inline mpd_size_t
_kmul_worksize(mpd_size_t n, mpd_size_t lim)
{ … }
#define MPD_KARATSUBA_BASECASE …
static void
_karatsuba_rec(mpd_uint_t *c, const mpd_uint_t *a, const mpd_uint_t *b,
mpd_uint_t *w, mpd_size_t la, mpd_size_t lb)
{ … }
static mpd_uint_t *
_mpd_kmul(const mpd_uint_t *u, const mpd_uint_t *v,
mpd_size_t ulen, mpd_size_t vlen,
mpd_size_t *rsize)
{ … }
static inline mpd_size_t
_mpd_get_transform_len(mpd_size_t rsize)
{ … }
#ifdef PPRO
#ifndef _MSC_VER
static inline unsigned short
_mpd_get_control87(void)
{
unsigned short cw;
__asm__ __volatile__ ("fnstcw %0" : "=m" (cw));
return cw;
}
static inline void
_mpd_set_control87(unsigned short cw)
{
__asm__ __volatile__ ("fldcw %0" : : "m" (cw));
}
#endif
static unsigned int
mpd_set_fenv(void)
{
unsigned int cw;
#ifdef _MSC_VER
unsigned int flags =
_EM_INVALID|_EM_DENORMAL|_EM_ZERODIVIDE|_EM_OVERFLOW|
_EM_UNDERFLOW|_EM_INEXACT|_RC_CHOP|_PC_64;
unsigned int mask = _MCW_EM|_MCW_RC|_MCW_PC;
unsigned int dummy;
__control87_2(0, 0, &cw, NULL);
__control87_2(flags, mask, &dummy, NULL);
#else
cw = _mpd_get_control87();
_mpd_set_control87(cw|0xF3F);
#endif
return cw;
}
static void
mpd_restore_fenv(unsigned int cw)
{
#ifdef _MSC_VER
unsigned int mask = _MCW_EM|_MCW_RC|_MCW_PC;
unsigned int dummy;
__control87_2(cw, mask, &dummy, NULL);
#else
_mpd_set_control87((unsigned short)cw);
#endif
}
#endif
static mpd_uint_t *
_mpd_fntmul(const mpd_uint_t *u, const mpd_uint_t *v,
mpd_size_t ulen, mpd_size_t vlen,
mpd_size_t *rsize)
{ … }
static int
_karatsuba_rec_fnt(mpd_uint_t *c, const mpd_uint_t *a, const mpd_uint_t *b,
mpd_uint_t *w, mpd_size_t la, mpd_size_t lb)
{ … }
static mpd_uint_t *
_mpd_kmul_fnt(const mpd_uint_t *u, const mpd_uint_t *v,
mpd_size_t ulen, mpd_size_t vlen,
mpd_size_t *rsize)
{ … }
static void
_mpd_qmul_inf(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status)
{ … }
static inline void
_mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static void
_mpd_qmul_exact(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qmul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qmul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qmul_i32(mpd_t *result, const mpd_t *a, int32_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qmul_u32(mpd_t *result, const mpd_t *a, uint32_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
#ifdef CONFIG_64
void
mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
#elif !defined(LEGACY_COMPILER)
void
mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_i64(&bb, b, &maxcontext, status);
mpd_qmul(result, a, &bb, ctx, status);
mpd_del(&bb);
}
void
mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b,
const mpd_context_t *ctx, uint32_t *status)
{
mpd_context_t maxcontext;
MPD_NEW_STATIC(bb,0,0,0,0);
mpd_maxcontext(&maxcontext);
mpd_qset_u64(&bb, b, &maxcontext, status);
mpd_qmul(result, a, &bb, ctx, status);
mpd_del(&bb);
}
#endif
void
mpd_qminus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qplus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qnext_minus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qnext_plus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qnext_toward(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static inline void
_mpd_qpow_uint(mpd_t *result, const mpd_t *base, mpd_uint_t exp,
uint8_t resultsign, const mpd_context_t *ctx, uint32_t *status)
{ … }
static inline void
_mpd_qpow_mpd(mpd_t *result, mpd_t *tbase, mpd_t *texp, uint8_t resultsign,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static void
_mpd_qpow_int(mpd_t *result, const mpd_t *base, const mpd_t *exp,
uint8_t resultsign,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static int
_qcheck_pow_one_inf(mpd_t *result, const mpd_t *base, uint8_t resultsign,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static int
_qcheck_pow_one(mpd_t *result, const mpd_t *base, const mpd_t *exp,
uint8_t resultsign,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static mpd_ssize_t
_lower_bound_zeta(const mpd_t *x, uint32_t *status)
{ … }
static int
_qcheck_pow_bounds(mpd_t *result, const mpd_t *x, const mpd_t *y,
uint8_t resultsign,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static void
_mpd_qpow_real(mpd_t *result, const mpd_t *base, const mpd_t *exp,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qpow(mpd_t *result, const mpd_t *base, const mpd_t *exp,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static inline void
_mpd_qpowmod_uint(mpd_t *result, mpd_t *base, mpd_uint_t exp,
const mpd_t *mod, uint32_t *status)
{ … }
void
mpd_qpowmod(mpd_t *result, const mpd_t *base, const mpd_t *exp,
const mpd_t *mod,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qquantize(mpd_t *result, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qreduce(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qrem(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b,
const mpd_context_t *ctx, uint32_t *status)
{ … }
static void
_mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qrescale_fmt(mpd_t *result, const mpd_t *a, mpd_ssize_t exp,
const mpd_context_t *ctx, uint32_t *status)
{ … }
enum { … };
static void
_mpd_qround_to_integral(int action, mpd_t *result, const mpd_t *a,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
int
mpd_same_quantum(const mpd_t *a, const mpd_t *b)
{ … }
static inline int
recpr_schedule_prec(mpd_ssize_t klist[MPD_MAX_PREC_LOG2],
mpd_ssize_t maxprec, mpd_ssize_t initprec)
{ … }
static void
_mpd_qreciprocal_approx(mpd_t *z, const mpd_t *v, uint32_t *status)
{ … }
static void
_mpd_qreciprocal(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
static void
_mpd_base_ndivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b,
uint32_t *status)
{ … }
static inline int
invroot_schedule_prec(mpd_ssize_t klist[MPD_MAX_PREC_LOG2],
mpd_ssize_t maxprec, mpd_ssize_t initprec)
{ … }
static inline void
_invroot_init_approx(mpd_t *z, mpd_uint_t vhat)
{ … }
static void
_mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
static void
_mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
void
mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
uint32_t *status)
{ … }
size_t
mpd_sizeinbase(const mpd_t *a, uint32_t base)
{ … }
static mpd_ssize_t
_mpd_importsize(size_t srclen, uint32_t base)
{ … }
static uint8_t
mpd_resize_u16(uint16_t **w, size_t nmemb)
{ … }
static uint8_t
mpd_resize_u32(uint32_t **w, size_t nmemb)
{ … }
static size_t
_baseconv_to_u16(uint16_t **w, size_t wlen, mpd_uint_t wbase,
mpd_uint_t *u, mpd_ssize_t ulen)
{ … }
static size_t
_coeff_from_u16(mpd_t *w, mpd_ssize_t wlen,
const mpd_uint_t *u, size_t ulen, uint32_t ubase,
uint32_t *status)
{ … }
static size_t
_baseconv_to_smaller(uint32_t **w, size_t wlen, uint32_t wbase,
mpd_uint_t *u, mpd_ssize_t ulen, mpd_uint_t ubase)
{ … }
#ifdef CONFIG_32
static size_t
_copy_equal_base(uint32_t **w, size_t wlen,
const uint32_t *u, size_t ulen)
{
if (wlen < ulen) {
if (!mpd_resize_u32(w, ulen)) {
return SIZE_MAX;
}
}
memcpy(*w, u, ulen * (sizeof **w));
return ulen;
}
static size_t
_baseconv_to_larger(uint32_t **w, size_t wlen, mpd_uint_t wbase,
const mpd_uint_t *u, size_t ulen, mpd_uint_t ubase)
{
size_t n = 0;
mpd_uint_t carry;
assert(wlen > 0 && ulen > 0);
assert(ubase < wbase);
(*w)[n++] = u[--ulen];
while (--ulen != SIZE_MAX) {
carry = _mpd_shortmul_b(*w, *w, n, ubase, wbase);
if (carry) {
if (n >= wlen) {
if (!mpd_resize_u32(w, n+1)) {
return SIZE_MAX;
}
wlen = n+1;
}
(*w)[n++] = carry;
}
carry = _mpd_shortadd_b(*w, n, u[ulen], wbase);
if (carry) {
if (n >= wlen) {
if (!mpd_resize_u32(w, n+1)) {
return SIZE_MAX;
}
wlen = n+1;
}
(*w)[n++] = carry;
}
}
return n;
}
static size_t
_coeff_from_larger_base(mpd_t *w, size_t wlen, mpd_uint_t wbase,
mpd_uint_t *u, mpd_ssize_t ulen, mpd_uint_t ubase,
uint32_t *status)
{
size_t n = 0;
assert(wlen > 0 && ulen > 0);
assert(wbase < ubase);
do {
if (n >= wlen) {
if (!mpd_qresize(w, n+1, status)) {
return SIZE_MAX;
}
wlen = n+1;
}
w->data[n++] = (uint32_t)_mpd_shortdiv_b(u, u, ulen, wbase, ubase);
ulen = _mpd_real_size(u, ulen);
} while (u[ulen-1] != 0);
return n;
}
#endif
static size_t
_coeff_from_smaller_base(mpd_t *w, mpd_ssize_t wlen, mpd_uint_t wbase,
const uint32_t *u, size_t ulen, mpd_uint_t ubase,
uint32_t *status)
{ … }
size_t
mpd_qexport_u16(uint16_t **rdata, size_t rlen, uint32_t rbase,
const mpd_t *src, uint32_t *status)
{ … }
size_t
mpd_qexport_u32(uint32_t **rdata, size_t rlen, uint32_t rbase,
const mpd_t *src, uint32_t *status)
{ … }
void
mpd_qimport_u16(mpd_t *result,
const uint16_t *srcdata, size_t srclen,
uint8_t srcsign, uint32_t srcbase,
const mpd_context_t *ctx, uint32_t *status)
{ … }
void
mpd_qimport_u32(mpd_t *result,
const uint32_t *srcdata, size_t srclen,
uint8_t srcsign, uint32_t srcbase,
const mpd_context_t *ctx, uint32_t *status)
{ … }
#if defined(CONFIG_64) && defined(__SIZEOF_INT128__)
static mpd_ssize_t
_set_coeff(uint64_t data[3], uint64_t hi, uint64_t lo)
{ … }
#else
static size_t
_uint_from_u16(mpd_uint_t *w, mpd_ssize_t wlen, const uint16_t *u, size_t ulen)
{
const mpd_uint_t ubase = 1U<<16;
mpd_ssize_t n = 0;
mpd_uint_t carry;
assert(wlen > 0 && ulen > 0);
w[n++] = u[--ulen];
while (--ulen != SIZE_MAX) {
carry = _mpd_shortmul_c(w, w, n, ubase);
if (carry) {
if (n >= wlen) {
abort();
}
w[n++] = carry;
}
carry = _mpd_shortadd(w, n, u[ulen]);
if (carry) {
if (n >= wlen) {
abort();
}
w[n++] = carry;
}
}
return n;
}
static mpd_ssize_t
_set_coeff(mpd_uint_t *data, mpd_ssize_t len, uint64_t hi, uint64_t lo)
{
uint16_t u16[8] = {0};
u16[7] = (uint16_t)((hi & 0xFFFF000000000000ULL) >> 48);
u16[6] = (uint16_t)((hi & 0x0000FFFF00000000ULL) >> 32);
u16[5] = (uint16_t)((hi & 0x00000000FFFF0000ULL) >> 16);
u16[4] = (uint16_t) (hi & 0x000000000000FFFFULL);
u16[3] = (uint16_t)((lo & 0xFFFF000000000000ULL) >> 48);
u16[2] = (uint16_t)((lo & 0x0000FFFF00000000ULL) >> 32);
u16[1] = (uint16_t)((lo & 0x00000000FFFF0000ULL) >> 16);
u16[0] = (uint16_t) (lo & 0x000000000000FFFFULL);
return (mpd_ssize_t)_uint_from_u16(data, len, u16, 8);
}
#endif
static int
_set_uint128_coeff_exp(mpd_t *result, uint64_t hi, uint64_t lo, mpd_ssize_t exp)
{ … }
int
mpd_from_uint128_triple(mpd_t *result, const mpd_uint128_triple_t *triple, uint32_t *status)
{ … }
#if defined(CONFIG_64) && defined(__SIZEOF_INT128__)
static void
_get_coeff(uint64_t *hi, uint64_t *lo, const mpd_t *a)
{ … }
#else
static size_t
_uint_to_u16(uint16_t w[8], mpd_uint_t *u, mpd_ssize_t ulen)
{
const mpd_uint_t wbase = 1U<<16;
size_t n = 0;
assert(ulen > 0);
do {
if (n >= 8) {
abort();
}
w[n++] = (uint16_t)_mpd_shortdiv(u, u, ulen, wbase);
ulen = _mpd_real_size(u, ulen);
} while (u[ulen-1] != 0);
return n;
}
static void
_get_coeff(uint64_t *hi, uint64_t *lo, const mpd_t *a)
{
uint16_t u16[8] = {0};
mpd_uint_t data[5] = {0};
switch (a->len) {
case 5:
data[4] = a->data[4];
case 4:
data[3] = a->data[3];
case 3:
data[2] = a->data[2];
case 2:
data[1] = a->data[1];
case 1:
data[0] = a->data[0];
break;
default:
abort();
}
_uint_to_u16(u16, data, a->len);
*hi = (uint64_t)u16[7] << 48;
*hi |= (uint64_t)u16[6] << 32;
*hi |= (uint64_t)u16[5] << 16;
*hi |= (uint64_t)u16[4];
*lo = (uint64_t)u16[3] << 48;
*lo |= (uint64_t)u16[2] << 32;
*lo |= (uint64_t)u16[1] << 16;
*lo |= (uint64_t)u16[0];
}
#endif
static enum mpd_triple_class
_coeff_as_uint128(uint64_t *hi, uint64_t *lo, const mpd_t *a)
{ … }
mpd_uint128_triple_t
mpd_as_uint128_triple(const mpd_t *a)
{ … }