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>
13 #include <bid_functions.h>
23 typedef enum mc_dec128_rounding_mode {
24 MC_DEC128_ROUND_NEAREST_EVEN = 0,
25 MC_DEC128_ROUND_DOWNWARD = 1,
26 MC_DEC128_ROUND_UPWARD = 2,
27 MC_DEC128_ROUND_TOWARD_ZERO = 3,
28 MC_DEC128_ROUND_NEAREST_AWAY = 4,
29 MC_DEC128_ROUND_DEFAULT = MC_DEC128_ROUND_NEAREST_EVEN,
30 } mc_dec128_rounding_mode;
39 #if defined _M_IX86 && !defined __INTEL_COMPILER
40 #define _mcDec128Align(n)
42 #define _mcDec128Align(n) __declspec(align (n))
46 #define _mcDec128Align(n) __attribute__ ((aligned (n)))
48 #define _mcDec128Align(n)
52 typedef union _mcDec128Align (16)
55 #if !defined(__INTELLISENSE__) && defined(__GNUC__) && defined(__amd64) && \
56 !defined(__APPLE__) && !defined(__clang__)
59 float value_ __attribute__ ((mode (TD)));
68 #define MC_DEC128_C(N) \
69 mc_dec128 _mcDec128Const (((N) < 0 ? -(N) : (N)), ((N) < 0 ? 1 : 0))
71 #define MC_DEC128_C(N) \
72 _mcDec128Const (((N) < 0 ? -(N) : (N)), ((N) < 0 ? 1 : 0))
75 #define MC_DEC128(N) MLIB_INIT (mc_dec128) MC_DEC128_C (N)
77 #define _mcDec128Combination(Bits) ((uint64_t) (Bits) << (47))
78 #define _mcDec128ZeroExpCombo _mcDec128Combination (1 << 7 | 1 << 13 | 1 << 14)
79 #define _mcDec128Const(N, Negate) \
80 _mcDec128ConstFromParts ( \
81 N, (_mcDec128ZeroExpCombo | ((uint64_t) (Negate) << 63)))
82 #define _mcDec128ConstFromParts(CoeffLow, HighWord) \
85 MLIB_IS_LITTLE_ENDIAN ? (uint64_t) (CoeffLow) \
86 : (uint64_t) (HighWord), \
87 MLIB_IS_LITTLE_ENDIAN ? (uint64_t) (HighWord) \
88 : (uint64_t) (CoeffLow), \
92 static const mc_dec128 MC_DEC128_ZERO = MC_DEC128_C (0);
93 static const mc_dec128 MC_DEC128_ONE = MC_DEC128_C (1);
94 static const mc_dec128 MC_DEC128_MINUSONE = MC_DEC128_C (-1);
97 #define MC_DEC128_LARGEST_NEGATIVE \
98 mc_dec128_from_string ("-9999999999999999999999999999999999E6111")
100 #define MC_DEC128_SMALLEST_NEGATIVE mc_dec128_from_string ("-1E-6176")
102 #define MC_DEC128_LARGEST_POSITIVE \
103 mc_dec128_from_string ("9999999999999999999999999999999999E6111")
105 #define MC_DEC128_SMALLEST_POSITIVE mc_dec128_from_string ("1E-6176")
107 #define MC_DEC128_NORMALIZED_ZERO MC_DEC128_C (0)
109 #define MC_DEC128_NEGATIVE_EXPONENT_ZERO mc_dec128_from_string ("0E-6176")
110 #define _mcDec128InfCombo \
111 _mcDec128Combination (1 << 15 | 1 << 14 | 1 << 13 | 1 << 12)
112 #define _mcDec128QuietNaNCombo \
113 _mcDec128Combination (1 << 15 | 1 << 14 | 1 << 13 | 1 << 12 | 1 << 11)
116 #define MC_DEC128_POSITIVE_INFINITY \
117 _mcDec128ConstFromParts (0, _mcDec128InfCombo)
119 #define MC_DEC128_NEGATIVE_INFINITY \
120 _mcDec128ConstFromParts (0, _mcDec128InfCombo | 1ull << 63)
122 #define MC_DEC128_POSITIVE_NAN \
123 _mcDec128ConstFromParts (0, _mcDec128QuietNaNCombo)
125 #define MC_DEC128_NEGATIVE_NAN \
126 _mcDec128ConstFromParts (0, _mcDec128QuietNaNCombo | 1ull << 63)
129 static inline BID_UINT128
130 _mc_to_bid128 (mc_dec128 d)
133 memcpy (&r, &d,
sizeof d);
138 static inline mc_dec128
139 _bid128_to_mc (BID_UINT128 d)
142 memcpy (&r, &d,
sizeof d);
154 static inline mc_dec128
155 mc_dec128_from_double_ex (
double d,
156 mc_dec128_rounding_mode rnd,
160 return _bid128_to_mc (
161 binary64_to_bid128 (d, rnd, flags ? &flags->bits : &zero_flags.bits));
168 static inline mc_dec128
169 mc_dec128_from_double (
double d)
171 return mc_dec128_from_double_ex (d, MC_DEC128_ROUND_DEFAULT, NULL);
182 static inline mc_dec128
183 mc_dec128_from_string_ex (
const char *s,
184 mc_dec128_rounding_mode rnd,
188 return _bid128_to_mc (bid128_from_string (
189 (
char *) s, rnd, flags ? &flags->bits : &zero_flags.bits));
196 static inline mc_dec128
197 mc_dec128_from_string (
const char *s)
199 return mc_dec128_from_string_ex (s, MC_DEC128_ROUND_DEFAULT, NULL);
223 out.
str, _mc_to_bid128 (d), flags ? &flags->bits : &zero_flags.bits);
231 mc_dec128_to_string (mc_dec128 d)
233 return mc_dec128_to_string_ex (d, NULL);
237 #define DECL_IDF_COMPARE_1(Oper) \
238 static inline bool mc_dec128_##Oper##_ex ( \
239 mc_dec128 left, mc_dec128 right, mc_dec128_flagset *flags) \
241 mc_dec128_flagset zero_flags = {0}; \
243 bid128_quiet_##Oper (_mc_to_bid128 (left), \
244 _mc_to_bid128 (right), \
245 flags ? &flags->bits : &zero_flags.bits); \
248 static inline bool mc_dec128_##Oper (mc_dec128 left, mc_dec128 right) \
250 return mc_dec128_##Oper##_ex (left, right, NULL); \
253 #define DECL_IDF_COMPARE(Op) DECL_IDF_COMPARE_1 (Op)
255 DECL_IDF_COMPARE (equal)
256 DECL_IDF_COMPARE (not_equal)
257 DECL_IDF_COMPARE (greater)
258 DECL_IDF_COMPARE (greater_equal)
259 DECL_IDF_COMPARE (less)
260 DECL_IDF_COMPARE (less_equal)
262 #undef DECL_IDF_COMPARE
263 #undef DECL_IDF_COMPARE_1
266 #define DECL_PREDICATE(Name, BIDName) \
267 static inline bool mc_dec128_##Name (mc_dec128 d) \
269 return 0 != bid128_##BIDName (_mc_to_bid128 (d)); \
272 DECL_PREDICATE (is_zero, isZero)
273 DECL_PREDICATE (is_negative, isSigned)
274 DECL_PREDICATE (is_inf, isInf)
275 DECL_PREDICATE (is_finite, isFinite)
276 DECL_PREDICATE (is_nan, isNaN)
278 #undef DECL_PREDICATE
281 #define DECL_IDF_BINOP_WRAPPER(Oper) \
282 static inline mc_dec128 mc_dec128_##Oper##_ex ( \
285 mc_dec128_rounding_mode mode, \
286 mc_dec128_flagset *flags) \
288 mc_dec128_flagset zero_flags = {0}; \
289 return _bid128_to_mc ( \
290 bid128_##Oper (_mc_to_bid128 (left), \
291 _mc_to_bid128 (right), \
293 flags ? &flags->bits : &zero_flags.bits)); \
296 static inline mc_dec128 mc_dec128_##Oper (mc_dec128 left, mc_dec128 right) \
298 return mc_dec128_##Oper##_ex ( \
299 left, right, MC_DEC128_ROUND_DEFAULT, NULL); \
302 DECL_IDF_BINOP_WRAPPER (add)
303 DECL_IDF_BINOP_WRAPPER (mul)
304 DECL_IDF_BINOP_WRAPPER (div)
305 DECL_IDF_BINOP_WRAPPER (sub)
306 DECL_IDF_BINOP_WRAPPER (pow)
308 #undef DECL_IDF_BINOP_WRAPPER
311 #define DECL_IDF_UNOP_WRAPPER(Oper) \
312 static inline mc_dec128 mc_dec128_##Oper##_ex (mc_dec128 operand, \
313 mc_dec128_flagset *flags) \
315 mc_dec128_flagset zero_flags = {0}; \
316 return _bid128_to_mc ( \
317 bid128_##Oper (_mc_to_bid128 (operand), \
318 MC_DEC128_ROUND_DEFAULT, \
319 flags ? &flags->bits : &zero_flags.bits)); \
322 static inline mc_dec128 mc_dec128_##Oper (mc_dec128 operand) \
324 return mc_dec128_##Oper##_ex (operand, NULL); \
327 DECL_IDF_UNOP_WRAPPER (log2)
328 DECL_IDF_UNOP_WRAPPER (log10)
329 #undef DECL_IDF_UNOP_WRAPPER
331 static inline mc_dec128
332 mc_dec128_round_integral_ex (mc_dec128 value,
333 mc_dec128_rounding_mode direction,
336 BID_UINT128 bid = _mc_to_bid128 (value);
338 _IDEC_flags *fl = flags ? &flags->bits : &zero_flags.bits;
340 case MC_DEC128_ROUND_TOWARD_ZERO:
341 return _bid128_to_mc (bid128_round_integral_zero (bid, fl));
342 case MC_DEC128_ROUND_NEAREST_AWAY:
343 return _bid128_to_mc (bid128_round_integral_nearest_away (bid, fl));
344 case MC_DEC128_ROUND_NEAREST_EVEN:
345 return _bid128_to_mc (bid128_round_integral_nearest_even (bid, fl));
346 case MC_DEC128_ROUND_DOWNWARD:
347 return _bid128_to_mc (bid128_round_integral_negative (bid, fl));
348 case MC_DEC128_ROUND_UPWARD:
349 return _bid128_to_mc (bid128_round_integral_positive (bid, fl));
355 static inline mc_dec128
356 mc_dec128_negate (mc_dec128 operand)
358 return _bid128_to_mc (bid128_negate (_mc_to_bid128 (operand)));
361 static inline mc_dec128
362 mc_dec128_abs (mc_dec128 operand)
364 return _bid128_to_mc (bid128_abs (_mc_to_bid128 (operand)));
376 static inline mc_dec128
377 mc_dec128_scale_ex (mc_dec128 fac,
379 mc_dec128_rounding_mode rounding,
383 return _bid128_to_mc (
384 bid128_scalbln (_mc_to_bid128 (fac),
387 flags ? &flags->bits : &zero_flags.bits));
397 static inline mc_dec128
398 mc_dec128_scale (mc_dec128 fac,
long int exp)
400 return mc_dec128_scale_ex (fac, exp, MC_DEC128_ROUND_DEFAULT, NULL);
426 res.
frac = _bid128_to_mc (bid128_modf (
427 _mc_to_bid128 (d), &whole, flags ? &flags->bits : &zero_flags.bits));
428 res.
whole = _bid128_to_mc (whole);
441 mc_dec128_modf (mc_dec128 d)
443 return mc_dec128_modf_ex (d, NULL);
454 static inline mc_dec128
458 return _bid128_to_mc (bid128_fmod (_mc_to_bid128 (numer),
459 _mc_to_bid128 (denom),
460 flags ? &flags->bits : &zero_flags.bits));
470 static inline mc_dec128
471 mc_dec128_fmod (mc_dec128 numer, mc_dec128 denom)
473 return mc_dec128_fmod_ex (numer, denom, NULL);
483 static inline int64_t
487 return bid128_to_int64_int (_mc_to_bid128 (d),
488 flags ? &flags->bits : &zero_flags.bits);
497 static inline int64_t
498 mc_dec128_to_int64 (mc_dec128 d)
500 return mc_dec128_to_int64_ex (d, NULL);
506 MC_DEC128_COMBO_NONCANONICAL = 3 << 15,
508 MC_DEC128_COMBO_INFINITY = 0x1e << 12,
510 MC_DEC128_MAX_BIASED_EXPONENT = 6143 + 6144,
512 MC_DEC128_EXPONENT_BIAS = 6143 + 33,
514 MC_DEC_MIN_EXPONENT = -6143,
516 MC_DEC_MAX_EXPONENT = 6144,
520 static inline uint32_t
521 mc_dec128_combination (mc_dec128 d)
524 uint64_t hi = d._words[MLIB_IS_LITTLE_ENDIAN ? 1 : 0];
526 int signpos = 64 - 1;
528 int fieldpos = signpos - 17;
529 int fieldmask = (1 << 17) - 1;
530 return (uint32_t) ((hi >> fieldpos) & (uint32_t) fieldmask);
536 static inline uint64_t
537 mc_dec128_coeff_high (mc_dec128 d)
539 uint64_t hi_field_mask = (1ull << 49) - 1;
540 uint32_t combo = mc_dec128_combination (d);
541 if (combo < MC_DEC128_COMBO_NONCANONICAL) {
542 uint64_t hi = d._words[MLIB_IS_LITTLE_ENDIAN ? 1 : 0];
543 return hi & hi_field_mask;
552 static inline uint64_t
553 mc_dec128_coeff_low (mc_dec128 d)
555 uint32_t combo = mc_dec128_combination (d);
556 if (combo < MC_DEC128_COMBO_NONCANONICAL) {
557 uint64_t lo = d._words[MLIB_IS_LITTLE_ENDIAN ? 0 : 1];
568 static inline mlib_int128
569 mc_dec128_coeff (mc_dec128 d)
572 uint64_t hi = mc_dec128_coeff_high (d);
574 uint64_t lo = mc_dec128_coeff_low (d);
576 mlib_int128 hi_128 = mlib_int128_lshift (MLIB_INT128_CAST (hi), 64);
577 return mlib_int128_add (hi_128, MLIB_INT128_CAST (lo));
588 static inline uint32_t
589 mc_dec128_get_biased_exp (mc_dec128 d)
591 uint32_t combo = mc_dec128_combination (d);
592 if (combo < MC_DEC128_COMBO_NONCANONICAL) {
595 if (combo >= MC_DEC128_COMBO_INFINITY) {
596 return MC_DEC128_MAX_BIASED_EXPONENT + 1;
598 return (combo >> 1) & ((1 << 14) - 1);
604 mc_dec128_to_new_decimal_string (mc_dec128 d)
606 if (mc_dec128_is_zero (d)) {
608 char *s = (
char *) calloc (2, 1);
615 if (mc_dec128_is_negative (d)) {
617 d = mc_dec128_negate (d);
618 char *s = mc_dec128_to_new_decimal_string (d);
622 char *s1 = (
char *) calloc (strlen (s) + 2, 1);
631 if (mc_dec128_is_inf (d) || mc_dec128_is_nan (d)) {
632 const char *r = mc_dec128_is_inf (d) ?
"Infinity" :
"NaN";
633 char *c = (
char *) calloc (strlen (r) + 1, 1);
640 const char DIGITS[] =
"0123456789";
641 const mc_dec128 TEN = MC_DEC128_C (10);
646 if (mc_dec128_is_zero (modf.
frac)) {
649 mc_dec128 log10 = mc_dec128_modf (mc_dec128_log10 (d)).
whole;
650 int64_t ndigits = mc_dec128_to_int64 (log10) + 1;
652 char *strbuf = (
char *) calloc ((
size_t) (ndigits + 1), 1);
655 char *optr = strbuf + ndigits - 1;
656 while (!mc_dec128_is_zero (modf.
whole)) {
657 mc_dec128 rem = mc_dec128_fmod (modf.
whole, TEN);
658 int64_t remi = mc_dec128_to_int64 (rem);
659 *optr-- = DIGITS[remi];
661 modf = mc_dec128_modf (mc_dec128_div (modf.
whole, TEN));
665 }
else if (mc_dec128_is_zero (modf.
whole)) {
667 while (!mc_dec128_is_zero (mc_dec128_modf (d).frac)) {
668 d = mc_dec128_mul (d, TEN);
671 char *part = mc_dec128_to_new_decimal_string (d);
675 char *buf = (
char *) calloc (strlen (part) + 3, 1);
679 strcpy (buf + 2, part);
685 char *whole = mc_dec128_to_new_decimal_string (modf.
whole);
689 char *frac = mc_dec128_to_new_decimal_string (modf.
frac);
694 char *ret = (
char *) calloc (strlen (whole) + strlen (frac) + 1, 1);
698 out += strlen (whole);
700 strcpy (out, frac + 1);
708 static inline mc_dec128
709 mc_dec128_from_bson_iter (bson_iter_t *it)
712 if (!bson_iter_decimal128 (it, &b)) {
713 mc_dec128 nan = MC_DEC128_POSITIVE_NAN;
717 memcpy (&ret, &b,
sizeof b);
721 static inline bson_decimal128_t
722 mc_dec128_to_bson_decimal128 (mc_dec128 v)
724 bson_decimal128_t ret;
725 memcpy (&ret, &v,
sizeof ret);
Definition: mc-dec128.h:32
The result of a dec_128 modf operation.
Definition: mc-dec128.h:404
mc_dec128 whole
The whole part of the result.
Definition: mc-dec128.h:406
mc_dec128 frac
The fractional part of the result.
Definition: mc-dec128.h:408
A type capable of holding a string rendering of a Decimal128 in engineering notation.
Definition: mc-dec128.h:206
char str[48]
The character array of the rendered value. Null-terminated.
Definition: mc-dec128.h:208