1#ifndef MC_DEC128_H_INCLUDED
2#define MC_DEC128_H_INCLUDED
6#include <mlib/macros.h>
7#include <mlib/int128.h>
8#include <mlib/endian.h>
12#ifndef MONGOCRYPT_INTELDFP
14#define MONGOCRYPT_HAVE_DECIMAL128_SUPPORT 0
18#define MONGOCRYPT_HAVE_DECIMAL128_SUPPORT 1
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)
65#if !defined(__INTELLISENSE__) && defined(__GNUC__) && defined(__amd64) && \
66 !defined(__APPLE__) && !defined(__clang__)
69 float value_ __attribute__ ((mode (TD)));
78#define MC_DEC128_C(N) \
79 mc_dec128 _mcDec128Const (((N) < 0 ? -(N) : (N)), ((N) < 0 ? 1 : 0))
81#define MC_DEC128_C(N) \
82 _mcDec128Const (((N) < 0 ? -(N) : (N)), ((N) < 0 ? 1 : 0))
85#define MC_DEC128(N) MLIB_INIT (mc_dec128) MC_DEC128_C (N)
87#define _mcDec128Combination(Bits) ((uint64_t) (Bits) << (47))
88#define _mcDec128ZeroExpCombo _mcDec128Combination (1 << 7 | 1 << 13 | 1 << 14)
89#define _mcDec128Const(N, Negate) \
90 _mcDec128ConstFromParts ( \
91 N, (_mcDec128ZeroExpCombo | ((uint64_t) (Negate) << 63)))
92#define _mcDec128ConstFromParts(CoeffLow, HighWord) \
95 MLIB_IS_LITTLE_ENDIAN ? (uint64_t) (CoeffLow) \
96 : (uint64_t) (HighWord), \
97 MLIB_IS_LITTLE_ENDIAN ? (uint64_t) (HighWord) \
98 : (uint64_t) (CoeffLow), \
102static const mc_dec128 MC_DEC128_ZERO = MC_DEC128_C (0);
103static const mc_dec128 MC_DEC128_ONE = MC_DEC128_C (1);
104static const mc_dec128 MC_DEC128_MINUSONE = MC_DEC128_C (-1);
107#define MC_DEC128_LARGEST_NEGATIVE \
108 mc_dec128_from_string ("-9999999999999999999999999999999999E6111")
110#define MC_DEC128_SMALLEST_NEGATIVE mc_dec128_from_string ("-1E-6176")
112#define MC_DEC128_LARGEST_POSITIVE \
113 mc_dec128_from_string ("9999999999999999999999999999999999E6111")
115#define MC_DEC128_SMALLEST_POSITIVE mc_dec128_from_string ("1E-6176")
117#define MC_DEC128_NORMALIZED_ZERO MC_DEC128_C (0)
119#define MC_DEC128_NEGATIVE_EXPONENT_ZERO mc_dec128_from_string ("0E-6176")
120#define _mcDec128InfCombo \
121 _mcDec128Combination (1 << 15 | 1 << 14 | 1 << 13 | 1 << 12)
122#define _mcDec128QuietNaNCombo \
123 _mcDec128Combination (1 << 15 | 1 << 14 | 1 << 13 | 1 << 12 | 1 << 11)
126#define MC_DEC128_POSITIVE_INFINITY \
127 _mcDec128ConstFromParts (0, _mcDec128InfCombo)
129#define MC_DEC128_NEGATIVE_INFINITY \
130 _mcDec128ConstFromParts (0, _mcDec128InfCombo | 1ull << 63)
132#define MC_DEC128_POSITIVE_NAN \
133 _mcDec128ConstFromParts (0, _mcDec128QuietNaNCombo)
135#define MC_DEC128_NEGATIVE_NAN \
136 _mcDec128ConstFromParts (0, _mcDec128QuietNaNCombo | 1ull << 63)
139static inline BID_UINT128
140_mc_to_bid128 (mc_dec128 d)
143 memcpy (&r, &d,
sizeof d);
148static inline mc_dec128
149_bid128_to_mc (BID_UINT128 d)
152 memcpy (&r, &d,
sizeof d);
164static inline mc_dec128
165mc_dec128_from_double_ex (
double d,
166 mc_dec128_rounding_mode rnd,
167 mc_dec128_flagset *flags)
169 mc_dec128_flagset zero_flags = {0};
170 return _bid128_to_mc (
171 binary64_to_bid128 (d, rnd, flags ? &flags->bits : &zero_flags.bits));
178static inline mc_dec128
179mc_dec128_from_double (
double d)
181 return mc_dec128_from_double_ex (d, MC_DEC128_ROUND_DEFAULT, NULL);
192static inline mc_dec128
193mc_dec128_from_string_ex (
const char *s,
194 mc_dec128_rounding_mode rnd,
195 mc_dec128_flagset *flags)
197 mc_dec128_flagset zero_flags = {0};
198 return _bid128_to_mc (bid128_from_string (
199 (
char *) s, rnd, flags ? &flags->bits : &zero_flags.bits));
206static inline mc_dec128
207mc_dec128_from_string (
const char *s)
209 return mc_dec128_from_string_ex (s, MC_DEC128_ROUND_DEFAULT, NULL);
216typedef struct mc_dec128_string {
227static inline mc_dec128_string
228mc_dec128_to_string_ex (mc_dec128 d, mc_dec128_flagset *flags)
230 mc_dec128_flagset zero_flags = {0};
231 mc_dec128_string out = {{0}};
233 out.str, _mc_to_bid128 (d), flags ? &flags->bits : &zero_flags.bits);
240static inline mc_dec128_string
241mc_dec128_to_string (mc_dec128 d)
243 return mc_dec128_to_string_ex (d, NULL);
247#define DECL_IDF_COMPARE_1(Oper) \
248 static inline bool mc_dec128_##Oper##_ex ( \
249 mc_dec128 left, mc_dec128 right, mc_dec128_flagset *flags) \
251 mc_dec128_flagset zero_flags = {0}; \
253 bid128_quiet_##Oper (_mc_to_bid128 (left), \
254 _mc_to_bid128 (right), \
255 flags ? &flags->bits : &zero_flags.bits); \
258 static inline bool mc_dec128_##Oper (mc_dec128 left, mc_dec128 right) \
260 return mc_dec128_##Oper##_ex (left, right, NULL); \
263#define DECL_IDF_COMPARE(Op) DECL_IDF_COMPARE_1 (Op)
265DECL_IDF_COMPARE (equal)
266DECL_IDF_COMPARE (not_equal)
267DECL_IDF_COMPARE (greater)
268DECL_IDF_COMPARE (greater_equal)
269DECL_IDF_COMPARE (less)
270DECL_IDF_COMPARE (less_equal)
272#undef DECL_IDF_COMPARE
273#undef DECL_IDF_COMPARE_1
276#define DECL_PREDICATE(Name, BIDName) \
277 static inline bool mc_dec128_##Name (mc_dec128 d) \
279 return 0 != bid128_##BIDName (_mc_to_bid128 (d)); \
282DECL_PREDICATE (is_zero, isZero)
283DECL_PREDICATE (is_negative, isSigned)
284DECL_PREDICATE (is_inf, isInf)
285DECL_PREDICATE (is_finite, isFinite)
286DECL_PREDICATE (is_nan, isNaN)
291#define DECL_IDF_BINOP_WRAPPER(Oper) \
292 static inline mc_dec128 mc_dec128_##Oper##_ex ( \
295 mc_dec128_rounding_mode mode, \
296 mc_dec128_flagset *flags) \
298 mc_dec128_flagset zero_flags = {0}; \
299 return _bid128_to_mc ( \
300 bid128_##Oper (_mc_to_bid128 (left), \
301 _mc_to_bid128 (right), \
303 flags ? &flags->bits : &zero_flags.bits)); \
306 static inline mc_dec128 mc_dec128_##Oper (mc_dec128 left, mc_dec128 right) \
308 return mc_dec128_##Oper##_ex ( \
309 left, right, MC_DEC128_ROUND_DEFAULT, NULL); \
312DECL_IDF_BINOP_WRAPPER (add)
313DECL_IDF_BINOP_WRAPPER (mul)
314DECL_IDF_BINOP_WRAPPER (div)
315DECL_IDF_BINOP_WRAPPER (sub)
316DECL_IDF_BINOP_WRAPPER (pow)
318#undef DECL_IDF_BINOP_WRAPPER
321#define DECL_IDF_UNOP_WRAPPER(Oper) \
322 static inline mc_dec128 mc_dec128_##Oper##_ex (mc_dec128 operand, \
323 mc_dec128_flagset *flags) \
325 mc_dec128_flagset zero_flags = {0}; \
326 return _bid128_to_mc ( \
327 bid128_##Oper (_mc_to_bid128 (operand), \
328 MC_DEC128_ROUND_DEFAULT, \
329 flags ? &flags->bits : &zero_flags.bits)); \
332 static inline mc_dec128 mc_dec128_##Oper (mc_dec128 operand) \
334 return mc_dec128_##Oper##_ex (operand, NULL); \
337DECL_IDF_UNOP_WRAPPER (log2)
338DECL_IDF_UNOP_WRAPPER (log10)
339#undef DECL_IDF_UNOP_WRAPPER
341static inline mc_dec128
342mc_dec128_round_integral_ex (mc_dec128 value,
343 mc_dec128_rounding_mode direction,
344 mc_dec128_flagset *flags)
346 BID_UINT128 bid = _mc_to_bid128 (value);
347 mc_dec128_flagset zero_flags = {0};
348 _IDEC_flags *fl = flags ? &flags->bits : &zero_flags.bits;
350 case MC_DEC128_ROUND_TOWARD_ZERO:
351 return _bid128_to_mc (bid128_round_integral_zero (bid, fl));
352 case MC_DEC128_ROUND_NEAREST_AWAY:
353 return _bid128_to_mc (bid128_round_integral_nearest_away (bid, fl));
354 case MC_DEC128_ROUND_NEAREST_EVEN:
355 return _bid128_to_mc (bid128_round_integral_nearest_even (bid, fl));
356 case MC_DEC128_ROUND_DOWNWARD:
357 return _bid128_to_mc (bid128_round_integral_negative (bid, fl));
358 case MC_DEC128_ROUND_UPWARD:
359 return _bid128_to_mc (bid128_round_integral_positive (bid, fl));
365static inline mc_dec128
366mc_dec128_negate (mc_dec128 operand)
368 return _bid128_to_mc (bid128_negate (_mc_to_bid128 (operand)));
371static inline mc_dec128
372mc_dec128_abs (mc_dec128 operand)
374 return _bid128_to_mc (bid128_abs (_mc_to_bid128 (operand)));
386static inline mc_dec128
387mc_dec128_scale_ex (mc_dec128 fac,
389 mc_dec128_rounding_mode rounding,
390 mc_dec128_flagset *flags)
392 mc_dec128_flagset zero_flags = {0};
393 return _bid128_to_mc (
394 bid128_scalbln (_mc_to_bid128 (fac),
397 flags ? &flags->bits : &zero_flags.bits));
407static inline mc_dec128
408mc_dec128_scale (mc_dec128 fac,
long int exp)
410 return mc_dec128_scale_ex (fac, exp, MC_DEC128_ROUND_DEFAULT, NULL);
414typedef struct mc_dec128_modf_result {
419} mc_dec128_modf_result;
430static inline mc_dec128_modf_result
431mc_dec128_modf_ex (mc_dec128 d, mc_dec128_flagset *flags)
433 mc_dec128_flagset zero_flags = {0};
434 mc_dec128_modf_result res;
436 res.frac = _bid128_to_mc (bid128_modf (
437 _mc_to_bid128 (d), &whole, flags ? &flags->bits : &zero_flags.bits));
438 res.whole = _bid128_to_mc (whole);
450static inline mc_dec128_modf_result
451mc_dec128_modf (mc_dec128 d)
453 return mc_dec128_modf_ex (d, NULL);
464static inline mc_dec128
465mc_dec128_fmod_ex (mc_dec128 numer, mc_dec128 denom, mc_dec128_flagset *flags)
467 mc_dec128_flagset zero_flags = {0};
468 return _bid128_to_mc (bid128_fmod (_mc_to_bid128 (numer),
469 _mc_to_bid128 (denom),
470 flags ? &flags->bits : &zero_flags.bits));
480static inline mc_dec128
481mc_dec128_fmod (mc_dec128 numer, mc_dec128 denom)
483 return mc_dec128_fmod_ex (numer, denom, NULL);
494mc_dec128_to_int64_ex (mc_dec128 d, mc_dec128_flagset *flags)
496 mc_dec128_flagset zero_flags = {0};
497 return bid128_to_int64_int (_mc_to_bid128 (d),
498 flags ? &flags->bits : &zero_flags.bits);
508mc_dec128_to_int64 (mc_dec128 d)
510 return mc_dec128_to_int64_ex (d, NULL);
516 MC_DEC128_COMBO_NONCANONICAL = 3 << 15,
518 MC_DEC128_COMBO_INFINITY = 0x1e << 12,
520 MC_DEC128_MAX_BIASED_EXPONENT = 6143 + 6144,
522 MC_DEC128_EXPONENT_BIAS = 6143 + 33,
524 MC_DEC_MIN_EXPONENT = -6143,
526 MC_DEC_MAX_EXPONENT = 6144,
530static inline uint32_t
531mc_dec128_combination (mc_dec128 d)
534 uint64_t hi = d._words[MLIB_IS_LITTLE_ENDIAN ? 1 : 0];
536 int signpos = 64 - 1;
538 int fieldpos = signpos - 17;
539 int fieldmask = (1 << 17) - 1;
540 return (uint32_t) ((hi >> fieldpos) & (uint32_t) fieldmask);
546static inline uint64_t
547mc_dec128_coeff_high (mc_dec128 d)
549 uint64_t hi_field_mask = (1ull << 49) - 1;
550 uint32_t combo = mc_dec128_combination (d);
551 if (combo < MC_DEC128_COMBO_NONCANONICAL) {
552 uint64_t hi = d._words[MLIB_IS_LITTLE_ENDIAN ? 1 : 0];
553 return hi & hi_field_mask;
562static inline uint64_t
563mc_dec128_coeff_low (mc_dec128 d)
565 uint32_t combo = mc_dec128_combination (d);
566 if (combo < MC_DEC128_COMBO_NONCANONICAL) {
567 uint64_t lo = d._words[MLIB_IS_LITTLE_ENDIAN ? 0 : 1];
578static inline mlib_int128
579mc_dec128_coeff (mc_dec128 d)
582 uint64_t hi = mc_dec128_coeff_high (d);
584 uint64_t lo = mc_dec128_coeff_low (d);
586 mlib_int128 hi_128 = mlib_int128_lshift (MLIB_INT128_CAST (hi), 64);
587 return mlib_int128_add (hi_128, MLIB_INT128_CAST (lo));
598static inline uint32_t
599mc_dec128_get_biased_exp (mc_dec128 d)
601 uint32_t combo = mc_dec128_combination (d);
602 if (combo < MC_DEC128_COMBO_NONCANONICAL) {
605 if (combo >= MC_DEC128_COMBO_INFINITY) {
606 return MC_DEC128_MAX_BIASED_EXPONENT + 1;
608 return (combo >> 1) & ((1 << 14) - 1);
614mc_dec128_to_new_decimal_string (mc_dec128 d)
616 if (mc_dec128_is_zero (d)) {
618 char *s = (
char *) calloc (2, 1);
625 if (mc_dec128_is_negative (d)) {
627 d = mc_dec128_negate (d);
628 char *s = mc_dec128_to_new_decimal_string (d);
632 char *s1 = (
char *) calloc (strlen (s) + 2, 1);
641 if (mc_dec128_is_inf (d) || mc_dec128_is_nan (d)) {
642 const char *r = mc_dec128_is_inf (d) ?
"Infinity" :
"NaN";
643 char *c = (
char *) calloc (strlen (r) + 1, 1);
650 const char DIGITS[] =
"0123456789";
651 const mc_dec128 TEN = MC_DEC128_C (10);
654 mc_dec128_modf_result modf = mc_dec128_modf (d);
656 if (mc_dec128_is_zero (modf.frac)) {
659 mc_dec128 log10 = mc_dec128_modf (mc_dec128_log10 (d)).whole;
660 int64_t ndigits = mc_dec128_to_int64 (log10) + 1;
662 char *strbuf = (
char *) calloc ((
size_t) (ndigits + 1), 1);
665 char *optr = strbuf + ndigits - 1;
666 while (!mc_dec128_is_zero (modf.whole)) {
667 mc_dec128 rem = mc_dec128_fmod (modf.whole, TEN);
668 int64_t remi = mc_dec128_to_int64 (rem);
669 *optr-- = DIGITS[remi];
671 modf = mc_dec128_modf (mc_dec128_div (modf.whole, TEN));
675 }
else if (mc_dec128_is_zero (modf.whole)) {
677 while (!mc_dec128_is_zero (mc_dec128_modf (d).frac)) {
678 d = mc_dec128_mul (d, TEN);
681 char *part = mc_dec128_to_new_decimal_string (d);
685 char *buf = (
char *) calloc (strlen (part) + 3, 1);
689 strcpy (buf + 2, part);
695 char *whole = mc_dec128_to_new_decimal_string (modf.whole);
699 char *frac = mc_dec128_to_new_decimal_string (modf.frac);
704 char *ret = (
char *) calloc (strlen (whole) + strlen (frac) + 1, 1);
708 out += strlen (whole);
710 strcpy (out, frac + 1);
718static inline mc_dec128
719mc_dec128_from_bson_iter (bson_iter_t *it)
722 if (!bson_iter_decimal128 (it, &b)) {
723 mc_dec128 nan = MC_DEC128_POSITIVE_NAN;
727 memcpy (&ret, &b,
sizeof b);
731static inline bson_decimal128_t
732mc_dec128_to_bson_decimal128 (mc_dec128 v)
734 bson_decimal128_t ret;
735 memcpy (&ret, &v,
sizeof ret);