25 #ifndef SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP |
25 #ifndef SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP |
26 #define SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP |
26 #define SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP |
27 |
27 |
28 #include <math.h> |
28 #include <math.h> |
29 |
29 |
30 // VM_LITTLE_ENDIAN is #defined appropriately in the Makefiles |
30 // Used to access the lower/higher 32 bits of a double |
31 // [jk] this is not 100% correct because the float word order may different |
31 typedef union { |
32 // from the byte order (e.g. on ARM FPA) |
32 double d; |
|
33 struct { |
33 #ifdef VM_LITTLE_ENDIAN |
34 #ifdef VM_LITTLE_ENDIAN |
34 # define __HI(x) *(1+(int*)&x) |
35 int lo; |
35 # define __LO(x) *(int*)&x |
36 int hi; |
36 #else |
37 #else |
37 # define __HI(x) *(int*)&x |
38 int hi; |
38 # define __LO(x) *(1+(int*)&x) |
39 int lo; |
39 #endif |
40 #endif |
|
41 } split; |
|
42 } DoubleIntConv; |
|
43 |
|
44 static inline int high(double d) { |
|
45 DoubleIntConv x = { d }; |
|
46 return x.split.hi; |
|
47 } |
|
48 |
|
49 static inline int low(double d) { |
|
50 DoubleIntConv x = { d }; |
|
51 return x.split.lo; |
|
52 } |
|
53 |
|
54 static inline void set_high(double* d, int high) { |
|
55 DoubleIntConv conv = { *d }; |
|
56 conv.split.hi = high; |
|
57 *d = conv.d; |
|
58 } |
|
59 |
|
60 static inline void set_low(double* d, int low) { |
|
61 DoubleIntConv conv = { *d }; |
|
62 conv.split.lo = low; |
|
63 *d = conv.d; |
|
64 } |
40 |
65 |
41 static double copysignA(double x, double y) { |
66 static double copysignA(double x, double y) { |
42 __HI(x) = (__HI(x)&0x7fffffff)|(__HI(y)&0x80000000); |
67 DoubleIntConv convX = { x }; |
43 return x; |
68 convX.split.hi = (convX.split.hi & 0x7fffffff) | (high(y) & 0x80000000); |
|
69 return convX.d; |
44 } |
70 } |
45 |
71 |
46 /* |
72 /* |
47 * ==================================================== |
73 * ==================================================== |
48 * Copyright (c) 1998 Oracle and/or its affiliates. All rights reserved. |
74 * Copyright (c) 1998 Oracle and/or its affiliates. All rights reserved. |
65 two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ |
91 two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ |
66 twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ |
92 twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ |
67 hugeX = 1.0e+300, |
93 hugeX = 1.0e+300, |
68 tiny = 1.0e-300; |
94 tiny = 1.0e-300; |
69 |
95 |
70 static double scalbnA (double x, int n) { |
96 static double scalbnA(double x, int n) { |
71 int k,hx,lx; |
97 int k,hx,lx; |
72 hx = __HI(x); |
98 hx = high(x); |
73 lx = __LO(x); |
99 lx = low(x); |
74 k = (hx&0x7ff00000)>>20; /* extract exponent */ |
100 k = (hx&0x7ff00000)>>20; /* extract exponent */ |
75 if (k==0) { /* 0 or subnormal x */ |
101 if (k==0) { /* 0 or subnormal x */ |
76 if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ |
102 if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ |
77 x *= two54; |
103 x *= two54; |
78 hx = __HI(x); |
104 hx = high(x); |
79 k = ((hx&0x7ff00000)>>20) - 54; |
105 k = ((hx&0x7ff00000)>>20) - 54; |
80 if (n< -50000) return tiny*x; /*underflow*/ |
106 if (n< -50000) return tiny*x; /*underflow*/ |
81 } |
107 } |
82 if (k==0x7ff) return x+x; /* NaN or Inf */ |
108 if (k==0x7ff) return x+x; /* NaN or Inf */ |
83 k = k+n; |
109 k = k+n; |
84 if (k > 0x7fe) return hugeX*copysignA(hugeX,x); /* overflow */ |
110 if (k > 0x7fe) return hugeX*copysignA(hugeX,x); /* overflow */ |
85 if (k > 0) /* normal result */ |
111 if (k > 0) { /* normal result */ |
86 {__HI(x) = (hx&0x800fffff)|(k<<20); return x;} |
112 set_high(&x, (hx&0x800fffff)|(k<<20)); |
|
113 return x; |
|
114 } |
87 if (k <= -54) { |
115 if (k <= -54) { |
88 if (n > 50000) /* in case integer overflow in n+k */ |
116 if (n > 50000) /* in case integer overflow in n+k */ |
89 return hugeX*copysignA(hugeX,x); /*overflow*/ |
117 return hugeX*copysignA(hugeX,x); /*overflow*/ |
90 else return tiny*copysignA(tiny,x); /*underflow*/ |
118 else return tiny*copysignA(tiny,x); /*underflow*/ |
91 } |
119 } |
92 k += 54; /* subnormal result */ |
120 k += 54; /* subnormal result */ |
93 __HI(x) = (hx&0x800fffff)|(k<<20); |
121 set_high(&x, (hx&0x800fffff)|(k<<20)); |
94 return x*twom54; |
122 return x*twom54; |
95 } |
123 } |
96 |
124 |
97 #endif // SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP |
125 #endif // SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP |