1*af3276d5Sguenther /* $OpenBSD: ldexp.c,v 1.10 2015/10/27 05:54:49 guenther Exp $ */
2af87a20cSmartynas /* @(#)s_scalbn.c 5.1 93/09/24 */
3af87a20cSmartynas /* @(#)fdlibm.h 5.1 93/09/24 */
4af87a20cSmartynas /*
5af87a20cSmartynas * ====================================================
6af87a20cSmartynas * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
7af87a20cSmartynas *
8af87a20cSmartynas * Developed at SunPro, a Sun Microsystems, Inc. business.
9af87a20cSmartynas * Permission to use, copy, modify, and distribute this
10af87a20cSmartynas * software is freely granted, provided that this notice
11af87a20cSmartynas * is preserved.
12af87a20cSmartynas * ====================================================
13af87a20cSmartynas */
14af87a20cSmartynas
15af87a20cSmartynas #include <sys/types.h>
16be9b7050Sguenther #include <endian.h>
17af87a20cSmartynas #include <float.h>
18af87a20cSmartynas #include <math.h>
19af87a20cSmartynas
20af87a20cSmartynas /* Bit fiddling routines copied from msun/src/math_private.h,v 1.15 */
21af87a20cSmartynas
22016765a7Smartynas #if (BYTE_ORDER == BIG_ENDIAN) || (defined(__arm__) && !defined(__VFP_FP__))
23af87a20cSmartynas
24af87a20cSmartynas typedef union
25af87a20cSmartynas {
26af87a20cSmartynas double value;
27af87a20cSmartynas struct
28af87a20cSmartynas {
29af87a20cSmartynas u_int32_t msw;
30af87a20cSmartynas u_int32_t lsw;
31af87a20cSmartynas } parts;
32af87a20cSmartynas } ieee_double_shape_type;
33af87a20cSmartynas
34af87a20cSmartynas #endif
35af87a20cSmartynas
36016765a7Smartynas #if (BYTE_ORDER == LITTLE_ENDIAN) && !(defined(__arm__) && !defined(__VFP_FP__))
37af87a20cSmartynas
38af87a20cSmartynas typedef union
39af87a20cSmartynas {
40af87a20cSmartynas double value;
41af87a20cSmartynas struct
42af87a20cSmartynas {
43af87a20cSmartynas u_int32_t lsw;
44af87a20cSmartynas u_int32_t msw;
45af87a20cSmartynas } parts;
46af87a20cSmartynas } ieee_double_shape_type;
47af87a20cSmartynas
48af87a20cSmartynas #endif
49af87a20cSmartynas
50af87a20cSmartynas /* Get two 32 bit ints from a double. */
51af87a20cSmartynas
52af87a20cSmartynas #define EXTRACT_WORDS(ix0,ix1,d) \
53af87a20cSmartynas do { \
54af87a20cSmartynas ieee_double_shape_type ew_u; \
55af87a20cSmartynas ew_u.value = (d); \
56af87a20cSmartynas (ix0) = ew_u.parts.msw; \
57af87a20cSmartynas (ix1) = ew_u.parts.lsw; \
58af87a20cSmartynas } while (0)
59af87a20cSmartynas
60af87a20cSmartynas /* Get the more significant 32 bit int from a double. */
61af87a20cSmartynas
62af87a20cSmartynas #define GET_HIGH_WORD(i,d) \
63af87a20cSmartynas do { \
64af87a20cSmartynas ieee_double_shape_type gh_u; \
65af87a20cSmartynas gh_u.value = (d); \
66af87a20cSmartynas (i) = gh_u.parts.msw; \
67af87a20cSmartynas } while (0)
68af87a20cSmartynas
69af87a20cSmartynas /* Set the more significant 32 bits of a double from an int. */
70af87a20cSmartynas
71af87a20cSmartynas #define SET_HIGH_WORD(d,v) \
72af87a20cSmartynas do { \
73af87a20cSmartynas ieee_double_shape_type sh_u; \
74af87a20cSmartynas sh_u.value = (d); \
75af87a20cSmartynas sh_u.parts.msw = (v); \
76af87a20cSmartynas (d) = sh_u.value; \
77af87a20cSmartynas } while (0)
78af87a20cSmartynas
79af87a20cSmartynas
80af87a20cSmartynas static const double
81af87a20cSmartynas two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
82af87a20cSmartynas twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
83af87a20cSmartynas huge = 1.0e+300,
84af87a20cSmartynas tiny = 1.0e-300;
85af87a20cSmartynas
86af87a20cSmartynas static double
_copysign(double x,double y)87af87a20cSmartynas _copysign(double x, double y)
88af87a20cSmartynas {
89af87a20cSmartynas u_int32_t hx,hy;
90af87a20cSmartynas GET_HIGH_WORD(hx,x);
91af87a20cSmartynas GET_HIGH_WORD(hy,y);
92af87a20cSmartynas SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000));
93af87a20cSmartynas return x;
94af87a20cSmartynas }
95af87a20cSmartynas
96af87a20cSmartynas double
ldexp(double x,int n)97af87a20cSmartynas ldexp(double x, int n)
98af87a20cSmartynas {
99af87a20cSmartynas int32_t k,hx,lx;
100af87a20cSmartynas EXTRACT_WORDS(hx,lx,x);
101af87a20cSmartynas k = (hx&0x7ff00000)>>20; /* extract exponent */
102af87a20cSmartynas if (k==0) { /* 0 or subnormal x */
103af87a20cSmartynas if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
104af87a20cSmartynas x *= two54;
105af87a20cSmartynas GET_HIGH_WORD(hx,x);
106af87a20cSmartynas k = ((hx&0x7ff00000)>>20) - 54;
107af87a20cSmartynas if (n< -50000) return tiny*x; /*underflow*/
108af87a20cSmartynas }
109af87a20cSmartynas if (k==0x7ff) return x+x; /* NaN or Inf */
110af87a20cSmartynas k = k+n;
111af87a20cSmartynas if (k > 0x7fe) return huge*_copysign(huge,x); /* overflow */
112af87a20cSmartynas if (k > 0) /* normal result */
113af87a20cSmartynas {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
114af87a20cSmartynas if (k <= -54) {
115af87a20cSmartynas if (n > 50000) /* in case integer overflow in n+k */
116af87a20cSmartynas return huge*_copysign(huge,x); /*overflow*/
117af87a20cSmartynas else return tiny*_copysign(tiny,x); /*underflow*/
118af87a20cSmartynas }
119af87a20cSmartynas k += 54; /* subnormal result */
120af87a20cSmartynas SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
121af87a20cSmartynas return x*twom54;
122af87a20cSmartynas }
123*af3276d5Sguenther DEF_STRONG(ldexp);
124af87a20cSmartynas
12538ffb667Sespie #if LDBL_MANT_DIG == DBL_MANT_DIG
1262fbf033eSmartynas __strong_alias(ldexpl, ldexp);
12738ffb667Sespie #endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
128