Merge pull request #578 from PX4/fix_mp_prime_strong_lucas_lefridge_compilation
[libtommath.git] / mp_set_double.c
blob0ede359c6253fb2e6ccf14a03ee49bc2ec219966
1 #include "tommath_private.h"
2 #ifdef MP_SET_DOUBLE_C
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4 /* SPDX-License-Identifier: Unlicense */
6 #if defined(MP_HAS_SET_DOUBLE)
7 mp_err mp_set_double(mp_int *a, double b)
9 uint64_t frac;
10 int exp;
11 mp_err err;
12 union {
13 double dbl;
14 uint64_t bits;
15 } cast;
16 cast.dbl = b;
18 exp = (int)((unsigned)(cast.bits >> 52) & 0x7FFu);
19 frac = (cast.bits & (((uint64_t)1 << 52) - (uint64_t)1)) | ((uint64_t)1 << 52);
21 if (exp == 0x7FF) { /* +-inf, NaN */
22 return MP_VAL;
24 exp -= 1023 + 52;
26 mp_set_u64(a, frac);
28 err = (exp < 0) ? mp_div_2d(a, -exp, a, NULL) : mp_mul_2d(a, exp, a);
29 if (err != MP_OKAY) {
30 return err;
33 if (((cast.bits >> 63) != 0u) && !mp_iszero(a)) {
34 a->sign = MP_NEG;
37 return MP_OKAY;
39 #else
40 /* pragma message() not supported by several compilers (in mostly older but still used versions) */
41 # ifdef _MSC_VER
42 # pragma message("mp_set_double implementation is only available on platforms with IEEE754 floating point format")
43 # else
44 # warning "mp_set_double implementation is only available on platforms with IEEE754 floating point format"
45 # endif
46 #endif
47 #endif