1 /* s_frexpl.c -- long double version of s_frexp.c.
5 * ====================================================
6 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8 * Developed at SunPro, a Sun Microsystems, Inc. business.
9 * Permission to use, copy, modify, and distribute this
10 * software is freely granted, provided that this notice
12 * ====================================================
15 #if defined(LIBM_SCCS) && !defined(lint)
16 static char rcsid
[] = "$NetBSD: $";
21 * x = frexpl(arg,&exp);
22 * return a long double fp quantity x such that 0.5 <= |x| <1.0
23 * and the corresponding binary exponent "exp". That is
25 * If arg is inf, 0.0, or NaN, then frexpl(arg,&exp) returns arg
30 #include <math_private.h>
31 #include <math_ldbl_opt.h>
33 long double __frexpl(long double x
, int *eptr
)
35 uint64_t hx
, lx
, ix
, ixl
;
39 ldbl_unpack (x
, &xhi
, &xlo
);
40 EXTRACT_WORDS64 (hx
, xhi
);
41 EXTRACT_WORDS64 (lx
, xlo
);
42 ixl
= 0x7fffffffffffffffULL
& lx
;
43 ix
= 0x7fffffffffffffffULL
& hx
;
45 if (ix
>= 0x7ff0000000000000ULL
|| ix
== 0)
54 /* Denormal high double, the low double must be 0.0. */
58 if (sizeof (ix
) == sizeof (long))
59 cnt
= __builtin_clzl (ix
);
60 else if ((ix
>> 32) != 0)
61 cnt
= __builtin_clzl ((long) (ix
>> 32));
63 cnt
= __builtin_clzl ((long) ix
) + 32;
69 ix
&= 0x000fffffffffffffULL
;
70 hx
&= 0x8000000000000000ULL
;
71 hx
|= (1022LL << 52) | ix
;
75 /* If the high double is an exact power of two and the low
76 double has the opposite sign, then the exponent calculated
77 from the high double is one too big. */
79 && (int64_t) (hx
^ lx
) < 0)
88 /* The low double started out as a denormal. Normalize its
89 mantissa and adjust the exponent. */
92 if (sizeof (ixl
) == sizeof (long))
93 cnt
= __builtin_clzl (ixl
);
94 else if ((ixl
>> 32) != 0)
95 cnt
= __builtin_clzl ((long) (ixl
>> 32));
97 cnt
= __builtin_clzl ((long) ixl
) + 32;
103 /* With variable precision we can't assume much about the
104 magnitude of the returned low double. It may even be a
107 ixl
&= 0x000fffffffffffffULL
;
108 lx
&= 0x8000000000000000ULL
;
111 /* Handle denormal low double. */
121 if ((hx
& 0x7ff0000000000000ULL
) == (1023LL << 52))
123 /* Oops, the adjustment we made above for values a
124 little smaller than powers of two turned out to
125 be wrong since the returned low double will be
126 zero. This can happen if the input was
127 something weird like 0x1p1000 - 0x1p-1000. */
134 lx
|= (explo
<< 52) | ixl
;
137 INSERT_WORDS64 (xhi
, hx
);
138 INSERT_WORDS64 (xlo
, lx
);
139 x
= ldbl_pack (xhi
, xlo
);
144 long_double_symbol (libm
, __frexpl
, frexpl
);
146 long_double_symbol (libc
, __frexpl
, frexpl
);