1 /* s_frexpl.c -- long double version of s_frexp.c.
2 * Conversion to IEEE quad long double by Jakub Jelinek, jj@ultra.linux.cz.
6 * ====================================================
7 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9 * Developed at SunPro, a Sun Microsystems, Inc. business.
10 * Permission to use, copy, modify, and distribute this
11 * software is freely granted, provided that this notice
13 * ====================================================
16 #if defined(LIBM_SCCS) && !defined(lint)
17 static char rcsid
[] = "$NetBSD: $";
22 * x = frexpl(arg,&exp);
23 * return a long double fp quantity x such that 0.5 <= |x| <1.0
24 * and the corresponding binary exponent "exp". That is
26 * If arg is inf, 0.0, or NaN, then frexpl(arg,&exp) returns arg
31 #include <math_private.h>
32 #include <math_ldbl_opt.h>
34 long double __frexpl(long double x
, int *eptr
)
36 uint64_t hx
, lx
, ix
, ixl
;
40 ldbl_unpack (x
, &xhi
, &xlo
);
41 EXTRACT_WORDS64 (hx
, xhi
);
42 EXTRACT_WORDS64 (lx
, xlo
);
43 ixl
= 0x7fffffffffffffffULL
& lx
;
44 ix
= 0x7fffffffffffffffULL
& hx
;
46 if (ix
>= 0x7ff0000000000000ULL
|| ix
== 0)
55 /* Denormal high double, the low double must be 0.0. */
59 if (sizeof (ix
) == sizeof (long))
60 cnt
= __builtin_clzl (ix
);
61 else if ((ix
>> 32) != 0)
62 cnt
= __builtin_clzl ((long) (ix
>> 32));
64 cnt
= __builtin_clzl ((long) ix
) + 32;
70 ix
&= 0x000fffffffffffffULL
;
71 hx
&= 0x8000000000000000ULL
;
72 hx
|= (1022LL << 52) | ix
;
76 /* If the high double is an exact power of two and the low
77 double has the opposite sign, then the exponent calculated
78 from the high double is one too big. */
80 && (int64_t) (hx
^ lx
) < 0)
89 /* The low double started out as a denormal. Normalize its
90 mantissa and adjust the exponent. */
93 if (sizeof (ixl
) == sizeof (long))
94 cnt
= __builtin_clzl (ixl
);
95 else if ((ixl
>> 32) != 0)
96 cnt
= __builtin_clzl ((long) (ixl
>> 32));
98 cnt
= __builtin_clzl ((long) ixl
) + 32;
104 /* With variable precision we can't assume much about the
105 magnitude of the returned low double. It may even be a
108 ixl
&= 0x000fffffffffffffULL
;
109 lx
&= 0x8000000000000000ULL
;
112 /* Handle denormal low double. */
122 if ((hx
& 0x7ff0000000000000ULL
) == (1023LL << 52))
124 /* Oops, the adjustment we made above for values a
125 little smaller than powers of two turned out to
126 be wrong since the returned low double will be
127 zero. This can happen if the input was
128 something weird like 0x1p1000 - 0x1p-1000. */
135 lx
|= (explo
<< 52) | ixl
;
138 INSERT_WORDS64 (xhi
, hx
);
139 INSERT_WORDS64 (xlo
, lx
);
140 x
= ldbl_pack (xhi
, xlo
);
145 long_double_symbol (libm
, __frexpl
, frexpl
);
147 long_double_symbol (libc
, __frexpl
, frexpl
);