1#ifndef MC_DEC128_H_INCLUDED
2#define MC_DEC128_H_INCLUDED
6#include <mlib/endian.h>
7#include <mlib/int128.h>
8#include <mlib/macros.h>
12#ifndef MONGOCRYPT_INTELDFP
14#define MONGOCRYPT_HAVE_DECIMAL128_SUPPORT() false
18#define MONGOCRYPT_HAVE_DECIMAL128_SUPPORT() true
23#include <bid_functions.h>
33typedef enum mc_dec128_rounding_mode {
34 MC_DEC128_ROUND_NEAREST_EVEN = 0,
35 MC_DEC128_ROUND_DOWNWARD = 1,
36 MC_DEC128_ROUND_UPWARD = 2,
37 MC_DEC128_ROUND_TOWARD_ZERO = 3,
38 MC_DEC128_ROUND_NEAREST_AWAY = 4,
39 MC_DEC128_ROUND_DEFAULT = MC_DEC128_ROUND_NEAREST_EVEN,
40} mc_dec128_rounding_mode;
42typedef struct mc_dec128_flagset {
49#if defined _M_IX86 && !defined __INTEL_COMPILER
50#define _mcDec128Align(n)
52#define _mcDec128Align(n) __declspec(align(n))
56#define _mcDec128Align(n) __attribute__((aligned(n)))
58#define _mcDec128Align(n)
62typedef union _mcDec128Align(16) {
64#if !defined(__INTELLISENSE__) && defined(__GNUC__) && defined(__amd64) && !defined(__APPLE__) && !defined(__clang__)
67 float value_ __attribute__((mode(TD)));
77#define MC_DEC128_C(N) mc_dec128 _mcDec128Const(((N) < 0 ? -(N) : (N)), ((N) < 0 ? 1 : 0))
79#define MC_DEC128_C(N) _mcDec128Const(((N) < 0 ? -(N) : (N)), ((N) < 0 ? 1 : 0))
82#define MC_DEC128(N) MLIB_INIT(mc_dec128) MC_DEC128_C(N)
84#define _mcDec128Combination(Bits) ((uint64_t)(Bits) << (47))
85#define _mcDec128ZeroExpCombo _mcDec128Combination(1 << 7 | 1 << 13 | 1 << 14)
86#define _mcDec128Const(N, Negate) _mcDec128ConstFromParts(N, (_mcDec128ZeroExpCombo | ((uint64_t)(Negate) << 63)))
87#define _mcDec128ConstFromParts(CoeffLow, HighWord) \
90 MLIB_IS_LITTLE_ENDIAN ? (uint64_t)(CoeffLow) : (uint64_t)(HighWord), \
91 MLIB_IS_LITTLE_ENDIAN ? (uint64_t)(HighWord) : (uint64_t)(CoeffLow), \
95static const mc_dec128 MC_DEC128_ZERO = MC_DEC128_C(0);
96static const mc_dec128 MC_DEC128_ONE = MC_DEC128_C(1);
97static const mc_dec128 MC_DEC128_MINUSONE = MC_DEC128_C(-1);
100#define MC_DEC128_LARGEST_NEGATIVE mc_dec128_from_string("-9999999999999999999999999999999999E6111")
102#define MC_DEC128_SMALLEST_NEGATIVE mc_dec128_from_string("-1E-6176")
104#define MC_DEC128_LARGEST_POSITIVE mc_dec128_from_string("9999999999999999999999999999999999E6111")
106#define MC_DEC128_SMALLEST_POSITIVE mc_dec128_from_string("1E-6176")
108#define MC_DEC128_NORMALIZED_ZERO MC_DEC128_C(0)
110#define MC_DEC128_NEGATIVE_EXPONENT_ZERO mc_dec128_from_string("0E-6176")
111#define _mcDec128InfCombo _mcDec128Combination(1 << 15 | 1 << 14 | 1 << 13 | 1 << 12)
112#define _mcDec128QuietNaNCombo _mcDec128Combination(1 << 15 | 1 << 14 | 1 << 13 | 1 << 12 | 1 << 11)
115#define MC_DEC128_POSITIVE_INFINITY _mcDec128ConstFromParts(0, _mcDec128InfCombo)
117#define MC_DEC128_NEGATIVE_INFINITY _mcDec128ConstFromParts(0, _mcDec128InfCombo | 1ull << 63)
119#define MC_DEC128_POSITIVE_NAN _mcDec128ConstFromParts(0, _mcDec128QuietNaNCombo)
121#define MC_DEC128_NEGATIVE_NAN _mcDec128ConstFromParts(0, _mcDec128QuietNaNCombo | 1ull << 63)
124static inline BID_UINT128 _mc_to_bid128(mc_dec128 d) {
126 memcpy(&r, &d,
sizeof d);
131static inline mc_dec128 _bid128_to_mc(BID_UINT128 d) {
133 memcpy(&r, &d,
sizeof d);
145static inline mc_dec128 mc_dec128_from_double_ex(
double d, mc_dec128_rounding_mode rnd, mc_dec128_flagset *flags) {
146 mc_dec128_flagset zero_flags = {0};
147 return _bid128_to_mc(binary64_to_bid128(d, rnd, flags ? &flags->bits : &zero_flags.bits));
154static inline mc_dec128 mc_dec128_from_double(
double d) {
155 return mc_dec128_from_double_ex(d, MC_DEC128_ROUND_DEFAULT, NULL);
166static inline mc_dec128 mc_dec128_from_string_ex(
const char *s, mc_dec128_rounding_mode rnd, mc_dec128_flagset *flags) {
167 mc_dec128_flagset zero_flags = {0};
168 return _bid128_to_mc(bid128_from_string((
char *)s, rnd, flags ? &flags->bits : &zero_flags.bits));
175static inline mc_dec128 mc_dec128_from_string(
const char *s) {
176 return mc_dec128_from_string_ex(s, MC_DEC128_ROUND_DEFAULT, NULL);
183typedef struct mc_dec128_string {
194static inline mc_dec128_string mc_dec128_to_string_ex(mc_dec128 d, mc_dec128_flagset *flags) {
195 mc_dec128_flagset zero_flags = {0};
196 mc_dec128_string out = {{0}};
197 bid128_to_string(out.str, _mc_to_bid128(d), flags ? &flags->bits : &zero_flags.bits);
204static inline mc_dec128_string mc_dec128_to_string(mc_dec128 d) {
205 return mc_dec128_to_string_ex(d, NULL);
209#define DECL_IDF_COMPARE_1(Oper) \
210 static inline bool mc_dec128_##Oper##_ex(mc_dec128 left, mc_dec128 right, mc_dec128_flagset *flags) { \
211 mc_dec128_flagset zero_flags = {0}; \
213 != bid128_quiet_##Oper(_mc_to_bid128(left), \
214 _mc_to_bid128(right), \
215 flags ? &flags->bits : &zero_flags.bits); \
218 static inline bool mc_dec128_##Oper(mc_dec128 left, mc_dec128 right) { \
219 return mc_dec128_##Oper##_ex(left, right, NULL); \
222#define DECL_IDF_COMPARE(Op) DECL_IDF_COMPARE_1(Op)
224DECL_IDF_COMPARE(equal)
225DECL_IDF_COMPARE(not_equal)
226DECL_IDF_COMPARE(greater)
227DECL_IDF_COMPARE(greater_equal)
228DECL_IDF_COMPARE(less)
229DECL_IDF_COMPARE(less_equal)
231#undef DECL_IDF_COMPARE
232#undef DECL_IDF_COMPARE_1
235#define DECL_PREDICATE(Name, BIDName) \
236 static inline bool mc_dec128_##Name(mc_dec128 d) { return 0 != bid128_##BIDName(_mc_to_bid128(d)); }
238DECL_PREDICATE(is_zero, isZero)
239DECL_PREDICATE(is_negative, isSigned)
240DECL_PREDICATE(is_inf, isInf)
241DECL_PREDICATE(is_finite, isFinite)
242DECL_PREDICATE(is_nan, isNaN)
247#define DECL_IDF_BINOP_WRAPPER(Oper) \
248 static inline mc_dec128 mc_dec128_##Oper##_ex(mc_dec128 left, \
250 mc_dec128_rounding_mode mode, \
251 mc_dec128_flagset *flags) { \
252 mc_dec128_flagset zero_flags = {0}; \
253 return _bid128_to_mc( \
254 bid128_##Oper(_mc_to_bid128(left), _mc_to_bid128(right), mode, flags ? &flags->bits : &zero_flags.bits)); \
257 static inline mc_dec128 mc_dec128_##Oper(mc_dec128 left, mc_dec128 right) { \
258 return mc_dec128_##Oper##_ex(left, right, MC_DEC128_ROUND_DEFAULT, NULL); \
261DECL_IDF_BINOP_WRAPPER(add)
262DECL_IDF_BINOP_WRAPPER(mul)
263DECL_IDF_BINOP_WRAPPER(div)
264DECL_IDF_BINOP_WRAPPER(sub)
265DECL_IDF_BINOP_WRAPPER(pow)
267#undef DECL_IDF_BINOP_WRAPPER
270#define DECL_IDF_UNOP_WRAPPER(Oper) \
271 static inline mc_dec128 mc_dec128_##Oper##_ex(mc_dec128 operand, mc_dec128_flagset *flags) { \
272 mc_dec128_flagset zero_flags = {0}; \
273 return _bid128_to_mc( \
274 bid128_##Oper(_mc_to_bid128(operand), MC_DEC128_ROUND_DEFAULT, flags ? &flags->bits : &zero_flags.bits)); \
277 static inline mc_dec128 mc_dec128_##Oper(mc_dec128 operand) { return mc_dec128_##Oper##_ex(operand, NULL); }
279DECL_IDF_UNOP_WRAPPER(log2)
280DECL_IDF_UNOP_WRAPPER(log10)
281#undef DECL_IDF_UNOP_WRAPPER
283static inline mc_dec128
284mc_dec128_round_integral_ex(mc_dec128 value, mc_dec128_rounding_mode direction, mc_dec128_flagset *flags) {
285 BID_UINT128 bid = _mc_to_bid128(value);
286 mc_dec128_flagset zero_flags = {0};
287 _IDEC_flags *fl = flags ? &flags->bits : &zero_flags.bits;
289 case MC_DEC128_ROUND_TOWARD_ZERO:
return _bid128_to_mc(bid128_round_integral_zero(bid, fl));
290 case MC_DEC128_ROUND_NEAREST_AWAY:
return _bid128_to_mc(bid128_round_integral_nearest_away(bid, fl));
291 case MC_DEC128_ROUND_NEAREST_EVEN:
return _bid128_to_mc(bid128_round_integral_nearest_even(bid, fl));
292 case MC_DEC128_ROUND_DOWNWARD:
return _bid128_to_mc(bid128_round_integral_negative(bid, fl));
293 case MC_DEC128_ROUND_UPWARD:
return _bid128_to_mc(bid128_round_integral_positive(bid, fl));
298static inline mc_dec128 mc_dec128_negate(mc_dec128 operand) {
299 return _bid128_to_mc(bid128_negate(_mc_to_bid128(operand)));
302static inline mc_dec128 mc_dec128_abs(mc_dec128 operand) {
303 return _bid128_to_mc(bid128_abs(_mc_to_bid128(operand)));
315static inline mc_dec128
316mc_dec128_scale_ex(mc_dec128 fac,
long int exp, mc_dec128_rounding_mode rounding, mc_dec128_flagset *flags) {
317 mc_dec128_flagset zero_flags = {0};
318 return _bid128_to_mc(bid128_scalbln(_mc_to_bid128(fac), exp, rounding, flags ? &flags->bits : &zero_flags.bits));
328static inline mc_dec128 mc_dec128_scale(mc_dec128 fac,
long int exp) {
329 return mc_dec128_scale_ex(fac, exp, MC_DEC128_ROUND_DEFAULT, NULL);
333typedef struct mc_dec128_modf_result {
338} mc_dec128_modf_result;
349static inline mc_dec128_modf_result mc_dec128_modf_ex(mc_dec128 d, mc_dec128_flagset *flags) {
350 mc_dec128_flagset zero_flags = {0};
351 mc_dec128_modf_result res;
353 res.frac = _bid128_to_mc(bid128_modf(_mc_to_bid128(d), &whole, flags ? &flags->bits : &zero_flags.bits));
354 res.whole = _bid128_to_mc(whole);
366static inline mc_dec128_modf_result mc_dec128_modf(mc_dec128 d) {
367 return mc_dec128_modf_ex(d, NULL);
378static inline mc_dec128 mc_dec128_fmod_ex(mc_dec128 numer, mc_dec128 denom, mc_dec128_flagset *flags) {
379 mc_dec128_flagset zero_flags = {0};
380 return _bid128_to_mc(
381 bid128_fmod(_mc_to_bid128(numer), _mc_to_bid128(denom), flags ? &flags->bits : &zero_flags.bits));
391static inline mc_dec128 mc_dec128_fmod(mc_dec128 numer, mc_dec128 denom) {
392 return mc_dec128_fmod_ex(numer, denom, NULL);
402static inline int64_t mc_dec128_to_int64_ex(mc_dec128 d, mc_dec128_flagset *flags) {
403 mc_dec128_flagset zero_flags = {0};
404 return bid128_to_int64_int(_mc_to_bid128(d), flags ? &flags->bits : &zero_flags.bits);
413static inline int64_t mc_dec128_to_int64(mc_dec128 d) {
414 return mc_dec128_to_int64_ex(d, NULL);
420 MC_DEC128_COMBO_NONCANONICAL = 3 << 15,
422 MC_DEC128_COMBO_INFINITY = 0x1e << 12,
424 MC_DEC128_MAX_BIASED_EXPONENT = 6143 + 6144,
426 MC_DEC128_EXPONENT_BIAS = 6143 + 33,
428 MC_DEC_MIN_EXPONENT = -6143,
430 MC_DEC_MAX_EXPONENT = 6144,
434static inline uint32_t mc_dec128_combination(mc_dec128 d) {
436 uint64_t hi = d._words[MLIB_IS_LITTLE_ENDIAN ? 1 : 0];
438 int signpos = 64 - 1;
440 int fieldpos = signpos - 17;
441 int fieldmask = (1 << 17) - 1;
442 return (uint32_t)((hi >> fieldpos) & (uint32_t)fieldmask);
448static inline uint64_t mc_dec128_coeff_high(mc_dec128 d) {
449 uint64_t hi_field_mask = (1ull << 49) - 1;
450 uint32_t combo = mc_dec128_combination(d);
451 if (combo < MC_DEC128_COMBO_NONCANONICAL) {
452 uint64_t hi = d._words[MLIB_IS_LITTLE_ENDIAN ? 1 : 0];
453 return hi & hi_field_mask;
462static inline uint64_t mc_dec128_coeff_low(mc_dec128 d) {
463 uint32_t combo = mc_dec128_combination(d);
464 if (combo < MC_DEC128_COMBO_NONCANONICAL) {
465 uint64_t lo = d._words[MLIB_IS_LITTLE_ENDIAN ? 0 : 1];
476static inline mlib_int128 mc_dec128_coeff(mc_dec128 d) {
478 uint64_t hi = mc_dec128_coeff_high(d);
480 uint64_t lo = mc_dec128_coeff_low(d);
482 mlib_int128 hi_128 = mlib_int128_lshift(MLIB_INT128_CAST(hi), 64);
483 return mlib_int128_add(hi_128, MLIB_INT128_CAST(lo));
494static inline uint32_t mc_dec128_get_biased_exp(mc_dec128 d) {
495 uint32_t combo = mc_dec128_combination(d);
496 if (combo < MC_DEC128_COMBO_NONCANONICAL) {
499 if (combo >= MC_DEC128_COMBO_INFINITY) {
500 return MC_DEC128_MAX_BIASED_EXPONENT + 1;
502 return (combo >> 1) & ((1 << 14) - 1);
507static inline char *mc_dec128_to_new_decimal_string(mc_dec128 d) {
508 if (mc_dec128_is_zero(d)) {
510 char *s = (
char *)calloc(2, 1);
517 if (mc_dec128_is_negative(d)) {
519 d = mc_dec128_negate(d);
520 char *s = mc_dec128_to_new_decimal_string(d);
524 char *s1 = (
char *)calloc(strlen(s) + 2, 1);
533 if (mc_dec128_is_inf(d) || mc_dec128_is_nan(d)) {
534 const char *r = mc_dec128_is_inf(d) ?
"Infinity" :
"NaN";
535 char *c = (
char *)calloc(strlen(r) + 1, 1);
542 const char DIGITS[] =
"0123456789";
543 const mc_dec128 TEN = MC_DEC128_C(10);
546 mc_dec128_modf_result modf = mc_dec128_modf(d);
548 if (mc_dec128_is_zero(modf.frac)) {
551 mc_dec128 log10 = mc_dec128_modf(mc_dec128_log10(d)).whole;
552 int64_t ndigits = mc_dec128_to_int64(log10) + 1;
554 char *strbuf = (
char *)calloc((
size_t)(ndigits + 1), 1);
557 char *optr = strbuf + ndigits - 1;
558 while (!mc_dec128_is_zero(modf.whole)) {
559 mc_dec128 rem = mc_dec128_fmod(modf.whole, TEN);
560 int64_t remi = mc_dec128_to_int64(rem);
561 *optr-- = DIGITS[remi];
563 modf = mc_dec128_modf(mc_dec128_div(modf.whole, TEN));
567 }
else if (mc_dec128_is_zero(modf.whole)) {
569 while (!mc_dec128_is_zero(mc_dec128_modf(d).frac)) {
570 d = mc_dec128_mul(d, TEN);
573 char *part = mc_dec128_to_new_decimal_string(d);
577 char *buf = (
char *)calloc(strlen(part) + 3, 1);
581 strcpy(buf + 2, part);
587 char *whole = mc_dec128_to_new_decimal_string(modf.whole);
591 char *frac = mc_dec128_to_new_decimal_string(modf.frac);
596 char *ret = (
char *)calloc(strlen(whole) + strlen(frac) + 1, 1);
600 out += strlen(whole);
602 strcpy(out, frac + 1);
610static inline mc_dec128 mc_dec128_from_bson_iter(
const bson_iter_t *it) {
612 if (!bson_iter_decimal128(it, &b)) {
613 mc_dec128 nan = MC_DEC128_POSITIVE_NAN;
617 memcpy(&ret, &b,
sizeof b);
621static inline bson_decimal128_t mc_dec128_to_bson_decimal128(mc_dec128 v) {
622 bson_decimal128_t ret;
623 memcpy(&ret, &v,
sizeof ret);