1/*
2 * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#ifndef SHARE_RUNTIME_SHAREDRUNTIMEMATH_HPP
26#define SHARE_RUNTIME_SHAREDRUNTIMEMATH_HPP
27
28#include <math.h>
29
30// Used to access the lower/higher 32 bits of a double
31typedef union {
32 double d;
33 struct {
34#ifdef VM_LITTLE_ENDIAN
35 int lo;
36 int hi;
37#else
38 int hi;
39 int lo;
40#endif
41 } split;
42} DoubleIntConv;
43
44static inline int high(double d) {
45 DoubleIntConv x;
46 x.d = d;
47 return x.split.hi;
48}
49
50static inline int low(double d) {
51 DoubleIntConv x;
52 x.d = d;
53 return x.split.lo;
54}
55
56static inline void set_high(double* d, int high) {
57 DoubleIntConv conv;
58 conv.d = *d;
59 conv.split.hi = high;
60 *d = conv.d;
61}
62
63static inline void set_low(double* d, int low) {
64 DoubleIntConv conv;
65 conv.d = *d;
66 conv.split.lo = low;
67 *d = conv.d;
68}
69
70static double copysignA(double x, double y) {
71 DoubleIntConv convX;
72 convX.d = x;
73 convX.split.hi = (convX.split.hi & 0x7fffffff) | (high(y) & 0x80000000);
74 return convX.d;
75}
76
77/*
78 * ====================================================
79 * Copyright (c) 1998 Oracle and/or its affiliates. All rights reserved.
80 *
81 * Developed at SunSoft, a Sun Microsystems, Inc. business.
82 * Permission to use, copy, modify, and distribute this
83 * software is freely granted, provided that this notice
84 * is preserved.
85 * ====================================================
86 */
87
88/*
89 * scalbn (double x, int n)
90 * scalbn(x,n) returns x* 2**n computed by exponent
91 * manipulation rather than by actually performing an
92 * exponentiation or a multiplication.
93 */
94
95static const double
96two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
97twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
98hugeX = 1.0e+300,
99tiny = 1.0e-300;
100
101static double scalbnA(double x, int n) {
102 int k,hx,lx;
103 hx = high(x);
104 lx = low(x);
105 k = (hx&0x7ff00000)>>20; /* extract exponent */
106 if (k==0) { /* 0 or subnormal x */
107 if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
108 x *= two54;
109 hx = high(x);
110 k = ((hx&0x7ff00000)>>20) - 54;
111 if (n< -50000) return tiny*x; /*underflow*/
112 }
113 if (k==0x7ff) return x+x; /* NaN or Inf */
114 k = k+n;
115 if (k > 0x7fe) return hugeX*copysignA(hugeX,x); /* overflow */
116 if (k > 0) { /* normal result */
117 set_high(&x, (hx&0x800fffff)|(k<<20));
118 return x;
119 }
120 if (k <= -54) {
121 if (n > 50000) /* in case integer overflow in n+k */
122 return hugeX*copysignA(hugeX,x); /*overflow*/
123 else return tiny*copysignA(tiny,x); /*underflow*/
124 }
125 k += 54; /* subnormal result */
126 set_high(&x, (hx&0x800fffff)|(k<<20));
127 return x*twom54;
128}
129
130#endif // SHARE_RUNTIME_SHAREDRUNTIMEMATH_HPP
131