2.9
[glibc/nacl-glibc.git] / sysdeps / ieee754 / ldbl-128ibm / s_frexpl.c
blobfab566da3bd06369c172e4808c4a7bbc70247196
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.
3 */
5 /*
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
12 * is preserved.
13 * ====================================================
16 #if defined(LIBM_SCCS) && !defined(lint)
17 static char rcsid[] = "$NetBSD: $";
18 #endif
21 * for non-zero x
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
25 * arg = x*2^exp.
26 * If arg is inf, 0.0, or NaN, then frexpl(arg,&exp) returns arg
27 * with *exp=0.
30 #include "math.h"
31 #include "math_private.h"
32 #include <math_ldbl_opt.h>
34 #ifdef __STDC__
35 static const long double
36 #else
37 static long double
38 #endif
39 two107 = 162259276829213363391578010288128.0; /* 0x4670000000000000, 0 */
41 #ifdef __STDC__
42 long double __frexpl(long double x, int *eptr)
43 #else
44 long double __frexpl(x, eptr)
45 long double x; int *eptr;
46 #endif
48 u_int64_t hx, lx, ix, ixl;
49 int64_t explo;
50 GET_LDOUBLE_WORDS64(hx,lx,x);
51 ixl = 0x7fffffffffffffffULL&lx;
52 ix = 0x7fffffffffffffffULL&hx;
53 *eptr = 0;
54 if(ix>=0x7ff0000000000000ULL||((ix|ixl)==0)) return x; /* 0,inf,nan */
55 if (ix<0x0010000000000000ULL) { /* subnormal */
56 x *= two107;
57 GET_LDOUBLE_MSW64(hx,x);
58 ix = hx&0x7fffffffffffffffULL;
59 *eptr = -107;
61 *eptr += (ix>>52)-1022;
63 if (ixl != 0ULL) {
64 explo = (ixl>>52) - (ix>>52) + 0x3fe;
65 if ((ixl&0x7ff0000000000000ULL) == 0LL) {
66 /* the lower double is a denomal so we need to correct its
67 mantissa and perhaps its exponent. */
68 int cnt;
70 if (sizeof (ixl) == sizeof (long))
71 cnt = __builtin_clzl (ixl);
72 else if ((ixl >> 32) != 0)
73 cnt = __builtin_clzl ((long) (ixl >> 32));
74 else
75 cnt = __builtin_clzl ((long) ixl) + 32;
76 cnt = cnt - 12;
77 lx = (lx&0x8000000000000000ULL) | ((explo-cnt)<<52)
78 | ((ixl<<(cnt+1))&0x000fffffffffffffULL);
79 } else
80 lx = (lx&0x800fffffffffffffULL) | (explo<<52);
81 } else
82 lx = 0ULL;
84 hx = (hx&0x800fffffffffffffULL) | 0x3fe0000000000000ULL;
85 SET_LDOUBLE_WORDS64(x,hx,lx);
86 return x;
88 #ifdef IS_IN_libm
89 long_double_symbol (libm, __frexpl, frexpl);
90 #else
91 long_double_symbol (libc, __frexpl, frexpl);
92 #endif