File: set_d.c

package info (click to toggle)
flint-arb 1%3A2.23.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 14,672 kB
  • sloc: ansic: 204,753; sh: 570; makefile: 287; python: 268
file content (83 lines) | stat: -rw-r--r-- 1,660 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*
    Copyright (C) 2012 Fredrik Johansson

    This file is part of Arb.

    Arb is free software: you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License (LGPL) as published
    by the Free Software Foundation; either version 2.1 of the License, or
    (at your option) any later version.  See <http://www.gnu.org/licenses/>.
*/

#include "flint/double_extras.h"
#include "fmpr.h"

void
fmpr_set_d(fmpr_t x, double v)
{
#if FLINT_BITS == 64
    mp_limb_t h, sign, exp, frac;
    slong real_exp, real_man;
    union { double uf; mp_limb_t ul; } u;

    u.uf = v;
    h = u.ul;
    sign = h >> 63;
    exp = (h << 1) >> 53;
    frac = (h << 12) >> 12;

    if (exp == 0 && frac == 0)
    {
        fmpr_zero(x);
        return;
    }
    else if (exp == 0x7ff)
    {
        if (frac == 0)
        {
            if (sign)
                fmpr_neg_inf(x);
            else
                fmpr_pos_inf(x);
        }
        else
        {
            fmpr_nan(x);
        }
        return;
    }

    /* handle subnormals */
    if (exp == 0 && frac != 0)
    {
        int exp2;
        v = frexp(v, &exp2);
        u.uf = v;
        h = u.ul;
        sign = h >> 63;
        exp = (h << 1) >> 53;
        frac = (h << 12) >> 12;
        exp += exp2;
    }

    real_exp = exp - 1023 - 52;

    frac |= (UWORD(1) << 52);
    real_man = sign ? (-frac) : frac;

    fmpr_set_si_2exp_si(x, real_man, real_exp);
#else
    mpfr_t t;
    mp_limb_t tmp[2];

    t->_mpfr_prec = 53;
    t->_mpfr_sign = 1;
    t->_mpfr_exp = 0;
    t->_mpfr_d = tmp;

    mpfr_set_d(t, v, MPFR_RNDD);

    fmpr_set_mpfr(x, t);
#endif
}