1dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/*
2dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Licensed to the Apache Software Foundation (ASF) under one or more
3dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * contributor license agreements.  See the NOTICE file distributed with
4dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * this work for additional information regarding copyright ownership.
5dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The ASF licenses this file to You under the Apache License, Version 2.0
6dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (the "License"); you may not use this file except in compliance with
7dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the License.  You may obtain a copy of the License at
8dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
9dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *      http://www.apache.org/licenses/LICENSE-2.0
10dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
11dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Unless required by applicable law or agreed to in writing, software
12dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * distributed under the License is distributed on an "AS IS" BASIS,
13dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See the License for the specific language governing permissions and
15dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * limitations under the License.
16dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
17dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpackage org.apache.commons.math.util;
18dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
19dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/**
20dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Faster, more accurate, portable alternative to {@link StrictMath}.
21dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>
22dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Additionally implements the following methods not found in StrictMath:
23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <ul>
24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #asinh(double)}</li>
25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #acosh(double)}</li>
26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #atanh(double)}</li>
27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </ul>
28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The following methods are found in StrictMath since 1.6 only
29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <ul>
30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #copySign(double, double)}</li>
31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #getExponent(double)}</li>
32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #nextAfter(double,double)}</li>
33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #nextUp(double)}</li>
34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #scalb(double, int)}</li>
35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #copySign(float, float)}</li>
36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #getExponent(float)}</li>
37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #nextAfter(float,double)}</li>
38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #nextUp(float)}</li>
39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li>{@link #scalb(float, int)}</li>
40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </ul>
41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 1074294 $ $Date: 2011-02-24 22:18:59 +0100 (jeu. 24 févr. 2011) $
42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @since 2.2
43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic class FastMath {
45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Archimede's constant PI, ratio of circle circumference to diameter. */
47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static final double PI = 105414357.0 / 33554432.0 + 1.984187159361080883e-9;
48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Napier's constant e, base of the natural logarithm. */
50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static final double E = 2850325.0 / 1048576.0 + 8.254840070411028747e-8;
51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Exponential evaluated at integer values,
53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * exp(x) =  expIntTableA[x + 750] + expIntTableB[x+750].
54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double EXP_INT_TABLE_A[] = new double[1500];
56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Exponential evaluated at integer values,
58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * exp(x) =  expIntTableA[x + 750] + expIntTableB[x+750]
59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double EXP_INT_TABLE_B[] = new double[1500];
61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Exponential over the range of 0 - 1 in increments of 2^-10
63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * exp(x/1024) =  expFracTableA[x] + expFracTableB[x].
64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double EXP_FRAC_TABLE_A[] = new double[1025];
66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Exponential over the range of 0 - 1 in increments of 2^-10
68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * exp(x/1024) =  expFracTableA[x] + expFracTableB[x].
69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double EXP_FRAC_TABLE_B[] = new double[1025];
71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Factorial table, for Taylor series expansions. */
73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double FACT[] = new double[20];
74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Extended precision logarithm table over the range 1 - 2 in increments of 2^-10. */
76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double LN_MANT[][] = new double[1024][];
77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** log(2) (high bits). */
79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double LN_2_A = 0.693147063255310059;
80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** log(2) (low bits). */
82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double LN_2_B = 1.17304635250823482e-7;
83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Coefficients for slowLog. */
85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double LN_SPLIT_COEF[][] = {
86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {2.0, 0.0},
87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.6666666269302368, 3.9736429850260626E-8},
88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.3999999761581421, 2.3841857910019882E-8},
89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.2857142686843872, 1.7029898543501842E-8},
90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.2222222089767456, 1.3245471311735498E-8},
91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.1818181574344635, 2.4384203044354907E-8},
92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.1538461446762085, 9.140260083262505E-9},
93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.13333332538604736, 9.220590270857665E-9},
94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.11764700710773468, 1.2393345855018391E-8},
95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.10526403784751892, 8.251545029714408E-9},
96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.0952233225107193, 1.2675934823758863E-8},
97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.08713622391223907, 1.1430250008909141E-8},
98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.07842259109020233, 2.404307984052299E-9},
99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.08371849358081818, 1.176342548272881E-8},
100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.030589580535888672, 1.2958646899018938E-9},
101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.14982303977012634, 1.225743062930824E-8},
102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    };
103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Coefficients for log, when input 0.99 < x < 1.01. */
105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double LN_QUICK_COEF[][] = {
106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {1.0, 5.669184079525E-24},
107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {-0.25, -0.25},
108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.3333333134651184, 1.986821492305628E-8},
109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {-0.25, -6.663542893624021E-14},
110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.19999998807907104, 1.1921056801463227E-8},
111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {-0.1666666567325592, -7.800414592973399E-9},
112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.1428571343421936, 5.650007086920087E-9},
113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {-0.12502530217170715, -7.44321345601866E-11},
114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.11113807559013367, 9.219544613762692E-9},
115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    };
116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Coefficients for log in the range of 1.0 < x < 1.0 + 2^-10. */
118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double LN_HI_PREC_COEF[][] = {
119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {1.0, -6.032174644509064E-23},
120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {-0.25, -0.25},
121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.3333333134651184, 1.9868161777724352E-8},
122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {-0.2499999701976776, -2.957007209750105E-8},
123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {0.19999954104423523, 1.5830993332061267E-10},
124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {-0.16624879837036133, -2.6033824355191673E-8}
125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    };
126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Sine table (high bits). */
128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double SINE_TABLE_A[] = new double[14];
129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Sine table (low bits). */
131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double SINE_TABLE_B[] = new double[14];
132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Cosine table (high bits). */
134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double COSINE_TABLE_A[] = new double[14];
135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Cosine table (low bits). */
137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double COSINE_TABLE_B[] = new double[14];
138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Tangent table, used by atan() (high bits). */
140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double TANGENT_TABLE_A[] = new double[14];
141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Tangent table, used by atan() (low bits). */
143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double TANGENT_TABLE_B[] = new double[14];
144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Bits of 1/(2*pi), need for reducePayneHanek(). */
146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final long RECIP_2PI[] = new long[] {
147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0x28be60dbL << 32) | 0x9391054aL,
148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0x7f09d5f4L << 32) | 0x7d4d3770L,
149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0x36d8a566L << 32) | 0x4f10e410L,
150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0x7f9458eaL << 32) | 0xf7aef158L,
151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0x6dc91b8eL << 32) | 0x909374b8L,
152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0x01924bbaL << 32) | 0x82746487L,
153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0x3f877ac7L << 32) | 0x2c4a69cfL,
154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0xba208d7dL << 32) | 0x4baed121L,
155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0x3a671c09L << 32) | 0xad17df90L,
156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0x4e64758eL << 32) | 0x60d4ce7dL,
157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0x272117e2L << 32) | 0xef7e4a0eL,
158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0xc7fe25ffL << 32) | 0xf7816603L,
159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0xfbcbc462L << 32) | 0xd6829b47L,
160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0xdb4d9fb3L << 32) | 0xc9f2c26dL,
161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0xd3d18fd9L << 32) | 0xa797fa8bL,
162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0x5d49eeb1L << 32) | 0xfaf97c5eL,
163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0xcf41ce7dL << 32) | 0xe294a4baL,
164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         0x9afed7ecL << 32  };
165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Bits of pi/4, need for reducePayneHanek(). */
167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final long PI_O_4_BITS[] = new long[] {
168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0xc90fdaa2L << 32) | 0x2168c234L,
169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        (0xc4c6628bL << 32) | 0x80dc1cd1L };
170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Eighths.
172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * This is used by sinQ, because its faster to do a table lookup than
173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * a multiply in this time-critical routine
174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double EIGHTHS[] = {0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0, 1.125, 1.25, 1.375, 1.5, 1.625};
176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Table of 2^((n+2)/3) */
178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double CBRTTWO[] = { 0.6299605249474366,
179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                                            0.7937005259840998,
180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                                            1.0,
181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                                            1.2599210498948732,
182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                                            1.5874010519681994 };
183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /*
185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  There are 52 bits in the mantissa of a double.
186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  For additional precision, the code splits double numbers into two parts,
187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  by clearing the low order 30 bits if possible, and then performs the arithmetic
188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  on each half separately.
189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * 0x40000000 - used to split a double into two parts, both with the low order bits cleared.
193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Equivalent to 2^30.
194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final long HEX_40000000 = 0x40000000L; // 1073741824L
196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Mask used to clear low order 30 bits */
198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final long MASK_30BITS = -1L - (HEX_40000000 -1); // 0xFFFFFFFFC0000000L;
199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** 2^52 - double numbers this large must be integral (no fraction) or NaN or Infinite */
201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final double TWO_POWER_52 = 4503599627370496.0;
202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    // Initialize tables
204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    static {
205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int i;
206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Generate an array of factorials
208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        FACT[0] = 1.0;
209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (i = 1; i < FACT.length; i++) {
210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            FACT[i] = FACT[i-1] * i;
211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double tmp[] = new double[2];
214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double recip[] = new double[2];
215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Populate expIntTable
217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (i = 0; i < 750; i++) {
218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            expint(i, tmp);
219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            EXP_INT_TABLE_A[i+750] = tmp[0];
220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            EXP_INT_TABLE_B[i+750] = tmp[1];
221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (i != 0) {
223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // Negative integer powers
224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                splitReciprocal(tmp, recip);
225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                EXP_INT_TABLE_A[750-i] = recip[0];
226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                EXP_INT_TABLE_B[750-i] = recip[1];
227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Populate expFracTable
231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (i = 0; i < EXP_FRAC_TABLE_A.length; i++) {
232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            slowexp(i/1024.0, tmp);
233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            EXP_FRAC_TABLE_A[i] = tmp[0];
234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            EXP_FRAC_TABLE_B[i] = tmp[1];
235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Populate lnMant table
238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (i = 0; i < LN_MANT.length; i++) {
239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double d = Double.longBitsToDouble( (((long) i) << 42) | 0x3ff0000000000000L );
240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            LN_MANT[i] = slowLog(d);
241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Build the sine and cosine tables
244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        buildSinCosTables();
245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Private Constructor
249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private FastMath() {
251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    // Generic helper methods
254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Get the high order bits from the mantissa.
257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Equivalent to adding and subtracting HEX_40000 but also works for very large numbers
258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param d the value to split
260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the high order part of the mantissa
261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double doubleHighPart(double d) {
263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (d > -MathUtils.SAFE_MIN && d < MathUtils.SAFE_MIN){
264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return d; // These are un-normalised - don't try to convert
265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long xl = Double.doubleToLongBits(d);
267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        xl = xl & MASK_30BITS; // Drop low order bits
268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return Double.longBitsToDouble(xl);
269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the square root of a number.
272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p><b>Note:</b> this implementation currently delegates to {@link Math#sqrt}
273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a number on which evaluation is done
274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return square root of a
275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double sqrt(final double a) {
277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return Math.sqrt(a);
278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the hyperbolic cosine of a number.
281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number on which evaluation is done
282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return hyperbolic cosine of x
283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double cosh(double x) {
285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x != x) {
286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return x;
287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x > 20.0) {
290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return exp(x)/2.0;
291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x < -20) {
294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return exp(-x)/2.0;
295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double hiPrec[] = new double[2];
298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x < 0.0) {
299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          x = -x;
300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      exp(x, 0.0, hiPrec);
302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double ya = hiPrec[0] + hiPrec[1];
304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double yb = -(ya - hiPrec[0] - hiPrec[1]);
305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double temp = ya * HEX_40000000;
307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double yaa = ya + temp - temp;
308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double yab = ya - yaa;
309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // recip = 1/y
311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double recip = 1.0/ya;
312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      temp = recip * HEX_40000000;
313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double recipa = recip + temp - temp;
314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double recipb = recip - recipa;
315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // Correct for rounding in division
317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      recipb += (1.0 - yaa*recipa - yaa*recipb - yab*recipa - yab*recipb) * recip;
318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // Account for yb
319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      recipb += -yb * recip * recip;
320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // y = y + 1/y
322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      temp = ya + recipa;
323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      yb += -(temp - ya - recipa);
324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      ya = temp;
325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      temp = ya + recipb;
326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      yb += -(temp - ya - recipb);
327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      ya = temp;
328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double result = ya + yb;
330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      result *= 0.5;
331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      return result;
332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the hyperbolic sine of a number.
335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number on which evaluation is done
336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return hyperbolic sine of x
337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double sinh(double x) {
339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      boolean negate = false;
340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x != x) {
341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return x;
342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x > 20.0) {
345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return exp(x)/2.0;
346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x < -20) {
349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return -exp(-x)/2.0;
350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x == 0) {
353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return x;
354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x < 0.0) {
357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          x = -x;
358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          negate = true;
359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double result;
362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x > 0.25) {
364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double hiPrec[] = new double[2];
365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          exp(x, 0.0, hiPrec);
366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ya = hiPrec[0] + hiPrec[1];
368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double yb = -(ya - hiPrec[0] - hiPrec[1]);
369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double temp = ya * HEX_40000000;
371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double yaa = ya + temp - temp;
372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double yab = ya - yaa;
373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // recip = 1/y
375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double recip = 1.0/ya;
376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          temp = recip * HEX_40000000;
377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double recipa = recip + temp - temp;
378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double recipb = recip - recipa;
379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // Correct for rounding in division
381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          recipb += (1.0 - yaa*recipa - yaa*recipb - yab*recipa - yab*recipb) * recip;
382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // Account for yb
383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          recipb += -yb * recip * recip;
384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          recipa = -recipa;
386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          recipb = -recipb;
387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // y = y + 1/y
389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          temp = ya + recipa;
390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          yb += -(temp - ya - recipa);
391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          ya = temp;
392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          temp = ya + recipb;
393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          yb += -(temp - ya - recipb);
394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          ya = temp;
395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          result = ya + yb;
397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          result *= 0.5;
398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      else {
400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double hiPrec[] = new double[2];
401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          expm1(x, hiPrec);
402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ya = hiPrec[0] + hiPrec[1];
404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double yb = -(ya - hiPrec[0] - hiPrec[1]);
405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          /* Compute expm1(-x) = -expm1(x) / (expm1(x) + 1) */
407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double denom = 1.0 + ya;
408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double denomr = 1.0 / denom;
409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double denomb = -(denom - 1.0 - ya) + yb;
410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ratio = ya * denomr;
411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double temp = ratio * HEX_40000000;
412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ra = ratio + temp - temp;
413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double rb = ratio - ra;
414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          temp = denom * HEX_40000000;
416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double za = denom + temp - temp;
417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double zb = denom - za;
418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          rb += (ya - za*ra - za*rb - zb*ra - zb*rb) * denomr;
420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // Adjust for yb
422dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          rb += yb*denomr;                        // numerator
423dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          rb += -ya * denomb * denomr * denomr;   // denominator
424dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
425dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // y = y - 1/y
426dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          temp = ya + ra;
427dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          yb += -(temp - ya - ra);
428dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          ya = temp;
429dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          temp = ya + rb;
430dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          yb += -(temp - ya - rb);
431dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          ya = temp;
432dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
433dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          result = ya + yb;
434dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          result *= 0.5;
435dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
436dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
437dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (negate) {
438dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          result = -result;
439dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
440dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
441dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      return result;
442dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
443dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
444dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the hyperbolic tangent of a number.
445dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number on which evaluation is done
446dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return hyperbolic tangent of x
447dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
448dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double tanh(double x) {
449dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      boolean negate = false;
450dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
451dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x != x) {
452dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return x;
453dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
454dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
455dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x > 20.0) {
456dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return 1.0;
457dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
458dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
459dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x < -20) {
460dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return -1.0;
461dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
462dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
463dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x == 0) {
464dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return x;
465dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
466dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
467dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x < 0.0) {
468dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          x = -x;
469dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          negate = true;
470dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
471dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
472dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double result;
473dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x >= 0.5) {
474dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double hiPrec[] = new double[2];
475dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // tanh(x) = (exp(2x) - 1) / (exp(2x) + 1)
476dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          exp(x*2.0, 0.0, hiPrec);
477dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
478dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ya = hiPrec[0] + hiPrec[1];
479dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double yb = -(ya - hiPrec[0] - hiPrec[1]);
480dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
481dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          /* Numerator */
482dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double na = -1.0 + ya;
483dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double nb = -(na + 1.0 - ya);
484dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double temp = na + yb;
485dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          nb += -(temp - na - yb);
486dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          na = temp;
487dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
488dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          /* Denominator */
489dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double da = 1.0 + ya;
490dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double db = -(da - 1.0 - ya);
491dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          temp = da + yb;
492dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          db += -(temp - da - yb);
493dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          da = temp;
494dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
495dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          temp = da * HEX_40000000;
496dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double daa = da + temp - temp;
497dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double dab = da - daa;
498dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
499dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // ratio = na/da
500dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ratio = na/da;
501dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          temp = ratio * HEX_40000000;
502dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ratioa = ratio + temp - temp;
503dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ratiob = ratio - ratioa;
504dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
505dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // Correct for rounding in division
506dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          ratiob += (na - daa*ratioa - daa*ratiob - dab*ratioa - dab*ratiob) / da;
507dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
508dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // Account for nb
509dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          ratiob += nb / da;
510dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // Account for db
511dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          ratiob += -db * na / da / da;
512dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
513dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          result = ratioa + ratiob;
514dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
515dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      else {
516dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double hiPrec[] = new double[2];
517dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // tanh(x) = expm1(2x) / (expm1(2x) + 2)
518dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          expm1(x*2.0, hiPrec);
519dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
520dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ya = hiPrec[0] + hiPrec[1];
521dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double yb = -(ya - hiPrec[0] - hiPrec[1]);
522dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
523dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          /* Numerator */
524dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double na = ya;
525dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double nb = yb;
526dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
527dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          /* Denominator */
528dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double da = 2.0 + ya;
529dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double db = -(da - 2.0 - ya);
530dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double temp = da + yb;
531dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          db += -(temp - da - yb);
532dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          da = temp;
533dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
534dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          temp = da * HEX_40000000;
535dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double daa = da + temp - temp;
536dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double dab = da - daa;
537dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
538dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // ratio = na/da
539dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ratio = na/da;
540dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          temp = ratio * HEX_40000000;
541dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ratioa = ratio + temp - temp;
542dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          double ratiob = ratio - ratioa;
543dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
544dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // Correct for rounding in division
545dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          ratiob += (na - daa*ratioa - daa*ratiob - dab*ratioa - dab*ratiob) / da;
546dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
547dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // Account for nb
548dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          ratiob += nb / da;
549dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // Account for db
550dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          ratiob += -db * na / da / da;
551dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
552dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          result = ratioa + ratiob;
553dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
554dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
555dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (negate) {
556dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          result = -result;
557dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
558dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
559dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      return result;
560dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
561dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
562dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the inverse hyperbolic cosine of a number.
563dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a number on which evaluation is done
564dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return inverse hyperbolic cosine of a
565dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
566dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double acosh(final double a) {
567dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return FastMath.log(a + FastMath.sqrt(a * a - 1));
568dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
569dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
570dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the inverse hyperbolic sine of a number.
571dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a number on which evaluation is done
572dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return inverse hyperbolic sine of a
573dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
574dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double asinh(double a) {
575dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
576dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        boolean negative = false;
577dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a < 0) {
578dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            negative = true;
579dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            a = -a;
580dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
581dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
582dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double absAsinh;
583dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a > 0.167) {
584dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            absAsinh = FastMath.log(FastMath.sqrt(a * a + 1) + a);
585dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
586dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double a2 = a * a;
587dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (a > 0.097) {
588dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                absAsinh = a * (1 - a2 * (1 / 3.0 - a2 * (1 / 5.0 - a2 * (1 / 7.0 - a2 * (1 / 9.0 - a2 * (1.0 / 11.0 - a2 * (1.0 / 13.0 - a2 * (1.0 / 15.0 - a2 * (1.0 / 17.0) * 15.0 / 16.0) * 13.0 / 14.0) * 11.0 / 12.0) * 9.0 / 10.0) * 7.0 / 8.0) * 5.0 / 6.0) * 3.0 / 4.0) / 2.0);
589dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else if (a > 0.036) {
590dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                absAsinh = a * (1 - a2 * (1 / 3.0 - a2 * (1 / 5.0 - a2 * (1 / 7.0 - a2 * (1 / 9.0 - a2 * (1.0 / 11.0 - a2 * (1.0 / 13.0) * 11.0 / 12.0) * 9.0 / 10.0) * 7.0 / 8.0) * 5.0 / 6.0) * 3.0 / 4.0) / 2.0);
591dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else if (a > 0.0036) {
592dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                absAsinh = a * (1 - a2 * (1 / 3.0 - a2 * (1 / 5.0 - a2 * (1 / 7.0 - a2 * (1 / 9.0) * 7.0 / 8.0) * 5.0 / 6.0) * 3.0 / 4.0) / 2.0);
593dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
594dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                absAsinh = a * (1 - a2 * (1 / 3.0 - a2 * (1 / 5.0) * 3.0 / 4.0) / 2.0);
595dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
596dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
597dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
598dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return negative ? -absAsinh : absAsinh;
599dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
600dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
601dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
602dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the inverse hyperbolic tangent of a number.
603dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a number on which evaluation is done
604dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return inverse hyperbolic tangent of a
605dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
606dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double atanh(double a) {
607dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
608dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        boolean negative = false;
609dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a < 0) {
610dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            negative = true;
611dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            a = -a;
612dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
613dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
614dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double absAtanh;
615dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a > 0.15) {
616dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            absAtanh = 0.5 * FastMath.log((1 + a) / (1 - a));
617dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
618dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double a2 = a * a;
619dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (a > 0.087) {
620dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                absAtanh = a * (1 + a2 * (1.0 / 3.0 + a2 * (1.0 / 5.0 + a2 * (1.0 / 7.0 + a2 * (1.0 / 9.0 + a2 * (1.0 / 11.0 + a2 * (1.0 / 13.0 + a2 * (1.0 / 15.0 + a2 * (1.0 / 17.0)))))))));
621dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else if (a > 0.031) {
622dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                absAtanh = a * (1 + a2 * (1.0 / 3.0 + a2 * (1.0 / 5.0 + a2 * (1.0 / 7.0 + a2 * (1.0 / 9.0 + a2 * (1.0 / 11.0 + a2 * (1.0 / 13.0)))))));
623dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else if (a > 0.003) {
624dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                absAtanh = a * (1 + a2 * (1.0 / 3.0 + a2 * (1.0 / 5.0 + a2 * (1.0 / 7.0 + a2 * (1.0 / 9.0)))));
625dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
626dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                absAtanh = a * (1 + a2 * (1.0 / 3.0 + a2 * (1.0 / 5.0)));
627dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
628dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
629dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
630dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return negative ? -absAtanh : absAtanh;
631dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
632dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
633dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
634dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the signum of a number.
635dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The signum is -1 for negative numbers, +1 for positive numbers and 0 otherwise
636dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a number on which evaluation is done
637dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return -1.0, -0.0, +0.0, +1.0 or NaN depending on sign of a
638dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
639dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double signum(final double a) {
640dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (a < 0.0) ? -1.0 : ((a > 0.0) ? 1.0 : a); // return +0.0/-0.0/NaN depending on a
641dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
642dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
643dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the signum of a number.
644dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The signum is -1 for negative numbers, +1 for positive numbers and 0 otherwise
645dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a number on which evaluation is done
646dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return -1.0, -0.0, +0.0, +1.0 or NaN depending on sign of a
647dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
648dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static float signum(final float a) {
649dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (a < 0.0f) ? -1.0f : ((a > 0.0f) ? 1.0f : a); // return +0.0/-0.0/NaN depending on a
650dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
651dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
652dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute next number towards positive infinity.
653dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a number to which neighbor should be computed
654dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return neighbor of a towards positive infinity
655dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
656dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double nextUp(final double a) {
657dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return nextAfter(a, Double.POSITIVE_INFINITY);
658dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
659dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
660dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute next number towards positive infinity.
661dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a number to which neighbor should be computed
662dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return neighbor of a towards positive infinity
663dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
664dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static float nextUp(final float a) {
665dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return nextAfter(a, Float.POSITIVE_INFINITY);
666dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
667dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
668dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Returns a pseudo-random number between 0.0 and 1.0.
669dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p><b>Note:</b> this implementation currently delegates to {@link Math#random}
670dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a random number between 0.0 and 1.0
671dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
672dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double random() {
673dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return Math.random();
674dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
675dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
676dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
677dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Exponential function.
678dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
679dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Computes exp(x), function result is nearly rounded.   It will be correctly
680dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * rounded to the theoretical value for 99.9% of input values, otherwise it will
681dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * have a 1 UPL error.
682dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
683dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Method:
684dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *    Lookup intVal = exp(int(x))
685dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *    Lookup fracVal = exp(int(x-int(x) / 1024.0) * 1024.0 );
686dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *    Compute z as the exponential of the remaining bits by a polynomial minus one
687dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *    exp(x) = intVal * fracVal * (1 + z)
688dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
689dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Accuracy:
690dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *    Calculation is done with 63 bits of precision, so result should be correctly
691dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *    rounded for 99.9% of input values, with less than 1 ULP error otherwise.
692dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
693dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x   a double
694dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return double e<sup>x</sup>
695dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
696dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double exp(double x) {
697dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return exp(x, 0.0, null);
698dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
699dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
700dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
701dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Internal helper method for exponential function.
702dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x original argument of the exponential function
703dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param extra extra bits of precision on input (To Be Confirmed)
704dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param hiPrec extra bits of precision on output (To Be Confirmed)
705dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return exp(x)
706dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
707dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double exp(double x, double extra, double[] hiPrec) {
708dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double intPartA;
709dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double intPartB;
710dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int intVal;
711dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
712dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Lookup exp(floor(x)).
713dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * intPartA will have the upper 22 bits, intPartB will have the lower
714dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * 52 bits.
715dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
716dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x < 0.0) {
717dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            intVal = (int) -x;
718dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
719dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (intVal > 746) {
720dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (hiPrec != null) {
721dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    hiPrec[0] = 0.0;
722dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    hiPrec[1] = 0.0;
723dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
724dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return 0.0;
725dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
726dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
727dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (intVal > 709) {
728dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* This will produce a subnormal output */
729dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                final double result = exp(x+40.19140625, extra, hiPrec) / 285040095144011776.0;
730dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (hiPrec != null) {
731dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    hiPrec[0] /= 285040095144011776.0;
732dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    hiPrec[1] /= 285040095144011776.0;
733dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
734dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return result;
735dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
736dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
737dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (intVal == 709) {
738dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* exp(1.494140625) is nearly a machine number... */
739dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                final double result = exp(x+1.494140625, extra, hiPrec) / 4.455505956692756620;
740dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (hiPrec != null) {
741dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    hiPrec[0] /= 4.455505956692756620;
742dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    hiPrec[1] /= 4.455505956692756620;
743dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
744dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return result;
745dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
746dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
747dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            intVal++;
748dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
749dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            intPartA = EXP_INT_TABLE_A[750-intVal];
750dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            intPartB = EXP_INT_TABLE_B[750-intVal];
751dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
752dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            intVal = -intVal;
753dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
754dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            intVal = (int) x;
755dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
756dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (intVal > 709) {
757dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (hiPrec != null) {
758dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    hiPrec[0] = Double.POSITIVE_INFINITY;
759dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    hiPrec[1] = 0.0;
760dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
761dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.POSITIVE_INFINITY;
762dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
763dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
764dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            intPartA = EXP_INT_TABLE_A[750+intVal];
765dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            intPartB = EXP_INT_TABLE_B[750+intVal];
766dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
767dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
768dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Get the fractional part of x, find the greatest multiple of 2^-10 less than
769dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * x and look up the exp function of it.
770dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * fracPartA will have the upper 22 bits, fracPartB the lower 52 bits.
771dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
772dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final int intFrac = (int) ((x - intVal) * 1024.0);
773dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double fracPartA = EXP_FRAC_TABLE_A[intFrac];
774dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double fracPartB = EXP_FRAC_TABLE_B[intFrac];
775dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
776dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* epsilon is the difference in x from the nearest multiple of 2^-10.  It
777dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * has a value in the range 0 <= epsilon < 2^-10.
778dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * Do the subtraction from x as the last step to avoid possible loss of percison.
779dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
780dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double epsilon = x - (intVal + intFrac / 1024.0);
781dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
782dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute z = exp(epsilon) - 1.0 via a minimax polynomial.  z has
783dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       full double precision (52 bits).  Since z < 2^-10, we will have
784dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       62 bits of precision when combined with the contant 1.  This will be
785dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       used in the last addition below to get proper rounding. */
786dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
787dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Remez generated polynomial.  Converges on the interval [0, 2^-10], error
788dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       is less than 0.5 ULP */
789dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double z = 0.04168701738764507;
790dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        z = z * epsilon + 0.1666666505023083;
791dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        z = z * epsilon + 0.5000000000042687;
792dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        z = z * epsilon + 1.0;
793dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        z = z * epsilon + -3.940510424527919E-20;
794dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
795dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute (intPartA+intPartB) * (fracPartA+fracPartB) by binomial
796dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       expansion.
797dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       tempA is exact since intPartA and intPartB only have 22 bits each.
798dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       tempB will have 52 bits of precision.
799dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
800dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double tempA = intPartA * fracPartA;
801dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double tempB = intPartA * fracPartB + intPartB * fracPartA + intPartB * fracPartB;
802dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
803dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute the result.  (1+z)(tempA+tempB).  Order of operations is
804dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       important.  For accuracy add by increasing size.  tempA is exact and
805dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       much larger than the others.  If there are extra bits specified from the
806dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond       pow() function, use them. */
807dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double tempC = tempB + tempA;
808dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double result;
809dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (extra != 0.0) {
810dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result = tempC*extra*z + tempC*extra + tempC*z + tempB + tempA;
811dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
812dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result = tempC*z + tempB + tempA;
813dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
814dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
815dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (hiPrec != null) {
816dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // If requesting high precision
817dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            hiPrec[0] = tempA;
818dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            hiPrec[1] = tempC*extra*z + tempC*extra + tempC*z + tempB;
819dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
820dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
821dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return result;
822dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
823dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
824dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute exp(x) - 1
825dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number to compute shifted exponential
826dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return exp(x) - 1
827dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
828dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double expm1(double x) {
829dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      return expm1(x, null);
830dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
831dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
832dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Internal helper method for expm1
833dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number to compute shifted exponential
834dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param hiPrecOut receive high precision result for -1.0 < x < 1.0
835dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return exp(x) - 1
836dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
837dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double expm1(double x, double hiPrecOut[]) {
838dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x != x || x == 0.0) { // NaN or zero
839dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return x;
840dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
841dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
842dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x <= -1.0 || x >= 1.0) {
843dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // If not between +/- 1.0
844dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            //return exp(x) - 1.0;
845dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double hiPrec[] = new double[2];
846dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            exp(x, 0.0, hiPrec);
847dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x > 0.0) {
848dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -1.0 + hiPrec[0] + hiPrec[1];
849dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
850dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                final double ra = -1.0 + hiPrec[0];
851dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double rb = -(ra + 1.0 - hiPrec[0]);
852dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                rb += hiPrec[1];
853dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return ra + rb;
854dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
855dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
856dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
857dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double baseA;
858dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double baseB;
859dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double epsilon;
860dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        boolean negative = false;
861dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
862dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x < 0.0) {
863dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            x = -x;
864dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            negative = true;
865dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
866dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
867dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {
868dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int intFrac = (int) (x * 1024.0);
869dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double tempA = EXP_FRAC_TABLE_A[intFrac] - 1.0;
870dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double tempB = EXP_FRAC_TABLE_B[intFrac];
871dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
872dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double temp = tempA + tempB;
873dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            tempB = -(temp - tempA - tempB);
874dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            tempA = temp;
875dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
876dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            temp = tempA * HEX_40000000;
877dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            baseA = tempA + temp - temp;
878dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            baseB = tempB + (tempA - baseA);
879dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
880dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            epsilon = x - intFrac/1024.0;
881dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
882dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
883dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
884dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute expm1(epsilon) */
885dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double zb = 0.008336750013465571;
886dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        zb = zb * epsilon + 0.041666663879186654;
887dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        zb = zb * epsilon + 0.16666666666745392;
888dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        zb = zb * epsilon + 0.49999999999999994;
889dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        zb = zb * epsilon;
890dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        zb = zb * epsilon;
891dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
892dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double za = epsilon;
893dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double temp = za + zb;
894dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        zb = -(temp - za - zb);
895dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        za = temp;
896dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
897dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = za * HEX_40000000;
898dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = za + temp - temp;
899dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        zb += za - temp;
900dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        za = temp;
901dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
902dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Combine the parts.   expm1(a+b) = expm1(a) + expm1(b) + expm1(a)*expm1(b) */
903dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double ya = za * baseA;
904dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //double yb = za*baseB + zb*baseA + zb*baseB;
905dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = ya + za * baseB;
906dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double yb = -(temp - ya - za * baseB);
907dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ya = temp;
908dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
909dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = ya + zb * baseA;
910dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb += -(temp - ya - zb * baseA);
911dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ya = temp;
912dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
913dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = ya + zb * baseB;
914dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb += -(temp - ya - zb*baseB);
915dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ya = temp;
916dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
917dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //ya = ya + za + baseA;
918dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //yb = yb + zb + baseB;
919dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = ya + baseA;
920dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb += -(temp - baseA - ya);
921dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ya = temp;
922dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
923dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = ya + za;
924dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //yb += (ya > za) ? -(temp - ya - za) : -(temp - za - ya);
925dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb += -(temp - ya - za);
926dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ya = temp;
927dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
928dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = ya + baseB;
929dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //yb += (ya > baseB) ? -(temp - ya - baseB) : -(temp - baseB - ya);
930dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb += -(temp - ya - baseB);
931dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ya = temp;
932dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
933dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = ya + zb;
934dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //yb += (ya > zb) ? -(temp - ya - zb) : -(temp - zb - ya);
935dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb += -(temp - ya - zb);
936dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ya = temp;
937dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
938dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (negative) {
939dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* Compute expm1(-x) = -expm1(x) / (expm1(x) + 1) */
940dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double denom = 1.0 + ya;
941dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double denomr = 1.0 / denom;
942dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double denomb = -(denom - 1.0 - ya) + yb;
943dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double ratio = ya * denomr;
944dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            temp = ratio * HEX_40000000;
945dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double ra = ratio + temp - temp;
946dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double rb = ratio - ra;
947dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
948dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            temp = denom * HEX_40000000;
949dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            za = denom + temp - temp;
950dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            zb = denom - za;
951dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
952dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            rb += (ya - za * ra - za * rb - zb * ra - zb * rb) * denomr;
953dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
954dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // f(x) = x/1+x
955dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Compute f'(x)
956dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Product rule:  d(uv) = du*v + u*dv
957dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Chain rule:  d(f(g(x)) = f'(g(x))*f(g'(x))
958dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // d(1/x) = -1/(x*x)
959dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // d(1/1+x) = -1/( (1+x)^2) *  1 =  -1/((1+x)*(1+x))
960dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // d(x/1+x) = -x/((1+x)(1+x)) + 1/1+x = 1 / ((1+x)(1+x))
961dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
962dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Adjust for yb
963dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            rb += yb * denomr;                      // numerator
964dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            rb += -ya * denomb * denomr * denomr;   // denominator
965dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
966dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // negate
967dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ya = -ra;
968dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            yb = -rb;
969dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
970dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
971dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (hiPrecOut != null) {
972dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            hiPrecOut[0] = ya;
973dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            hiPrecOut[1] = yb;
974dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
975dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
976dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return ya + yb;
977dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
978dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
979dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
980dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  For x between 0 and 1, returns exp(x), uses extended precision
981dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param x argument of exponential
982dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param result placeholder where to place exp(x) split in two terms
983dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  for extra precision (i.e. exp(x) = result[0] ° result[1]
984dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return exp(x)
985dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
986dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double slowexp(final double x, final double result[]) {
987dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double xs[] = new double[2];
988dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double ys[] = new double[2];
989dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double facts[] = new double[2];
990dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double as[] = new double[2];
991dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(x, xs);
992dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ys[0] = ys[1] = 0.0;
993dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
994dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 19; i >= 0; i--) {
995dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitMult(xs, ys, as);
996dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ys[0] = as[0];
997dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ys[1] = as[1];
998dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
999dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            split(FACT[i], as);
1000dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitReciprocal(as, facts);
1001dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1002dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitAdd(ys, facts, as);
1003dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ys[0] = as[0];
1004dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ys[1] = as[1];
1005dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1006dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1007dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (result != null) {
1008dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result[0] = ys[0];
1009dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result[1] = ys[1];
1010dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1011dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1012dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return ys[0] + ys[1];
1013dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1014dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1015dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute split[0], split[1] such that their sum is equal to d,
1016dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * and split[0] has its 30 least significant bits as zero.
1017dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param d number to split
1018dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param split placeholder where to place the result
1019dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1020dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static void split(final double d, final double split[]) {
1021dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (d < 8e298 && d > -8e298) {
1022dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double a = d * HEX_40000000;
1023dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            split[0] = (d + a) - a;
1024dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            split[1] = d - split[0];
1025dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
1026dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double a = d * 9.31322574615478515625E-10;
1027dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            split[0] = (d + a - d) * HEX_40000000;
1028dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            split[1] = d - split[0];
1029dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1030dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1031dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1032dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Recompute a split.
1033dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a input/out array containing the split, changed
1034dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * on output
1035dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1036dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static void resplit(final double a[]) {
1037dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double c = a[0] + a[1];
1038dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double d = -(c - a[0] - a[1]);
1039dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1040dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (c < 8e298 && c > -8e298) {
1041dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double z = c * HEX_40000000;
1042dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            a[0] = (c + z) - z;
1043dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            a[1] = c - a[0] + d;
1044dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
1045dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double z = c * 9.31322574615478515625E-10;
1046dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            a[0] = (c + z - c) * HEX_40000000;
1047dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            a[1] = c - a[0] + d;
1048dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1049dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1050dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1051dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Multiply two numbers in split form.
1052dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a first term of multiplication
1053dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param b second term of multiplication
1054dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param ans placeholder where to put the result
1055dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1056dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static void splitMult(double a[], double b[], double ans[]) {
1057dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ans[0] = a[0] * b[0];
1058dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ans[1] = a[0] * b[1] + a[1] * b[0] + a[1] * b[1];
1059dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1060dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Resplit */
1061dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        resplit(ans);
1062dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1063dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1064dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Add two numbers in split form.
1065dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a first term of addition
1066dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param b second term of addition
1067dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param ans placeholder where to put the result
1068dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1069dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static void splitAdd(final double a[], final double b[], final double ans[]) {
1070dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ans[0] = a[0] + b[0];
1071dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ans[1] = a[1] + b[1];
1072dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1073dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        resplit(ans);
1074dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1075dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1076dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the reciprocal of in.  Use the following algorithm.
1077dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  in = c + d.
1078dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  want to find x + y such that x+y = 1/(c+d) and x is much
1079dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  larger than y and x has several zero bits on the right.
1080dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
1081dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Set b = 1/(2^22),  a = 1 - b.  Thus (a+b) = 1.
1082dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Use following identity to compute (a+b)/(c+d)
1083dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
1084dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  (a+b)/(c+d)  =   a/c   +    (bc - ad) / (c^2 + cd)
1085dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  set x = a/c  and y = (bc - ad) / (c^2 + cd)
1086dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  This will be close to the right answer, but there will be
1087dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  some rounding in the calculation of X.  So by carefully
1088dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  computing 1 - (c+d)(x+y) we can compute an error and
1089dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  add that back in.   This is done carefully so that terms
1090dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  of similar size are subtracted first.
1091dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param in initial number, in split form
1092dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param result placeholder where to put the result
1093dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1094dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static void splitReciprocal(final double in[], final double result[]) {
1095dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double b = 1.0/4194304.0;
1096dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double a = 1.0 - b;
1097dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1098dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (in[0] == 0.0) {
1099dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            in[0] = in[1];
1100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            in[1] = 0.0;
1101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[0] = a / in[0];
1104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[1] = (b*in[0]-a*in[1]) / (in[0]*in[0] + in[0]*in[1]);
1105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (result[1] != result[1]) { // can happen if result[1] is NAN
1107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result[1] = 0.0;
1108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Resplit */
1111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        resplit(result);
1112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < 2; i++) {
1114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* this may be overkill, probably once is enough */
1115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double err = 1.0 - result[0] * in[0] - result[0] * in[1] -
1116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result[1] * in[0] - result[1] * in[1];
1117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /*err = 1.0 - err; */
1118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            err = err * (result[0] + result[1]);
1119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /*printf("err = %16e\n", err); */
1120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result[1] += err;
1121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute (a[0] + a[1]) * (b[0] + b[1]) in extended precision.
1125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a first term of the multiplication
1126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param b second term of the multiplication
1127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param result placeholder where to put the result
1128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static void quadMult(final double a[], final double b[], final double result[]) {
1130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double xs[] = new double[2];
1131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double ys[] = new double[2];
1132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double zs[] = new double[2];
1133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* a[0] * b[0] */
1135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(a[0], xs);
1136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(b[0], ys);
1137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        splitMult(xs, ys, zs);
1138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[0] = zs[0];
1140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[1] = zs[1];
1141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* a[0] * b[1] */
1143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(b[1], ys);
1144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        splitMult(xs, ys, zs);
1145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double tmp = result[0] + zs[0];
1147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[1] = result[1] - (tmp - result[0] - zs[0]);
1148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[0] = tmp;
1149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        tmp = result[0] + zs[1];
1150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[1] = result[1] - (tmp - result[0] - zs[1]);
1151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[0] = tmp;
1152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* a[1] * b[0] */
1154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(a[1], xs);
1155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(b[0], ys);
1156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        splitMult(xs, ys, zs);
1157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        tmp = result[0] + zs[0];
1159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[1] = result[1] - (tmp - result[0] - zs[0]);
1160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[0] = tmp;
1161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        tmp = result[0] + zs[1];
1162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[1] = result[1] - (tmp - result[0] - zs[1]);
1163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[0] = tmp;
1164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* a[1] * b[0] */
1166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(a[1], xs);
1167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(b[1], ys);
1168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        splitMult(xs, ys, zs);
1169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        tmp = result[0] + zs[0];
1171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[1] = result[1] - (tmp - result[0] - zs[0]);
1172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[0] = tmp;
1173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        tmp = result[0] + zs[1];
1174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[1] = result[1] - (tmp - result[0] - zs[1]);
1175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[0] = tmp;
1176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute exp(p) for a integer p in extended precision.
1179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param p integer whose exponential is requested
1180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param result placeholder where to put the result in extended precision
1181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return exp(p) in standard precision (equal to result[0] + result[1])
1182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double expint(int p, final double result[]) {
1184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //double x = M_E;
1185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double xs[] = new double[2];
1186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double as[] = new double[2];
1187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double ys[] = new double[2];
1188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //split(x, xs);
1189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //xs[1] = (double)(2.7182818284590452353602874713526625L - xs[0]);
1190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //xs[0] = 2.71827697753906250000;
1191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //xs[1] = 4.85091998273542816811e-06;
1192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //xs[0] = Double.longBitsToDouble(0x4005bf0800000000L);
1193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //xs[1] = Double.longBitsToDouble(0x3ed458a2bb4a9b00L);
1194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* E */
1196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        xs[0] = 2.718281828459045;
1197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        xs[1] = 1.4456468917292502E-16;
1198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(1.0, ys);
1200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (p > 0) {
1202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if ((p & 1) != 0) {
1203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                quadMult(ys, xs, as);
1204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ys[0] = as[0]; ys[1] = as[1];
1205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            quadMult(xs, xs, as);
1208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xs[0] = as[0]; xs[1] = as[1];
1209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            p >>= 1;
1211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (result != null) {
1214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result[0] = ys[0];
1215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result[1] = ys[1];
1216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            resplit(result);
1218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return ys[0] + ys[1];
1221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
1225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Natural logarithm.
1226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
1227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x   a double
1228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return log(x)
1229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double log(final double x) {
1231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return log(x, null);
1232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
1235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Internal helper method for natural logarithm function.
1236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x original argument of the natural logarithm function
1237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param hiPrec extra bits of precision on output (To Be Confirmed)
1238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return log(x)
1239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double log(final double x, final double[] hiPrec) {
1241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x==0) { // Handle special case of +0/-0
1242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.NEGATIVE_INFINITY;
1243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long bits = Double.doubleToLongBits(x);
1245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Handle special cases of negative input, and NaN */
1247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((bits & 0x8000000000000000L) != 0 || x != x) {
1248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x != 0.0) {
1249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (hiPrec != null) {
1250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    hiPrec[0] = Double.NaN;
1251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
1252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.NaN;
1254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Handle special cases of Positive infinity. */
1258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x == Double.POSITIVE_INFINITY) {
1259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (hiPrec != null) {
1260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                hiPrec[0] = Double.POSITIVE_INFINITY;
1261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.POSITIVE_INFINITY;
1264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Extract the exponent */
1267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int exp = (int)(bits >> 52)-1023;
1268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((bits & 0x7ff0000000000000L) == 0) {
1270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Subnormal!
1271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x == 0) {
1272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // Zero
1273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (hiPrec != null) {
1274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    hiPrec[0] = Double.NEGATIVE_INFINITY;
1275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
1276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.NEGATIVE_INFINITY;
1278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* Normalize the subnormal number. */
1281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            bits <<= 1;
1282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            while ( (bits & 0x0010000000000000L) == 0) {
1283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                exp--;
1284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                bits <<= 1;
1285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (exp == -1 || exp == 0) {
1290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x < 1.01 && x > 0.99 && hiPrec == null) {
1291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* The normal method doesn't work well in the range [0.99, 1.01], so call do a straight
1292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond           polynomial expansion in higer precision. */
1293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               /* Compute x - 1.0 and split it */
1295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double xa = x - 1.0;
1296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double xb = xa - x + 1.0;
1297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double tmp = xa * HEX_40000000;
1298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double aa = xa + tmp - tmp;
1299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double ab = xa - aa;
1300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                xa = aa;
1301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                xb = ab;
1302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double ya = LN_QUICK_COEF[LN_QUICK_COEF.length-1][0];
1304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double yb = LN_QUICK_COEF[LN_QUICK_COEF.length-1][1];
1305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                for (int i = LN_QUICK_COEF.length - 2; i >= 0; i--) {
1307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    /* Multiply a = y * x */
1308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    aa = ya * xa;
1309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    ab = ya * xb + yb * xa + yb * xb;
1310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    /* split, so now y = a */
1311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    tmp = aa * HEX_40000000;
1312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    ya = aa + tmp - tmp;
1313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    yb = aa - ya + ab;
1314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    /* Add  a = y + lnQuickCoef */
1316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    aa = ya + LN_QUICK_COEF[i][0];
1317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    ab = yb + LN_QUICK_COEF[i][1];
1318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    /* Split y = a */
1319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    tmp = aa * HEX_40000000;
1320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    ya = aa + tmp - tmp;
1321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    yb = aa - ya + ab;
1322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
1323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* Multiply a = y * x */
1325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                aa = ya * xa;
1326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ab = ya * xb + yb * xa + yb * xb;
1327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* split, so now y = a */
1328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                tmp = aa * HEX_40000000;
1329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ya = aa + tmp - tmp;
1330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                yb = aa - ya + ab;
1331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return ya + yb;
1333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // lnm is a log of a number in the range of 1.0 - 2.0, so 0 <= lnm < ln(2)
1337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double lnm[] = LN_MANT[(int)((bits & 0x000ffc0000000000L) >> 42)];
1338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /*
1340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    double epsilon = x / Double.longBitsToDouble(bits & 0xfffffc0000000000L);
1341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    epsilon -= 1.0;
1343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
1344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // y is the most significant 10 bits of the mantissa
1346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //double y = Double.longBitsToDouble(bits & 0xfffffc0000000000L);
1347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //double epsilon = (x - y) / y;
1348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double epsilon = (bits & 0x3ffffffffffL) / (TWO_POWER_52 + (bits & 0x000ffc0000000000L));
1349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double lnza = 0.0;
1351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double lnzb = 0.0;
1352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (hiPrec != null) {
1354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* split epsilon -> x */
1355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double tmp = epsilon * HEX_40000000;
1356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double aa = epsilon + tmp - tmp;
1357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double ab = epsilon - aa;
1358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double xa = aa;
1359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double xb = ab;
1360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* Need a more accurate epsilon, so adjust the division. */
1362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double numer = bits & 0x3ffffffffffL;
1363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double denom = TWO_POWER_52 + (bits & 0x000ffc0000000000L);
1364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            aa = numer - xa*denom - xb * denom;
1365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xb += aa / denom;
1366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* Remez polynomial evaluation */
1368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double ya = LN_HI_PREC_COEF[LN_HI_PREC_COEF.length-1][0];
1369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double yb = LN_HI_PREC_COEF[LN_HI_PREC_COEF.length-1][1];
1370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            for (int i = LN_HI_PREC_COEF.length - 2; i >= 0; i--) {
1372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* Multiply a = y * x */
1373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                aa = ya * xa;
1374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ab = ya * xb + yb * xa + yb * xb;
1375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* split, so now y = a */
1376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                tmp = aa * HEX_40000000;
1377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ya = aa + tmp - tmp;
1378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                yb = aa - ya + ab;
1379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* Add  a = y + lnHiPrecCoef */
1381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                aa = ya + LN_HI_PREC_COEF[i][0];
1382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ab = yb + LN_HI_PREC_COEF[i][1];
1383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* Split y = a */
1384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                tmp = aa * HEX_40000000;
1385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ya = aa + tmp - tmp;
1386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                yb = aa - ya + ab;
1387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* Multiply a = y * x */
1390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            aa = ya * xa;
1391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ab = ya * xb + yb * xa + yb * xb;
1392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* split, so now lnz = a */
1394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /*
1395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      tmp = aa * 1073741824.0;
1396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      lnza = aa + tmp - tmp;
1397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      lnzb = aa - lnza + ab;
1398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond             */
1399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            lnza = aa + ab;
1400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            lnzb = -(lnza - aa - ab);
1401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
1402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* High precision not required.  Eval Remez polynomial
1403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         using standard double precision */
1404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            lnza = -0.16624882440418567;
1405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            lnza = lnza * epsilon + 0.19999954120254515;
1406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            lnza = lnza * epsilon + -0.2499999997677497;
1407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            lnza = lnza * epsilon + 0.3333333333332802;
1408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            lnza = lnza * epsilon + -0.5;
1409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            lnza = lnza * epsilon + 1.0;
1410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            lnza = lnza * epsilon;
1411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Relative sizes:
1414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * lnzb     [0, 2.33E-10]
1415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * lnm[1]   [0, 1.17E-7]
1416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * ln2B*exp [0, 1.12E-4]
1417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * lnza      [0, 9.7E-4]
1418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * lnm[0]   [0, 0.692]
1419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * ln2A*exp [0, 709]
1420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
1421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1422dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute the following sum:
1423dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * lnzb + lnm[1] + ln2B*exp + lnza + lnm[0] + ln2A*exp;
1424dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
1425dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1426dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //return lnzb + lnm[1] + ln2B*exp + lnza + lnm[0] + ln2A*exp;
1427dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double a = LN_2_A*exp;
1428dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double b = 0.0;
1429dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double c = a+lnm[0];
1430dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double d = -(c-a-lnm[0]);
1431dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = c;
1432dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + d;
1433dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1434dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = a + lnza;
1435dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = -(c - a - lnza);
1436dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = c;
1437dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + d;
1438dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1439dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = a + LN_2_B*exp;
1440dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = -(c - a - LN_2_B*exp);
1441dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = c;
1442dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + d;
1443dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1444dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = a + lnm[1];
1445dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = -(c - a - lnm[1]);
1446dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = c;
1447dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + d;
1448dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1449dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = a + lnzb;
1450dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = -(c - a - lnzb);
1451dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = c;
1452dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + d;
1453dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1454dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (hiPrec != null) {
1455dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            hiPrec[0] = a;
1456dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            hiPrec[1] = b;
1457dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1458dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1459dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return a + b;
1460dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1461dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1462dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute log(1 + x).
1463dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x a number
1464dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return log(1 + x)
1465dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1466dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double log1p(final double x) {
1467dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xpa = 1.0 + x;
1468dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xpb = -(xpa - 1.0 - x);
1469dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1470dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x == -1) {
1471dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return x/0.0;   // -Infinity
1472dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1473dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1474dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x > 0 && 1/x == 0) { // x = Infinity
1475dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return x;
1476dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1477dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1478dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x>1e-6 || x<-1e-6) {
1479dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double hiPrec[] = new double[2];
1480dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1481dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double lores = log(xpa, hiPrec);
1482dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (Double.isInfinite(lores)){ // don't allow this to be converted to NaN
1483dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return lores;
1484dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1485dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1486dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* Do a taylor series expansion around xpa */
1487dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* f(x+y) = f(x) + f'(x)*y + f''(x)/2 y^2 */
1488dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double fx1 = xpb/xpa;
1489dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1490dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double epsilon = 0.5 * fx1 + 1.0;
1491dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            epsilon = epsilon * fx1;
1492dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1493dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return epsilon + hiPrec[1] + hiPrec[0];
1494dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1495dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1496dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Value is small |x| < 1e6, do a Taylor series centered on 1.0 */
1497dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double y = x * 0.333333333333333 - 0.5;
1498dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        y = y * x + 1.0;
1499dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        y = y * x;
1500dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1501dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return y;
1502dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1503dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1504dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the base 10 logarithm.
1505dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x a number
1506dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return log10(x)
1507dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1508dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double log10(final double x) {
1509dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double hiPrec[] = new double[2];
1510dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1511dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double lores = log(x, hiPrec);
1512dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Double.isInfinite(lores)){ // don't allow this to be converted to NaN
1513dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return lores;
1514dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1515dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1516dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double tmp = hiPrec[0] * HEX_40000000;
1517dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double lna = hiPrec[0] + tmp - tmp;
1518dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double lnb = hiPrec[0] - lna + hiPrec[1];
1519dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1520dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double rln10a = 0.4342944622039795;
1521dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double rln10b = 1.9699272335463627E-8;
1522dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1523dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return rln10b * lnb + rln10b * lna + rln10a * lnb + rln10a * lna;
1524dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1525dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1526dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
1527dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Power function.  Compute x^y.
1528dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
1529dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x   a double
1530dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param y   a double
1531dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return double
1532dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1533dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double pow(double x, double y) {
1534dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double lns[] = new double[2];
1535dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1536dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (y == 0.0) {
1537dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return 1.0;
1538dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1539dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1540dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x != x) { // X is NaN
1541dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return x;
1542dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1543dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1544dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1545dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x == 0) {
1546dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            long bits = Double.doubleToLongBits(x);
1547dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if ((bits & 0x8000000000000000L) != 0) {
1548dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // -zero
1549dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                long yi = (long) y;
1550dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1551dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (y < 0 && y == yi && (yi & 1) == 1) {
1552dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return Double.NEGATIVE_INFINITY;
1553dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
1554dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1555dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (y < 0 && y == yi && (yi & 1) == 1) {
1556dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return -0.0;
1557dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
1558dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1559dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (y > 0 && y == yi && (yi & 1) == 1) {
1560dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return -0.0;
1561dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
1562dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1563dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1564dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y < 0) {
1565dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.POSITIVE_INFINITY;
1566dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1567dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y > 0) {
1568dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return 0.0;
1569dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1570dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1571dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.NaN;
1572dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1573dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1574dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x == Double.POSITIVE_INFINITY) {
1575dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y != y) { // y is NaN
1576dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return y;
1577dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1578dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y < 0.0) {
1579dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return 0.0;
1580dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
1581dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.POSITIVE_INFINITY;
1582dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1583dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1584dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1585dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (y == Double.POSITIVE_INFINITY) {
1586dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x * x == 1.0)
1587dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond              return Double.NaN;
1588dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1589dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x * x > 1.0) {
1590dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.POSITIVE_INFINITY;
1591dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
1592dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return 0.0;
1593dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1594dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1595dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1596dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x == Double.NEGATIVE_INFINITY) {
1597dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y != y) { // y is NaN
1598dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return y;
1599dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1600dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1601dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y < 0) {
1602dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                long yi = (long) y;
1603dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (y == yi && (yi & 1) == 1) {
1604dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return -0.0;
1605dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
1606dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1607dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return 0.0;
1608dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1609dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1610dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y > 0)  {
1611dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                long yi = (long) y;
1612dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (y == yi && (yi & 1) == 1) {
1613dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return Double.NEGATIVE_INFINITY;
1614dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
1615dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1616dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.POSITIVE_INFINITY;
1617dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1618dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1619dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1620dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (y == Double.NEGATIVE_INFINITY) {
1621dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1622dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x * x == 1.0) {
1623dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.NaN;
1624dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1625dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1626dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x * x < 1.0) {
1627dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.POSITIVE_INFINITY;
1628dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
1629dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return 0.0;
1630dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1631dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1632dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1633dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Handle special case x<0 */
1634dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x < 0) {
1635dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // y is an even integer in this case
1636dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y >= TWO_POWER_52 || y <= -TWO_POWER_52) {
1637dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return pow(-x, y);
1638dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1639dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1640dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y == (long) y) {
1641dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // If y is an integer
1642dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return ((long)y & 1) == 0 ? pow(-x, y) : -pow(-x, y);
1643dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
1644dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.NaN;
1645dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1646dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1647dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1648dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Split y into ya and yb such that y = ya+yb */
1649dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double ya;
1650dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double yb;
1651dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (y < 8e298 && y > -8e298) {
1652dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double tmp1 = y * HEX_40000000;
1653dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ya = y + tmp1 - tmp1;
1654dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            yb = y - ya;
1655dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
1656dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double tmp1 = y * 9.31322574615478515625E-10;
1657dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double tmp2 = tmp1 * 9.31322574615478515625E-10;
1658dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ya = (tmp1 + tmp2 - tmp1) * HEX_40000000 * HEX_40000000;
1659dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            yb = y - ya;
1660dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1661dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1662dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute ln(x) */
1663dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double lores = log(x, lns);
1664dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Double.isInfinite(lores)){ // don't allow this to be converted to NaN
1665dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return lores;
1666dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1667dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1668dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double lna = lns[0];
1669dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double lnb = lns[1];
1670dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1671dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* resplit lns */
1672dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double tmp1 = lna * HEX_40000000;
1673dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double tmp2 = lna + tmp1 - tmp1;
1674dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        lnb += lna - tmp2;
1675dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        lna = tmp2;
1676dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1677dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // y*ln(x) = (aa+ab)
1678dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double aa = lna * ya;
1679dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double ab = lna * yb + lnb * ya + lnb * yb;
1680dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1681dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        lna = aa+ab;
1682dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        lnb = -(lna - aa - ab);
1683dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1684dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double z = 1.0 / 120.0;
1685dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        z = z * lnb + (1.0 / 24.0);
1686dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        z = z * lnb + (1.0 / 6.0);
1687dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        z = z * lnb + 0.5;
1688dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        z = z * lnb + 1.0;
1689dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        z = z * lnb;
1690dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1691dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double result = exp(lna, z, null);
1692dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //result = result + result * z;
1693dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return result;
1694dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1695dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1696dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** xi in the range of [1, 2].
1697dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *                                3        5        7
1698dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *      x+1           /          x        x        x          \
1699dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  ln ----- =   2 *  |  x  +   ----  +  ----  +  ---- + ...  |
1700dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *      1-x           \          3        5        7          /
1701dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
1702dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * So, compute a Remez approximation of the following function
1703dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
1704dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  ln ((sqrt(x)+1)/(1-sqrt(x)))  /  x
1705dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
1706dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * This will be an even function with only positive coefficents.
1707dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * x is in the range [0 - 1/3].
1708dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
1709dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Transform xi for input to the above function by setting
1710dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * x = (xi-1)/(xi+1).   Input to the polynomial is x^2, then
1711dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the result is multiplied by x.
1712dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param xi number from which log is requested
1713dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return log(xi)
1714dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1715dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double[] slowLog(double xi) {
1716dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double x[] = new double[2];
1717dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double x2[] = new double[2];
1718dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double y[] = new double[2];
1719dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double a[] = new double[2];
1720dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1721dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(xi, x);
1722dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1723dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Set X = (x-1)/(x+1) */
1724dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        x[0] += 1.0;
1725dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        resplit(x);
1726dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        splitReciprocal(x, a);
1727dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        x[0] -= 2.0;
1728dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        resplit(x);
1729dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        splitMult(x, a, y);
1730dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        x[0] = y[0];
1731dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        x[1] = y[1];
1732dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1733dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Square X -> X2*/
1734dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        splitMult(x, x, x2);
1735dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1736dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1737dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //x[0] -= 1.0;
1738dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //resplit(x);
1739dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1740dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        y[0] = LN_SPLIT_COEF[LN_SPLIT_COEF.length-1][0];
1741dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        y[1] = LN_SPLIT_COEF[LN_SPLIT_COEF.length-1][1];
1742dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1743dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = LN_SPLIT_COEF.length-2; i >= 0; i--) {
1744dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitMult(y, x2, a);
1745dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            y[0] = a[0];
1746dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            y[1] = a[1];
1747dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitAdd(y, LN_SPLIT_COEF[i], a);
1748dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            y[0] = a[0];
1749dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            y[1] = a[1];
1750dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1751dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1752dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        splitMult(y, x, a);
1753dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        y[0] = a[0];
1754dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        y[1] = a[1];
1755dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1756dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return y;
1757dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1758dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1759dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
1760dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For x between 0 and pi/4 compute sine.
1761dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which sine is requested
1762dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param result placeholder where to put the result in extended precision
1763dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return sin(x)
1764dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1765dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double slowSin(final double x, final double result[]) {
1766dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double xs[] = new double[2];
1767dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double ys[] = new double[2];
1768dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double facts[] = new double[2];
1769dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double as[] = new double[2];
1770dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(x, xs);
1771dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ys[0] = ys[1] = 0.0;
1772dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1773dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 19; i >= 0; i--) {
1774dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitMult(xs, ys, as);
1775dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ys[0] = as[0]; ys[1] = as[1];
1776dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1777dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if ( (i & 1) == 0) {
1778dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                continue;
1779dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1780dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1781dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            split(FACT[i], as);
1782dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitReciprocal(as, facts);
1783dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1784dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if ( (i & 2) != 0 ) {
1785dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                facts[0] = -facts[0];
1786dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                facts[1] = -facts[1];
1787dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1788dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1789dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitAdd(ys, facts, as);
1790dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ys[0] = as[0]; ys[1] = as[1];
1791dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1792dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1793dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (result != null) {
1794dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result[0] = ys[0];
1795dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result[1] = ys[1];
1796dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1797dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1798dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return ys[0] + ys[1];
1799dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1800dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1801dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
1802dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  For x between 0 and pi/4 compute cosine
1803dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which cosine is requested
1804dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param result placeholder where to put the result in extended precision
1805dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return cos(x)
1806dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1807dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double slowCos(final double x, final double result[]) {
1808dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1809dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double xs[] = new double[2];
1810dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double ys[] = new double[2];
1811dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double facts[] = new double[2];
1812dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double as[] = new double[2];
1813dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        split(x, xs);
1814dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ys[0] = ys[1] = 0.0;
1815dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1816dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 19; i >= 0; i--) {
1817dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitMult(xs, ys, as);
1818dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ys[0] = as[0]; ys[1] = as[1];
1819dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1820dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if ( (i & 1) != 0) {
1821dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                continue;
1822dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1823dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1824dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            split(FACT[i], as);
1825dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitReciprocal(as, facts);
1826dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1827dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if ( (i & 2) != 0 ) {
1828dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                facts[0] = -facts[0];
1829dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                facts[1] = -facts[1];
1830dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1831dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1832dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitAdd(ys, facts, as);
1833dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ys[0] = as[0]; ys[1] = as[1];
1834dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1835dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1836dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (result != null) {
1837dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result[0] = ys[0];
1838dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result[1] = ys[1];
1839dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1840dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1841dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return ys[0] + ys[1];
1842dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1843dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1844dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Build the sine and cosine tables.
1845dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1846dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static void buildSinCosTables() {
1847dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double result[] = new double[2];
1848dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1849dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Use taylor series for 0 <= x <= 6/8 */
1850dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < 7; i++) {
1851dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double x = i / 8.0;
1852dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1853dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            slowSin(x, result);
1854dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            SINE_TABLE_A[i] = result[0];
1855dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            SINE_TABLE_B[i] = result[1];
1856dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1857dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            slowCos(x, result);
1858dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            COSINE_TABLE_A[i] = result[0];
1859dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            COSINE_TABLE_B[i] = result[1];
1860dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1861dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1862dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Use angle addition formula to complete table to 13/8, just beyond pi/2 */
1863dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 7; i < 14; i++) {
1864dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double xs[] = new double[2];
1865dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double ys[] = new double[2];
1866dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double as[] = new double[2];
1867dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double bs[] = new double[2];
1868dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double temps[] = new double[2];
1869dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1870dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if ( (i & 1) == 0) {
1871dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // Even, use double angle
1872dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                xs[0] = SINE_TABLE_A[i/2];
1873dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                xs[1] = SINE_TABLE_B[i/2];
1874dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ys[0] = COSINE_TABLE_A[i/2];
1875dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ys[1] = COSINE_TABLE_B[i/2];
1876dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1877dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* compute sine */
1878dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                splitMult(xs, ys, result);
1879dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                SINE_TABLE_A[i] = result[0] * 2.0;
1880dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                SINE_TABLE_B[i] = result[1] * 2.0;
1881dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1882dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* Compute cosine */
1883dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                splitMult(ys, ys, as);
1884dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                splitMult(xs, xs, temps);
1885dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                temps[0] = -temps[0];
1886dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                temps[1] = -temps[1];
1887dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                splitAdd(as, temps, result);
1888dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                COSINE_TABLE_A[i] = result[0];
1889dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                COSINE_TABLE_B[i] = result[1];
1890dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
1891dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                xs[0] = SINE_TABLE_A[i/2];
1892dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                xs[1] = SINE_TABLE_B[i/2];
1893dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ys[0] = COSINE_TABLE_A[i/2];
1894dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ys[1] = COSINE_TABLE_B[i/2];
1895dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                as[0] = SINE_TABLE_A[i/2+1];
1896dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                as[1] = SINE_TABLE_B[i/2+1];
1897dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                bs[0] = COSINE_TABLE_A[i/2+1];
1898dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                bs[1] = COSINE_TABLE_B[i/2+1];
1899dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1900dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* compute sine */
1901dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                splitMult(xs, bs, temps);
1902dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                splitMult(ys, as, result);
1903dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                splitAdd(result, temps, result);
1904dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                SINE_TABLE_A[i] = result[0];
1905dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                SINE_TABLE_B[i] = result[1];
1906dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1907dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                /* Compute cosine */
1908dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                splitMult(ys, bs, result);
1909dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                splitMult(xs, as, temps);
1910dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                temps[0] = -temps[0];
1911dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                temps[1] = -temps[1];
1912dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                splitAdd(result, temps, result);
1913dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                COSINE_TABLE_A[i] = result[0];
1914dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                COSINE_TABLE_B[i] = result[1];
1915dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
1916dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1917dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1918dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute tangent = sine/cosine */
1919dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < 14; i++) {
1920dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double xs[] = new double[2];
1921dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double ys[] = new double[2];
1922dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double as[] = new double[2];
1923dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1924dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            as[0] = COSINE_TABLE_A[i];
1925dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            as[1] = COSINE_TABLE_B[i];
1926dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1927dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitReciprocal(as, ys);
1928dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1929dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xs[0] = SINE_TABLE_A[i];
1930dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xs[1] = SINE_TABLE_B[i];
1931dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1932dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            splitMult(xs, ys, as);
1933dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1934dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            TANGENT_TABLE_A[i] = as[0];
1935dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            TANGENT_TABLE_B[i] = as[1];
1936dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
1937dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1938dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1939dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1940dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
1941dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Computes sin(x) - x, where |x| < 1/16.
1942dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Use a Remez polynomial approximation.
1943dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param x a number smaller than 1/16
1944dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return sin(x) - x
1945dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1946dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double polySine(final double x)
1947dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    {
1948dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double x2 = x*x;
1949dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1950dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double p = 2.7553817452272217E-6;
1951dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        p = p * x2 + -1.9841269659586505E-4;
1952dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        p = p * x2 + 0.008333333333329196;
1953dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        p = p * x2 + -0.16666666666666666;
1954dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //p *= x2;
1955dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //p *= x;
1956dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        p = p * x2 * x;
1957dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1958dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return p;
1959dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1960dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1961dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
1962dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Computes cos(x) - 1, where |x| < 1/16.
1963dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Use a Remez polynomial approximation.
1964dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param x a number smaller than 1/16
1965dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return cos(x) - 1
1966dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1967dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double polyCosine(double x) {
1968dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double x2 = x*x;
1969dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1970dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double p = 2.479773539153719E-5;
1971dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        p = p * x2 + -0.0013888888689039883;
1972dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        p = p * x2 + 0.041666666666621166;
1973dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        p = p * x2 + -0.49999999999999994;
1974dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        p *= x2;
1975dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1976dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return p;
1977dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
1978dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1979dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
1980dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Compute sine over the first quadrant (0 < x < pi/2).
1981dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Use combination of table lookup and rational polynomial expansion.
1982dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param xa number from which sine is requested
1983dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param xb extra bits for x (may be 0.0)
1984dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return sin(xa + xb)
1985dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
1986dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double sinQ(double xa, double xb) {
1987dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int idx = (int) ((xa * 8.0) + 0.5);
1988dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double epsilon = xa - EIGHTHS[idx]; //idx*0.125;
1989dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1990dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Table lookups
1991dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double sintA = SINE_TABLE_A[idx];
1992dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double sintB = SINE_TABLE_B[idx];
1993dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double costA = COSINE_TABLE_A[idx];
1994dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double costB = COSINE_TABLE_B[idx];
1995dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
1996dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Polynomial eval of sin(epsilon), cos(epsilon)
1997dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double sinEpsA = epsilon;
1998dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double sinEpsB = polySine(epsilon);
1999dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double cosEpsA = 1.0;
2000dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double cosEpsB = polyCosine(epsilon);
2001dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2002dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Split epsilon   xa + xb = x
2003dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double temp = sinEpsA * HEX_40000000;
2004dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double temp2 = (sinEpsA + temp) - temp;
2005dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        sinEpsB +=  sinEpsA - temp2;
2006dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        sinEpsA = temp2;
2007dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2008dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute sin(x) by angle addition formula */
2009dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double result;
2010dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2011dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute the following sum:
2012dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         *
2013dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB +
2014dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         *          sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB;
2015dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         *
2016dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * Ranges of elements
2017dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         *
2018dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * xxxtA   0            PI/2
2019dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * xxxtB   -1.5e-9      1.5e-9
2020dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * sinEpsA -0.0625      0.0625
2021dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * sinEpsB -6e-11       6e-11
2022dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * cosEpsA  1.0
2023dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * cosEpsB  0           -0.0625
2024dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         *
2025dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
2026dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2027dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB +
2028dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //          sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB;
2029dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2030dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //result = sintA + sintA*cosEpsB + sintB + sintB * cosEpsB;
2031dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //result += costA*sinEpsA + costA*sinEpsB + costB*sinEpsA + costB * sinEpsB;
2032dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double a = 0;
2033dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double b = 0;
2034dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2035dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double t = sintA;
2036dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double c = a + t;
2037dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double d = -(c - a - t);
2038dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = c;
2039dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + d;
2040dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2041dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        t = costA * sinEpsA;
2042dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = a + t;
2043dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = -(c - a - t);
2044dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = c;
2045dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + d;
2046dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2047dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + sintA * cosEpsB + costA * sinEpsB;
2048dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /*
2049dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    t = sintA*cosEpsB;
2050dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    c = a + t;
2051dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    d = -(c - a - t);
2052dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    a = c;
2053dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    b = b + d;
2054dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2055dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    t = costA*sinEpsB;
2056dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    c = a + t;
2057dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    d = -(c - a - t);
2058dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    a = c;
2059dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    b = b + d;
2060dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
2061dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2062dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + sintB + costB * sinEpsA + sintB * cosEpsB + costB * sinEpsB;
2063dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /*
2064dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    t = sintB;
2065dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    c = a + t;
2066dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    d = -(c - a - t);
2067dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    a = c;
2068dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    b = b + d;
2069dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2070dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    t = costB*sinEpsA;
2071dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    c = a + t;
2072dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    d = -(c - a - t);
2073dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    a = c;
2074dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    b = b + d;
2075dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2076dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    t = sintB*cosEpsB;
2077dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    c = a + t;
2078dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    d = -(c - a - t);
2079dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    a = c;
2080dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    b = b + d;
2081dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2082dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    t = costB*sinEpsB;
2083dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    c = a + t;
2084dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    d = -(c - a - t);
2085dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    a = c;
2086dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    b = b + d;
2087dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
2088dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2089dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xb != 0.0) {
2090dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            t = ((costA + costB) * (cosEpsA + cosEpsB) -
2091dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                 (sintA + sintB) * (sinEpsA + sinEpsB)) * xb;  // approximate cosine*xb
2092dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            c = a + t;
2093dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            d = -(c - a - t);
2094dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            a = c;
2095dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            b = b + d;
2096dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2097dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2098dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result = a + b;
2099dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return result;
2101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
2102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
2104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Compute cosine in the first quadrant by subtracting input from PI/2 and
2105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * then calling sinQ.  This is more accurate as the input approaches PI/2.
2106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param xa number from which cosine is requested
2107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param xb extra bits for x (may be 0.0)
2108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return cos(xa + xb)
2109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
2110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double cosQ(double xa, double xb) {
2111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double pi2a = 1.5707963267948966;
2112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double pi2b = 6.123233995736766E-17;
2113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double a = pi2a - xa;
2115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double b = -(a - pi2a + xa);
2116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b += pi2b - xb;
2117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return sinQ(a, b);
2119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
2120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
2122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Compute tangent (or cotangent) over the first quadrant.   0 < x < pi/2
2123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Use combination of table lookup and rational polynomial expansion.
2124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param xa number from which sine is requested
2125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param xb extra bits for x (may be 0.0)
2126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param cotanFlag if true, compute the cotangent instead of the tangent
2127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return tan(xa+xb) (or cotangent, depending on cotanFlag)
2128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
2129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double tanQ(double xa, double xb, boolean cotanFlag) {
2130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int idx = (int) ((xa * 8.0) + 0.5);
2132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double epsilon = xa - EIGHTHS[idx]; //idx*0.125;
2133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Table lookups
2135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double sintA = SINE_TABLE_A[idx];
2136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double sintB = SINE_TABLE_B[idx];
2137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double costA = COSINE_TABLE_A[idx];
2138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double costB = COSINE_TABLE_B[idx];
2139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Polynomial eval of sin(epsilon), cos(epsilon)
2141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double sinEpsA = epsilon;
2142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double sinEpsB = polySine(epsilon);
2143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double cosEpsA = 1.0;
2144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double cosEpsB = polyCosine(epsilon);
2145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Split epsilon   xa + xb = x
2147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double temp = sinEpsA * HEX_40000000;
2148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double temp2 = (sinEpsA + temp) - temp;
2149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        sinEpsB +=  sinEpsA - temp2;
2150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        sinEpsA = temp2;
2151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute sin(x) by angle addition formula */
2153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute the following sum:
2155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         *
2156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB +
2157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         *          sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB;
2158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         *
2159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * Ranges of elements
2160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         *
2161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * xxxtA   0            PI/2
2162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * xxxtB   -1.5e-9      1.5e-9
2163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * sinEpsA -0.0625      0.0625
2164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * sinEpsB -6e-11       6e-11
2165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * cosEpsA  1.0
2166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * cosEpsB  0           -0.0625
2167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         *
2168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
2169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB +
2171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //          sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB;
2172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //result = sintA + sintA*cosEpsB + sintB + sintB * cosEpsB;
2174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //result += costA*sinEpsA + costA*sinEpsB + costB*sinEpsA + costB * sinEpsB;
2175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double a = 0;
2176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double b = 0;
2177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Compute sine
2179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double t = sintA;
2180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double c = a + t;
2181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double d = -(c - a - t);
2182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = c;
2183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + d;
2184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        t = costA*sinEpsA;
2186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = a + t;
2187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = -(c - a - t);
2188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = c;
2189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + d;
2190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + sintA*cosEpsB + costA*sinEpsB;
2192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB;
2193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double sina = a + b;
2195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double sinb = -(sina - a - b);
2196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Compute cosine
2198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = b = c = d = 0.0;
2200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        t = costA*cosEpsA;
2202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = a + t;
2203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = -(c - a - t);
2204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = c;
2205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + d;
2206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        t = -sintA*sinEpsA;
2208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = a + t;
2209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = -(c - a - t);
2210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = c;
2211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + d;
2212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b + costB*cosEpsA + costA*cosEpsB + costB*cosEpsB;
2214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = b - (sintB*sinEpsA + sintA*sinEpsB + sintB*sinEpsB);
2215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double cosa = a + b;
2217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double cosb = -(cosa - a - b);
2218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (cotanFlag) {
2220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double tmp;
2221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            tmp = cosa; cosa = sina; sina = tmp;
2222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            tmp = cosb; cosb = sinb; sinb = tmp;
2223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* estimate and correct, compute 1.0/(cosa+cosb) */
2227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /*
2228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    double est = (sina+sinb)/(cosa+cosb);
2229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    double err = (sina - cosa*est) + (sinb - cosb*est);
2230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    est += err/(cosa+cosb);
2231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    err = (sina - cosa*est) + (sinb - cosb*est);
2232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
2233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // f(x) = 1/x,   f'(x) = -1/x^2
2235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double est = sina/cosa;
2237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Split the estimate to get more accurate read on division rounding */
2239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = est * HEX_40000000;
2240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double esta = (est + temp) - temp;
2241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double estb =  est - esta;
2242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = cosa * HEX_40000000;
2244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double cosaa = (cosa + temp) - temp;
2245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double cosab =  cosa - cosaa;
2246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //double err = (sina - est*cosa)/cosa;  // Correction for division rounding
2248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double err = (sina - esta*cosaa - esta*cosab - estb*cosaa - estb*cosab)/cosa;  // Correction for division rounding
2249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        err += sinb/cosa;                     // Change in est due to sinb
2250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        err += -sina * cosb / cosa / cosa;    // Change in est due to cosb
2251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xb != 0.0) {
2253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // tan' = 1 + tan^2      cot' = -(1 + cot^2)
2254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Approximate impact of xb
2255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double xbadj = xb + est*est*xb;
2256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (cotanFlag) {
2257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                xbadj = -xbadj;
2258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            err += xbadj;
2261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return est+err;
2264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
2265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Reduce the input argument using the Payne and Hanek method.
2267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  This is good for all inputs 0.0 < x < inf
2268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Output is remainder after dividing by PI/2
2269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  The result array should contain 3 numbers.
2270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  result[0] is the integer portion, so mod 4 this gives the quadrant.
2271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  result[1] is the upper bits of the remainder
2272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  result[2] is the lower bits of the remainder
2273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
2274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number to reduce
2275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param result placeholder where to put the result
2276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
2277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static void reducePayneHanek(double x, double result[])
2278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    {
2279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Convert input double to bits */
2280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long inbits = Double.doubleToLongBits(x);
2281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int exponent = (int) ((inbits >> 52) & 0x7ff) - 1023;
2282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Convert to fixed point representation */
2284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        inbits &= 0x000fffffffffffffL;
2285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        inbits |= 0x0010000000000000L;
2286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Normalize input to be between 0.5 and 1.0 */
2288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        exponent++;
2289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        inbits <<= 11;
2290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Based on the exponent, get a shifted copy of recip2pi */
2292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long shpi0;
2293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long shpiA;
2294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long shpiB;
2295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int idx = exponent >> 6;
2296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int shift = exponent - (idx << 6);
2297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (shift != 0) {
2299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            shpi0 = (idx == 0) ? 0 : (RECIP_2PI[idx-1] << shift);
2300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            shpi0 |= RECIP_2PI[idx] >>> (64-shift);
2301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            shpiA = (RECIP_2PI[idx] << shift) | (RECIP_2PI[idx+1] >>> (64-shift));
2302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            shpiB = (RECIP_2PI[idx+1] << shift) | (RECIP_2PI[idx+2] >>> (64-shift));
2303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
2304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            shpi0 = (idx == 0) ? 0 : RECIP_2PI[idx-1];
2305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            shpiA = RECIP_2PI[idx];
2306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            shpiB = RECIP_2PI[idx+1];
2307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Multiply input by shpiA */
2310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long a = inbits >>> 32;
2311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long b = inbits & 0xffffffffL;
2312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long c = shpiA >>> 32;
2314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long d = shpiA & 0xffffffffL;
2315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long ac = a * c;
2317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long bd = b * d;
2318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long bc = b * c;
2319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long ad = a * d;
2320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long prodB = bd + (ad << 32);
2322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long prodA = ac + (ad >>> 32);
2323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        boolean bita = (bd & 0x8000000000000000L) != 0;
2325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        boolean bitb = (ad & 0x80000000L ) != 0;
2326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        boolean bitsum = (prodB & 0x8000000000000000L) != 0;
2327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Carry */
2329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ( (bita && bitb) ||
2330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ((bita || bitb) && !bitsum) ) {
2331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            prodA++;
2332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bita = (prodB & 0x8000000000000000L) != 0;
2335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitb = (bc & 0x80000000L ) != 0;
2336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        prodB = prodB + (bc << 32);
2338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        prodA = prodA + (bc >>> 32);
2339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitsum = (prodB & 0x8000000000000000L) != 0;
2341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Carry */
2343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ( (bita && bitb) ||
2344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ((bita || bitb) && !bitsum) ) {
2345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            prodA++;
2346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Multiply input by shpiB */
2349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = shpiB >>> 32;
2350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = shpiB & 0xffffffffL;
2351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ac = a * c;
2352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bc = b * c;
2353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ad = a * d;
2354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Collect terms */
2356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ac = ac + ((bc + ad) >>> 32);
2357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bita = (prodB & 0x8000000000000000L) != 0;
2359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitb = (ac & 0x8000000000000000L ) != 0;
2360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        prodB += ac;
2361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitsum = (prodB & 0x8000000000000000L) != 0;
2362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Carry */
2363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ( (bita && bitb) ||
2364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ((bita || bitb) && !bitsum) ) {
2365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            prodA++;
2366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Multiply by shpi0 */
2369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = shpi0 >>> 32;
2370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = shpi0 & 0xffffffffL;
2371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bd = b * d;
2373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bc = b * c;
2374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ad = a * d;
2375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        prodA += bd + ((bc + ad) << 32);
2377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /*
2379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * prodA, prodB now contain the remainder as a fraction of PI.  We want this as a fraction of
2380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * PI/2, so use the following steps:
2381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * 1.) multiply by 4.
2382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * 2.) do a fixed point muliply by PI/4.
2383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * 3.) Convert to floating point.
2384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         * 4.) Multiply by 2
2385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
2386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* This identifies the quadrant */
2388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int intPart = (int)(prodA >>> 62);
2389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Multiply by 4 */
2391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        prodA <<= 2;
2392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        prodA |= prodB >>> 62;
2393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        prodB <<= 2;
2394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Multiply by PI/4 */
2396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = prodA >>> 32;
2397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = prodA & 0xffffffffL;
2398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = PI_O_4_BITS[0] >>> 32;
2400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = PI_O_4_BITS[0] & 0xffffffffL;
2401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ac = a * c;
2403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bd = b * d;
2404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bc = b * c;
2405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ad = a * d;
2406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long prod2B = bd + (ad << 32);
2408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long prod2A = ac + (ad >>> 32);
2409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bita = (bd & 0x8000000000000000L) != 0;
2411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitb = (ad & 0x80000000L ) != 0;
2412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitsum = (prod2B & 0x8000000000000000L) != 0;
2413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Carry */
2415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ( (bita && bitb) ||
2416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ((bita || bitb) && !bitsum) ) {
2417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            prod2A++;
2418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bita = (prod2B & 0x8000000000000000L) != 0;
2421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitb = (bc & 0x80000000L ) != 0;
2422dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2423dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        prod2B = prod2B + (bc << 32);
2424dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        prod2A = prod2A + (bc >>> 32);
2425dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2426dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitsum = (prod2B & 0x8000000000000000L) != 0;
2427dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2428dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Carry */
2429dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ( (bita && bitb) ||
2430dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ((bita || bitb) && !bitsum) ) {
2431dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            prod2A++;
2432dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2433dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2434dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Multiply input by pio4bits[1] */
2435dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = PI_O_4_BITS[1] >>> 32;
2436dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = PI_O_4_BITS[1] & 0xffffffffL;
2437dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ac = a * c;
2438dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bc = b * c;
2439dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ad = a * d;
2440dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2441dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Collect terms */
2442dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ac = ac + ((bc + ad) >>> 32);
2443dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2444dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bita = (prod2B & 0x8000000000000000L) != 0;
2445dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitb = (ac & 0x8000000000000000L ) != 0;
2446dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        prod2B += ac;
2447dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitsum = (prod2B & 0x8000000000000000L) != 0;
2448dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Carry */
2449dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ( (bita && bitb) ||
2450dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ((bita || bitb) && !bitsum) ) {
2451dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            prod2A++;
2452dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2453dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2454dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Multiply inputB by pio4bits[0] */
2455dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        a = prodB >>> 32;
2456dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        b = prodB & 0xffffffffL;
2457dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        c = PI_O_4_BITS[0] >>> 32;
2458dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        d = PI_O_4_BITS[0] & 0xffffffffL;
2459dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ac = a * c;
2460dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bc = b * c;
2461dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ad = a * d;
2462dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2463dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Collect terms */
2464dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ac = ac + ((bc + ad) >>> 32);
2465dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2466dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bita = (prod2B & 0x8000000000000000L) != 0;
2467dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitb = (ac & 0x8000000000000000L ) != 0;
2468dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        prod2B += ac;
2469dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        bitsum = (prod2B & 0x8000000000000000L) != 0;
2470dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Carry */
2471dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ( (bita && bitb) ||
2472dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ((bita || bitb) && !bitsum) ) {
2473dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            prod2A++;
2474dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2475dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2476dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Convert to double */
2477dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double tmpA = (prod2A >>> 12) / TWO_POWER_52;  // High order 52 bits
2478dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double tmpB = (((prod2A & 0xfffL) << 40) + (prod2B >>> 24)) / TWO_POWER_52 / TWO_POWER_52; // Low bits
2479dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2480dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double sumA = tmpA + tmpB;
2481dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double sumB = -(sumA - tmpA - tmpB);
2482dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2483dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Multiply by PI/2 and return */
2484dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[0] = intPart;
2485dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[1] = sumA * 2.0;
2486dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result[2] = sumB * 2.0;
2487dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
2488dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2489dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
2490dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Sine function.
2491dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param x a number
2492dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return sin(x)
2493dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
2494dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double sin(double x) {
2495dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        boolean negative = false;
2496dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int quadrant = 0;
2497dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xa;
2498dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xb = 0.0;
2499dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2500dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Take absolute value of the input */
2501dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        xa = x;
2502dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x < 0) {
2503dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            negative = true;
2504dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xa = -xa;
2505dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2506dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2507dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Check for zero and negative zero */
2508dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa == 0.0) {
2509dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            long bits = Double.doubleToLongBits(x);
2510dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (bits < 0) {
2511dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -0.0;
2512dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2513dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return 0.0;
2514dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2515dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2516dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa != xa || xa == Double.POSITIVE_INFINITY) {
2517dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.NaN;
2518dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2519dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2520dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Perform any argument reduction */
2521dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa > 3294198.0) {
2522dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // PI * (2**20)
2523dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Argument too big for CodyWaite reduction.  Must use
2524dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // PayneHanek.
2525dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double reduceResults[] = new double[3];
2526dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            reducePayneHanek(xa, reduceResults);
2527dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            quadrant = ((int) reduceResults[0]) & 3;
2528dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xa = reduceResults[1];
2529dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xb = reduceResults[2];
2530dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (xa > 1.5707963267948966) {
2531dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* Inline the Cody/Waite reduction for performance */
2532dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2533dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Estimate k
2534dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            //k = (int)(xa / 1.5707963267948966);
2535dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int k = (int)(xa * 0.6366197723675814);
2536dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2537dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Compute remainder
2538dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double remA;
2539dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double remB;
2540dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            while (true) {
2541dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double a = -k * 1.570796251296997;
2542dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remA = xa + a;
2543dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remB = -(remA - xa - a);
2544dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2545dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                a = -k * 7.549789948768648E-8;
2546dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double b = remA;
2547dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remA = a + b;
2548dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remB += -(remA - b - a);
2549dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2550dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                a = -k * 6.123233995736766E-17;
2551dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                b = remA;
2552dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remA = a + b;
2553dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remB += -(remA - b - a);
2554dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2555dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (remA > 0.0)
2556dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    break;
2557dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2558dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // Remainder is negative, so decrement k and try again.
2559dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // This should only happen if the input is very close
2560dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // to an even multiple of pi/2
2561dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                k--;
2562dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2563dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            quadrant = k & 3;
2564dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xa = remA;
2565dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xb = remB;
2566dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2567dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2568dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (negative) {
2569dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            quadrant ^= 2;  // Flip bit 1
2570dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2571dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2572dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        switch (quadrant) {
2573dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            case 0:
2574dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return sinQ(xa, xb);
2575dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            case 1:
2576dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return cosQ(xa, xb);
2577dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            case 2:
2578dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -sinQ(xa, xb);
2579dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            case 3:
2580dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -cosQ(xa, xb);
2581dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            default:
2582dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.NaN;
2583dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2584dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
2585dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2586dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
2587dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Cosine function
2588dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param x a number
2589dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return cos(x)
2590dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
2591dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double cos(double x) {
2592dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int quadrant = 0;
2593dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2594dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Take absolute value of the input */
2595dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xa = x;
2596dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x < 0) {
2597dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xa = -xa;
2598dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2599dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2600dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa != xa || xa == Double.POSITIVE_INFINITY) {
2601dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.NaN;
2602dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2603dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2604dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Perform any argument reduction */
2605dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xb = 0;
2606dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa > 3294198.0) {
2607dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // PI * (2**20)
2608dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Argument too big for CodyWaite reduction.  Must use
2609dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // PayneHanek.
2610dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double reduceResults[] = new double[3];
2611dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            reducePayneHanek(xa, reduceResults);
2612dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            quadrant = ((int) reduceResults[0]) & 3;
2613dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xa = reduceResults[1];
2614dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xb = reduceResults[2];
2615dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (xa > 1.5707963267948966) {
2616dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* Inline the Cody/Waite reduction for performance */
2617dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2618dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Estimate k
2619dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            //k = (int)(xa / 1.5707963267948966);
2620dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int k = (int)(xa * 0.6366197723675814);
2621dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2622dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Compute remainder
2623dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double remA;
2624dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double remB;
2625dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            while (true) {
2626dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double a = -k * 1.570796251296997;
2627dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remA = xa + a;
2628dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remB = -(remA - xa - a);
2629dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2630dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                a = -k * 7.549789948768648E-8;
2631dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double b = remA;
2632dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remA = a + b;
2633dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remB += -(remA - b - a);
2634dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2635dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                a = -k * 6.123233995736766E-17;
2636dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                b = remA;
2637dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remA = a + b;
2638dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remB += -(remA - b - a);
2639dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2640dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (remA > 0.0)
2641dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    break;
2642dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2643dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // Remainder is negative, so decrement k and try again.
2644dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // This should only happen if the input is very close
2645dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // to an even multiple of pi/2
2646dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                k--;
2647dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2648dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            quadrant = k & 3;
2649dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xa = remA;
2650dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xb = remB;
2651dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2652dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2653dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //if (negative)
2654dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //  quadrant = (quadrant + 2) % 4;
2655dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2656dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        switch (quadrant) {
2657dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            case 0:
2658dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return cosQ(xa, xb);
2659dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            case 1:
2660dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -sinQ(xa, xb);
2661dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            case 2:
2662dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -cosQ(xa, xb);
2663dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            case 3:
2664dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return sinQ(xa, xb);
2665dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            default:
2666dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.NaN;
2667dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2668dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
2669dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2670dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
2671dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *   Tangent function
2672dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param x a number
2673dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return tan(x)
2674dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
2675dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double tan(double x) {
2676dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        boolean negative = false;
2677dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int quadrant = 0;
2678dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2679dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Take absolute value of the input */
2680dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xa = x;
2681dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x < 0) {
2682dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            negative = true;
2683dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xa = -xa;
2684dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2685dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2686dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Check for zero and negative zero */
2687dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa == 0.0) {
2688dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            long bits = Double.doubleToLongBits(x);
2689dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (bits < 0) {
2690dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -0.0;
2691dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2692dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return 0.0;
2693dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2694dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2695dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa != xa || xa == Double.POSITIVE_INFINITY) {
2696dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.NaN;
2697dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2698dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2699dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Perform any argument reduction */
2700dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xb = 0;
2701dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa > 3294198.0) {
2702dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // PI * (2**20)
2703dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Argument too big for CodyWaite reduction.  Must use
2704dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // PayneHanek.
2705dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double reduceResults[] = new double[3];
2706dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            reducePayneHanek(xa, reduceResults);
2707dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            quadrant = ((int) reduceResults[0]) & 3;
2708dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xa = reduceResults[1];
2709dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xb = reduceResults[2];
2710dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (xa > 1.5707963267948966) {
2711dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* Inline the Cody/Waite reduction for performance */
2712dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2713dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Estimate k
2714dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            //k = (int)(xa / 1.5707963267948966);
2715dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int k = (int)(xa * 0.6366197723675814);
2716dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2717dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Compute remainder
2718dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double remA;
2719dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double remB;
2720dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            while (true) {
2721dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double a = -k * 1.570796251296997;
2722dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remA = xa + a;
2723dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remB = -(remA - xa - a);
2724dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2725dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                a = -k * 7.549789948768648E-8;
2726dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                double b = remA;
2727dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remA = a + b;
2728dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remB += -(remA - b - a);
2729dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2730dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                a = -k * 6.123233995736766E-17;
2731dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                b = remA;
2732dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remA = a + b;
2733dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                remB += -(remA - b - a);
2734dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2735dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (remA > 0.0)
2736dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    break;
2737dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2738dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // Remainder is negative, so decrement k and try again.
2739dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // This should only happen if the input is very close
2740dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // to an even multiple of pi/2
2741dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                k--;
2742dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2743dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            quadrant = k & 3;
2744dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xa = remA;
2745dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xb = remB;
2746dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2747dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2748dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa > 1.5) {
2749dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Accurracy suffers between 1.5 and PI/2
2750dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double pi2a = 1.5707963267948966;
2751dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double pi2b = 6.123233995736766E-17;
2752dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2753dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double a = pi2a - xa;
2754dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double b = -(a - pi2a + xa);
2755dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            b += pi2b - xb;
2756dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2757dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xa = a + b;
2758dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xb = -(xa - a - b);
2759dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            quadrant ^= 1;
2760dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            negative ^= true;
2761dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2762dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2763dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double result;
2764dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((quadrant & 1) == 0) {
2765dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result = tanQ(xa, xb, false);
2766dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
2767dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result = -tanQ(xa, xb, true);
2768dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2769dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2770dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (negative) {
2771dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result = -result;
2772dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2773dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2774dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return result;
2775dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
2776dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2777dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
2778dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Arctangent function
2779dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param x a number
2780dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return atan(x)
2781dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
2782dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double atan(double x) {
2783dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return atan(x, 0.0, false);
2784dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
2785dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2786dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Internal helper function to compute arctangent.
2787dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param xa number from which arctangent is requested
2788dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param xb extra bits for x (may be 0.0)
2789dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param leftPlane if true, result angle must be put in the left half plane
2790dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return atan(xa + xb) (or angle shifted by {@code PI} if leftPlane is true)
2791dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
2792dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static double atan(double xa, double xb, boolean leftPlane) {
2793dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        boolean negate = false;
2794dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int idx;
2795dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2796dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa == 0.0) { // Matches +/- 0.0; return correct sign
2797dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return leftPlane ? copySign(Math.PI, xa) : xa;
2798dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2799dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2800dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa < 0) {
2801dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // negative
2802dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xa = -xa;
2803dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            xb = -xb;
2804dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            negate = true;
2805dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2806dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2807dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa > 1.633123935319537E16) { // Very large input
2808dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (negate ^ leftPlane) ? (-Math.PI/2.0) : (Math.PI/2.0);
2809dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2810dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2811dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Estimate the closest tabulated arctan value, compute eps = xa-tangentTable */
2812dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (xa < 1.0) {
2813dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            idx = (int) (((-1.7168146928204136 * xa * xa + 8.0) * xa) + 0.5);
2814dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
2815dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double temp = 1.0/xa;
2816dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            idx = (int) (-((-1.7168146928204136 * temp * temp + 8.0) * temp) + 13.07);
2817dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2818dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double epsA = xa - TANGENT_TABLE_A[idx];
2819dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double epsB = -(epsA - xa + TANGENT_TABLE_A[idx]);
2820dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        epsB += xb - TANGENT_TABLE_B[idx];
2821dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2822dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double temp = epsA + epsB;
2823dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        epsB = -(temp - epsA - epsB);
2824dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        epsA = temp;
2825dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2826dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Compute eps = eps / (1.0 + xa*tangent) */
2827dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = xa * HEX_40000000;
2828dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double ya = xa + temp - temp;
2829dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double yb = xb + xa - ya;
2830dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        xa = ya;
2831dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        xb += yb;
2832dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2833dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //if (idx > 8 || idx == 0)
2834dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (idx == 0) {
2835dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* If the slope of the arctan is gentle enough (< 0.45), this approximation will suffice */
2836dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            //double denom = 1.0 / (1.0 + xa*tangentTableA[idx] + xb*tangentTableA[idx] + xa*tangentTableB[idx] + xb*tangentTableB[idx]);
2837dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double denom = 1.0 / (1.0 + (xa + xb) * (TANGENT_TABLE_A[idx] + TANGENT_TABLE_B[idx]));
2838dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            //double denom = 1.0 / (1.0 + xa*tangentTableA[idx]);
2839dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ya = epsA * denom;
2840dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            yb = epsB * denom;
2841dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
2842dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double temp2 = xa * TANGENT_TABLE_A[idx];
2843dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double za = 1.0 + temp2;
2844dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double zb = -(za - 1.0 - temp2);
2845dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            temp2 = xb * TANGENT_TABLE_A[idx] + xa * TANGENT_TABLE_B[idx];
2846dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            temp = za + temp2;
2847dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            zb += -(temp - za - temp2);
2848dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            za = temp;
2849dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2850dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            zb += xb * TANGENT_TABLE_B[idx];
2851dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ya = epsA / za;
2852dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2853dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            temp = ya * HEX_40000000;
2854dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double yaa = (ya + temp) - temp;
2855dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double yab = ya - yaa;
2856dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2857dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            temp = za * HEX_40000000;
2858dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double zaa = (za + temp) - temp;
2859dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double zab = za - zaa;
2860dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2861dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            /* Correct for rounding in division */
2862dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            yb = (epsA - yaa * zaa - yaa * zab - yab * zaa - yab * zab) / za;
2863dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2864dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            yb += -epsA * zb / za / za;
2865dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            yb += epsB / za;
2866dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2867dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2868dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2869dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        epsA = ya;
2870dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        epsB = yb;
2871dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2872dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Evaluate polynomial */
2873dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double epsA2 = epsA*epsA;
2874dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2875dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /*
2876dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    yb = -0.09001346640161823;
2877dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    yb = yb * epsA2 + 0.11110718400605211;
2878dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    yb = yb * epsA2 + -0.1428571349122913;
2879dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    yb = yb * epsA2 + 0.19999999999273194;
2880dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    yb = yb * epsA2 + -0.33333333333333093;
2881dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    yb = yb * epsA2 * epsA;
2882dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond         */
2883dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2884dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb = 0.07490822288864472;
2885dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb = yb * epsA2 + -0.09088450866185192;
2886dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb = yb * epsA2 + 0.11111095942313305;
2887dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb = yb * epsA2 + -0.1428571423679182;
2888dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb = yb * epsA2 + 0.19999999999923582;
2889dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb = yb * epsA2 + -0.33333333333333287;
2890dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb = yb * epsA2 * epsA;
2891dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2892dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2893dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ya = epsA;
2894dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2895dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = ya + yb;
2896dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb = -(temp - ya - yb);
2897dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ya = temp;
2898dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2899dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* Add in effect of epsB.   atan'(x) = 1/(1+x^2) */
2900dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        yb += epsB / (1.0 + epsA * epsA);
2901dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2902dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double result;
2903dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double resultb;
2904dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2905dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        //result = yb + eighths[idx] + ya;
2906dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double za = EIGHTHS[idx] + ya;
2907dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double zb = -(za - EIGHTHS[idx] - ya);
2908dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        temp = za + yb;
2909dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        zb += -(temp - za - yb);
2910dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        za = temp;
2911dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2912dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result = za + zb;
2913dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        resultb = -(result - za - zb);
2914dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2915dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (leftPlane) {
2916dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // Result is in the left plane
2917dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double pia = 1.5707963267948966*2.0;
2918dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final double pib = 6.123233995736766E-17*2.0;
2919dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2920dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            za = pia - result;
2921dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            zb = -(za - pia + result);
2922dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            zb += pib - resultb;
2923dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2924dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result = za + zb;
2925dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            resultb = -(result - za - zb);
2926dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2927dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2928dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2929dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (negate ^ leftPlane) {
2930dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result = -result;
2931dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2932dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2933dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return result;
2934dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
2935dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2936dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
2937dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Two arguments arctangent function
2938dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param y ordinate
2939dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x abscissa
2940dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return phase angle of point (x,y) between {@code -PI} and {@code PI}
2941dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
2942dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double atan2(double y, double x) {
2943dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x !=x || y != y) {
2944dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.NaN;
2945dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2946dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2947dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (y == 0.0) {
2948dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double result = x*y;
2949dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double invx = 1.0/x;
2950dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double invy = 1.0/y;
2951dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2952dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (invx == 0.0) { // X is infinite
2953dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (x > 0) {
2954dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return y; // return +/- 0.0
2955dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                } else {
2956dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return copySign(Math.PI, y);
2957dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
2958dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2959dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2960dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x < 0.0 || invx < 0.0) {
2961dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (y < 0.0 || invy < 0.0) {
2962dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return -Math.PI;
2963dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                } else {
2964dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return Math.PI;
2965dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
2966dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
2967dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return result;
2968dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2969dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2970dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2971dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // y cannot now be zero
2972dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2973dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (y == Double.POSITIVE_INFINITY) {
2974dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x == Double.POSITIVE_INFINITY) {
2975dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Math.PI/4.0;
2976dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2977dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2978dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x == Double.NEGATIVE_INFINITY) {
2979dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Math.PI*3.0/4.0;
2980dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2981dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2982dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Math.PI/2.0;
2983dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2984dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2985dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (y == Double.NEGATIVE_INFINITY) {
2986dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x == Double.POSITIVE_INFINITY) {
2987dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -Math.PI/4.0;
2988dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2989dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2990dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (x == Double.NEGATIVE_INFINITY) {
2991dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -Math.PI*3.0/4.0;
2992dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
2993dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2994dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return -Math.PI/2.0;
2995dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
2996dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
2997dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x == Double.POSITIVE_INFINITY) {
2998dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y > 0.0 || 1/y > 0.0) {
2999dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return 0.0;
3000dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3001dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3002dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y < 0.0 || 1/y < 0.0) {
3003dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -0.0;
3004dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3005dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3006dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3007dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x == Double.NEGATIVE_INFINITY)
3008dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        {
3009dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y > 0.0 || 1/y > 0.0) {
3010dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Math.PI;
3011dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3012dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3013dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y < 0.0 || 1/y < 0.0) {
3014dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -Math.PI;
3015dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3016dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3017dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3018dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Neither y nor x can be infinite or NAN here
3019dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3020dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x == 0) {
3021dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y > 0.0 || 1/y > 0.0) {
3022dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Math.PI/2.0;
3023dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3024dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3025dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y < 0.0 || 1/y < 0.0) {
3026dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -Math.PI/2.0;
3027dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3028dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3029dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3030dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Compute ratio r = y/x
3031dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double r = y/x;
3032dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Double.isInfinite(r)) { // bypass calculations that can create NaN
3033dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return atan(r, 0, x < 0);
3034dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3035dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3036dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double ra = doubleHighPart(r);
3037dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double rb = r - ra;
3038dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3039dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Split x
3040dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double xa = doubleHighPart(x);
3041dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double xb = x - xa;
3042dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3043dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        rb += (y - ra * xa - ra * xb - rb * xa - rb * xb) / x;
3044dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3045dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double temp = ra + rb;
3046dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        rb = -(temp - ra - rb);
3047dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        ra = temp;
3048dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3049dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (ra == 0) { // Fix up the sign so atan works correctly
3050dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ra = copySign(0.0, y);
3051dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3052dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3053dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // Call atan
3054dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double result = atan(ra, rb, x < 0);
3055dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3056dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return result;
3057dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3058dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3059dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the arc sine of a number.
3060dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number on which evaluation is done
3061dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return arc sine of x
3062dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3063dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double asin(double x) {
3064dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x != x) {
3065dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return Double.NaN;
3066dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3067dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3068dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x > 1.0 || x < -1.0) {
3069dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return Double.NaN;
3070dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3071dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3072dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x == 1.0) {
3073dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return Math.PI/2.0;
3074dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3075dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3076dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x == -1.0) {
3077dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return -Math.PI/2.0;
3078dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3079dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3080dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x == 0.0) { // Matches +/- 0.0; return correct sign
3081dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return x;
3082dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3083dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3084dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Compute asin(x) = atan(x/sqrt(1-x*x)) */
3085dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3086dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Split x */
3087dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double temp = x * HEX_40000000;
3088dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      final double xa = x + temp - temp;
3089dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      final double xb = x - xa;
3090dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3091dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Square it */
3092dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double ya = xa*xa;
3093dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double yb = xa*xb*2.0 + xb*xb;
3094dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3095dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Subtract from 1 */
3096dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      ya = -ya;
3097dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      yb = -yb;
3098dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3099dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double za = 1.0 + ya;
3100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double zb = -(za - 1.0 - ya);
3101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      temp = za + yb;
3103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      zb += -(temp - za - yb);
3104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      za = temp;
3105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Square root */
3107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double y;
3108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      y = sqrt(za);
3109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      temp = y * HEX_40000000;
3110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      ya = y + temp - temp;
3111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      yb = y - ya;
3112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Extend precision of sqrt */
3114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      yb += (za - ya*ya - 2*ya*yb - yb*yb) / (2.0*y);
3115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Contribution of zb to sqrt */
3117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double dx = zb / (2.0*y);
3118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // Compute ratio r = x/y
3120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double r = x/y;
3121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      temp = r * HEX_40000000;
3122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double ra = r + temp - temp;
3123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double rb = r - ra;
3124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      rb += (x - ra*ya - ra*yb - rb*ya - rb*yb) / y;  // Correct for rounding in division
3126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      rb += -x * dx / y / y;  // Add in effect additional bits of sqrt.
3127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      temp = ra + rb;
3129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      rb = -(temp - ra - rb);
3130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      ra = temp;
3131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      return atan(ra, rb, false);
3133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the arc cosine of a number.
3136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number on which evaluation is done
3137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return arc cosine of x
3138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double acos(double x) {
3140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x != x) {
3141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return Double.NaN;
3142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x > 1.0 || x < -1.0) {
3145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return Double.NaN;
3146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x == -1.0) {
3149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return Math.PI;
3150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x == 1.0) {
3153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return 0.0;
3154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (x == 0) {
3157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return Math.PI/2.0;
3158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Compute acos(x) = atan(sqrt(1-x*x)/x) */
3161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Split x */
3163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double temp = x * HEX_40000000;
3164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      final double xa = x + temp - temp;
3165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      final double xb = x - xa;
3166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Square it */
3168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double ya = xa*xa;
3169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double yb = xa*xb*2.0 + xb*xb;
3170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Subtract from 1 */
3172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      ya = -ya;
3173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      yb = -yb;
3174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double za = 1.0 + ya;
3176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double zb = -(za - 1.0 - ya);
3177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      temp = za + yb;
3179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      zb += -(temp - za - yb);
3180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      za = temp;
3181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Square root */
3183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double y = sqrt(za);
3184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      temp = y * HEX_40000000;
3185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      ya = y + temp - temp;
3186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      yb = y - ya;
3187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Extend precision of sqrt */
3189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      yb += (za - ya*ya - 2*ya*yb - yb*yb) / (2.0*y);
3190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Contribution of zb to sqrt */
3192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      yb += zb / (2.0*y);
3193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      y = ya+yb;
3194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      yb = -(y - ya - yb);
3195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // Compute ratio r = y/x
3197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double r = y/x;
3198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // Did r overflow?
3200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (Double.isInfinite(r)) { // x is effectively zero
3201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return Math.PI/2; // so return the appropriate value
3202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double ra = doubleHighPart(r);
3205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double rb = r - ra;
3206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      rb += (y - ra*xa - ra*xb - rb*xa - rb*xb) / x;  // Correct for rounding in division
3208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      rb += yb / x;  // Add in effect additional bits of sqrt.
3209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      temp = ra + rb;
3211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      rb = -(temp - ra - rb);
3212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      ra = temp;
3213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      return atan(ra, rb, x<0);
3215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the cubic root of a number.
3218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number on which evaluation is done
3219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return cubic root of x
3220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double cbrt(double x) {
3222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Convert input double to bits */
3223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      long inbits = Double.doubleToLongBits(x);
3224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      int exponent = (int) ((inbits >> 52) & 0x7ff) - 1023;
3225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      boolean subnormal = false;
3226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (exponent == -1023) {
3228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          if (x == 0) {
3229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond              return x;
3230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          }
3231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          /* Subnormal, so normalize */
3233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          subnormal = true;
3234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          x *= 1.8014398509481984E16;  // 2^54
3235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          inbits = Double.doubleToLongBits(x);
3236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          exponent = (int) ((inbits >> 52) & 0x7ff) - 1023;
3237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (exponent == 1024) {
3240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          // Nan or infinity.  Don't care which.
3241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          return x;
3242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Divide the exponent by 3 */
3245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      int exp3 = exponent / 3;
3246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* p2 will be the nearest power of 2 to x with its exponent divided by 3 */
3248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double p2 = Double.longBitsToDouble((inbits & 0x8000000000000000L) |
3249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                                          (long)(((exp3 + 1023) & 0x7ff)) << 52);
3250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* This will be a number between 1 and 2 */
3252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      final double mant = Double.longBitsToDouble((inbits & 0x000fffffffffffffL) | 0x3ff0000000000000L);
3253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Estimate the cube root of mant by polynomial */
3255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double est = -0.010714690733195933;
3256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      est = est * mant + 0.0875862700108075;
3257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      est = est * mant + -0.3058015757857271;
3258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      est = est * mant + 0.7249995199969751;
3259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      est = est * mant + 0.5039018405998233;
3260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      est *= CBRTTWO[exponent % 3 + 2];
3262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // est should now be good to about 15 bits of precision.   Do 2 rounds of
3264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // Newton's method to get closer,  this should get us full double precision
3265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // Scale down x for the purpose of doing newtons method.  This avoids over/under flows.
3266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      final double xs = x / (p2*p2*p2);
3267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      est += (xs - est*est*est) / (3*est*est);
3268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      est += (xs - est*est*est) / (3*est*est);
3269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      // Do one round of Newton's method in extended precision to get the last bit right.
3271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double temp = est * HEX_40000000;
3272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double ya = est + temp - temp;
3273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double yb = est - ya;
3274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double za = ya * ya;
3276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double zb = ya * yb * 2.0 + yb * yb;
3277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      temp = za * HEX_40000000;
3278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double temp2 = za + temp - temp;
3279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      zb += za - temp2;
3280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      za = temp2;
3281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      zb = za * yb + ya * zb + zb * yb;
3283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      za = za * ya;
3284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double na = xs - za;
3286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      double nb = -(na - xs + za);
3287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      nb -= zb;
3288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      est += (na+nb)/(3*est*est);
3290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      /* Scale by a power of two, so this is exact. */
3292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      est *= p2;
3293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      if (subnormal) {
3295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond          est *= 3.814697265625E-6;  // 2^-18
3296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      }
3297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      return est;
3299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Convert degrees to radians, with error of less than 0.5 ULP
3303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param x angle in degrees
3304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return x converted into radians
3305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double toRadians(double x)
3307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    {
3308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Double.isInfinite(x) || x == 0.0) { // Matches +/- 0.0; return correct sign
3309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return x;
3310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // These are PI/180 split into high and low order bits
3313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double facta = 0.01745329052209854;
3314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double factb = 1.997844754509471E-9;
3315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xa = doubleHighPart(x);
3317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xb = x - xa;
3318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double result = xb * factb + xb * facta + xa * factb + xa * facta;
3320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (result == 0) {
3321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result = result * x; // ensure correct sign if calculation underflows
3322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return result;
3324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Convert radians to degrees, with error of less than 0.5 ULP
3328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @param x angle in radians
3329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  @return x converted into degrees
3330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double toDegrees(double x)
3332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    {
3333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Double.isInfinite(x) || x == 0.0) { // Matches +/- 0.0; return correct sign
3334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return x;
3335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // These are 180/PI split into high and low order bits
3338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double facta = 57.2957763671875;
3339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double factb = 3.145894820876798E-6;
3340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xa = doubleHighPart(x);
3342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double xb = x - xa;
3343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return xb * factb + xb * facta + xa * factb + xa * facta;
3345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Absolute value.
3349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which absolute value is requested
3350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return abs(x)
3351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static int abs(final int x) {
3353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (x < 0) ? -x : x;
3354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Absolute value.
3358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which absolute value is requested
3359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return abs(x)
3360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static long abs(final long x) {
3362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (x < 0l) ? -x : x;
3363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Absolute value.
3367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which absolute value is requested
3368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return abs(x)
3369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static float abs(final float x) {
3371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (x < 0.0f) ? -x : (x == 0.0f) ? 0.0f : x; // -0.0 => +0.0
3372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Absolute value.
3376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which absolute value is requested
3377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return abs(x)
3378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double abs(double x) {
3380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (x < 0.0) ? -x : (x == 0.0) ? 0.0 : x; // -0.0 => +0.0
3381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Compute least significant bit (Unit in Last Position) for a number.
3385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which ulp is requested
3386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return ulp(x)
3387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double ulp(double x) {
3389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Double.isInfinite(x)) {
3390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.POSITIVE_INFINITY;
3391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return abs(x - Double.longBitsToDouble(Double.doubleToLongBits(x) ^ 1));
3393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Compute least significant bit (Unit in Last Position) for a number.
3397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which ulp is requested
3398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return ulp(x)
3399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static float ulp(float x) {
3401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Float.isInfinite(x)) {
3402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Float.POSITIVE_INFINITY;
3403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return abs(x - Float.intBitsToFloat(Float.floatToIntBits(x) ^ 1));
3405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Multiply a double number by a power of 2.
3409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param d number to multiply
3410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param n power of 2
3411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return d &times; 2<sup>n</sup>
3412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double scalb(final double d, final int n) {
3414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // first simple and fast handling when 2^n can be represented using normal numbers
3416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((n > -1023) && (n < 1024)) {
3417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return d * Double.longBitsToDouble(((long) (n + 1023)) << 52);
3418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // handle special cases
3421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Double.isNaN(d) || Double.isInfinite(d) || (d == 0)) {
3422dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return d;
3423dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3424dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (n < -2098) {
3425dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (d > 0) ? 0.0 : -0.0;
3426dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3427dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (n > 2097) {
3428dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (d > 0) ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
3429dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3430dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3431dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // decompose d
3432dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final long bits = Double.doubleToLongBits(d);
3433dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final long sign = bits & 0x8000000000000000L;
3434dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int  exponent   = ((int) (bits >>> 52)) & 0x7ff;
3435dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long mantissa   = bits & 0x000fffffffffffffL;
3436dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3437dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // compute scaled exponent
3438dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int scaledExponent = exponent + n;
3439dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3440dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (n < 0) {
3441dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // we are really in the case n <= -1023
3442dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (scaledExponent > 0) {
3443dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // both the input and the result are normal numbers, we only adjust the exponent
3444dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.longBitsToDouble(sign | (((long) scaledExponent) << 52) | mantissa);
3445dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else if (scaledExponent > -53) {
3446dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // the input is a normal number and the result is a subnormal number
3447dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3448dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // recover the hidden mantissa bit
3449dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                mantissa = mantissa | (1L << 52);
3450dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3451dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // scales down complete mantissa, hence losing least significant bits
3452dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                final long mostSignificantLostBit = mantissa & (1L << (-scaledExponent));
3453dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                mantissa = mantissa >>> (1 - scaledExponent);
3454dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (mostSignificantLostBit != 0) {
3455dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    // we need to add 1 bit to round up the result
3456dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    mantissa++;
3457dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
3458dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.longBitsToDouble(sign | mantissa);
3459dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3460dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
3461dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // no need to compute the mantissa, the number scales down to 0
3462dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return (sign == 0L) ? 0.0 : -0.0;
3463dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3464dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
3465dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // we are really in the case n >= 1024
3466dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (exponent == 0) {
3467dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3468dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // the input number is subnormal, normalize it
3469dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                while ((mantissa >>> 52) != 1) {
3470dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    mantissa = mantissa << 1;
3471dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    --scaledExponent;
3472dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
3473dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ++scaledExponent;
3474dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                mantissa = mantissa & 0x000fffffffffffffL;
3475dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3476dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (scaledExponent < 2047) {
3477dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return Double.longBitsToDouble(sign | (((long) scaledExponent) << 52) | mantissa);
3478dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                } else {
3479dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return (sign == 0L) ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
3480dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
3481dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3482dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else if (scaledExponent < 2047) {
3483dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Double.longBitsToDouble(sign | (((long) scaledExponent) << 52) | mantissa);
3484dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
3485dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return (sign == 0L) ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
3486dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3487dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3488dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3489dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3490dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3491dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3492dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Multiply a float number by a power of 2.
3493dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param f number to multiply
3494dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param n power of 2
3495dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return f &times; 2<sup>n</sup>
3496dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3497dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static float scalb(final float f, final int n) {
3498dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3499dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // first simple and fast handling when 2^n can be represented using normal numbers
3500dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((n > -127) && (n < 128)) {
3501dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return f * Float.intBitsToFloat((n + 127) << 23);
3502dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3503dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3504dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // handle special cases
3505dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Float.isNaN(f) || Float.isInfinite(f) || (f == 0f)) {
3506dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return f;
3507dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3508dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (n < -277) {
3509dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (f > 0) ? 0.0f : -0.0f;
3510dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3511dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (n > 276) {
3512dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (f > 0) ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY;
3513dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3514dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3515dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // decompose f
3516dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final int bits = Float.floatToIntBits(f);
3517dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final int sign = bits & 0x80000000;
3518dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int  exponent  = (bits >>> 23) & 0xff;
3519dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int mantissa   = bits & 0x007fffff;
3520dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3521dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // compute scaled exponent
3522dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int scaledExponent = exponent + n;
3523dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3524dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (n < 0) {
3525dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // we are really in the case n <= -127
3526dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (scaledExponent > 0) {
3527dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // both the input and the result are normal numbers, we only adjust the exponent
3528dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Float.intBitsToFloat(sign | (scaledExponent << 23) | mantissa);
3529dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else if (scaledExponent > -24) {
3530dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // the input is a normal number and the result is a subnormal number
3531dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3532dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // recover the hidden mantissa bit
3533dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                mantissa = mantissa | (1 << 23);
3534dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3535dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // scales down complete mantissa, hence losing least significant bits
3536dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                final int mostSignificantLostBit = mantissa & (1 << (-scaledExponent));
3537dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                mantissa = mantissa >>> (1 - scaledExponent);
3538dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (mostSignificantLostBit != 0) {
3539dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    // we need to add 1 bit to round up the result
3540dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    mantissa++;
3541dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
3542dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Float.intBitsToFloat(sign | mantissa);
3543dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3544dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
3545dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // no need to compute the mantissa, the number scales down to 0
3546dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return (sign == 0) ? 0.0f : -0.0f;
3547dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3548dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
3549dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            // we are really in the case n >= 128
3550dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (exponent == 0) {
3551dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3552dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // the input number is subnormal, normalize it
3553dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                while ((mantissa >>> 23) != 1) {
3554dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    mantissa = mantissa << 1;
3555dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    --scaledExponent;
3556dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
3557dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                ++scaledExponent;
3558dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                mantissa = mantissa & 0x007fffff;
3559dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3560dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (scaledExponent < 255) {
3561dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return Float.intBitsToFloat(sign | (scaledExponent << 23) | mantissa);
3562dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                } else {
3563dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    return (sign == 0) ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY;
3564dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
3565dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3566dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else if (scaledExponent < 255) {
3567dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return Float.intBitsToFloat(sign | (scaledExponent << 23) | mantissa);
3568dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
3569dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return (sign == 0) ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY;
3570dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3571dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3572dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3573dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3574dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3575dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3576dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Get the next machine representable number after a number, moving
3577dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * in the direction of another number.
3578dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
3579dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The ordering is as follows (increasing):
3580dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <ul>
3581dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>-INFINITY</li>
3582dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>-MAX_VALUE</li>
3583dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>-MIN_VALUE</li>
3584dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>-0.0</li>
3585dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>+0.0</li>
3586dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>+MIN_VALUE</li>
3587dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>+MAX_VALUE</li>
3588dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>+INFINITY</li>
3589dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li></li>
3590dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
3591dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If arguments compare equal, then the second argument is returned.
3592dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
3593dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If {@code direction} is greater than {@code d},
3594dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the smallest machine representable number strictly greater than
3595dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * {@code d} is returned; if less, then the largest representable number
3596dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * strictly less than {@code d} is returned.</p>
3597dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
3598dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If {@code d} is infinite and direction does not
3599dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * bring it back to finite numbers, it is returned unchanged.</p>
3600dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
3601dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param d base number
3602dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param direction (the only important thing is whether
3603dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * {@code direction} is greater or smaller than {@code d})
3604dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the next machine representable number in the specified direction
3605dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3606dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double nextAfter(double d, double direction) {
3607dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3608dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // handling of some important special cases
3609dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Double.isNaN(d) || Double.isNaN(direction)) {
3610dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.NaN;
3611dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (d == direction) {
3612dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return direction;
3613dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (Double.isInfinite(d)) {
3614dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (d < 0) ? -Double.MAX_VALUE : Double.MAX_VALUE;
3615dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (d == 0) {
3616dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (direction < 0) ? -Double.MIN_VALUE : Double.MIN_VALUE;
3617dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3618dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // special cases MAX_VALUE to infinity and  MIN_VALUE to 0
3619dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // are handled just as normal numbers
3620dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3621dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final long bits = Double.doubleToLongBits(d);
3622dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final long sign = bits & 0x8000000000000000L;
3623dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((direction < d) ^ (sign == 0L)) {
3624dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.longBitsToDouble(sign | ((bits & 0x7fffffffffffffffL) + 1));
3625dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
3626dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.longBitsToDouble(sign | ((bits & 0x7fffffffffffffffL) - 1));
3627dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3628dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3629dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3630dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3631dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3632dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Get the next machine representable number after a number, moving
3633dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * in the direction of another number.
3634dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
3635dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The ordering is as follows (increasing):
3636dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <ul>
3637dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>-INFINITY</li>
3638dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>-MAX_VALUE</li>
3639dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>-MIN_VALUE</li>
3640dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>-0.0</li>
3641dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>+0.0</li>
3642dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>+MIN_VALUE</li>
3643dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>+MAX_VALUE</li>
3644dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>+INFINITY</li>
3645dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li></li>
3646dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
3647dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If arguments compare equal, then the second argument is returned.
3648dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
3649dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If {@code direction} is greater than {@code f},
3650dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the smallest machine representable number strictly greater than
3651dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * {@code f} is returned; if less, then the largest representable number
3652dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * strictly less than {@code f} is returned.</p>
3653dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
3654dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If {@code f} is infinite and direction does not
3655dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * bring it back to finite numbers, it is returned unchanged.</p>
3656dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
3657dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param f base number
3658dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param direction (the only important thing is whether
3659dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * {@code direction} is greater or smaller than {@code f})
3660dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the next machine representable number in the specified direction
3661dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3662dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static float nextAfter(final float f, final double direction) {
3663dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3664dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // handling of some important special cases
3665dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Double.isNaN(f) || Double.isNaN(direction)) {
3666dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Float.NaN;
3667dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (f == direction) {
3668dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (float) direction;
3669dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (Float.isInfinite(f)) {
3670dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (f < 0f) ? -Float.MAX_VALUE : Float.MAX_VALUE;
3671dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (f == 0f) {
3672dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return (direction < 0) ? -Float.MIN_VALUE : Float.MIN_VALUE;
3673dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3674dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // special cases MAX_VALUE to infinity and  MIN_VALUE to 0
3675dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // are handled just as normal numbers
3676dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3677dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final int bits = Float.floatToIntBits(f);
3678dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final int sign = bits & 0x80000000;
3679dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((direction < f) ^ (sign == 0)) {
3680dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Float.intBitsToFloat(sign | ((bits & 0x7fffffff) + 1));
3681dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
3682dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Float.intBitsToFloat(sign | ((bits & 0x7fffffff) - 1));
3683dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3684dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3685dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3686dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3687dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Get the largest whole number smaller than x.
3688dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which floor is requested
3689dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a double number f such that f is an integer f <= x < f + 1.0
3690dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3691dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double floor(double x) {
3692dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long y;
3693dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3694dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x != x) { // NaN
3695dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return x;
3696dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3697dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3698dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x >= TWO_POWER_52 || x <= -TWO_POWER_52) {
3699dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return x;
3700dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3701dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3702dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        y = (long) x;
3703dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x < 0 && y != x) {
3704dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            y--;
3705dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3706dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3707dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (y == 0) {
3708dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return x*y;
3709dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3710dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3711dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return y;
3712dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3713dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3714dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Get the smallest whole number larger than x.
3715dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which ceil is requested
3716dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a double number c such that c is an integer c - 1.0 < x <= c
3717dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3718dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double ceil(double x) {
3719dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double y;
3720dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3721dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x != x) { // NaN
3722dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return x;
3723dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3724dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3725dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        y = floor(x);
3726dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (y == x) {
3727dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return y;
3728dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3729dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3730dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        y += 1.0;
3731dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3732dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (y == 0) {
3733dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return x*y;
3734dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3735dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3736dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return y;
3737dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3738dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3739dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Get the whole number that is the nearest to x, or the even one if x is exactly half way between two integers.
3740dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which nearest whole number is requested
3741dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a double number r such that r is an integer r - 0.5 <= x <= r + 0.5
3742dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3743dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double rint(double x) {
3744dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double y = floor(x);
3745dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double d = x - y;
3746dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3747dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (d > 0.5) {
3748dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (y == -1.0) {
3749dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return -0.0; // Preserve sign of operand
3750dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3751dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return y+1.0;
3752dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3753dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (d < 0.5) {
3754dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return y;
3755dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3756dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3757dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* half way, round to even */
3758dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long z = (long) y;
3759dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (z & 1) == 0 ? y : y + 1.0;
3760dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3761dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3762dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Get the closest long to x.
3763dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which closest long is requested
3764dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return closest long to x
3765dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3766dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static long round(double x) {
3767dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (long) floor(x + 0.5);
3768dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3769dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3770dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Get the closest int to x.
3771dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x number from which closest int is requested
3772dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return closest int to x
3773dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3774dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static int round(final float x) {
3775dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (int) floor(x + 0.5f);
3776dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3777dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3778dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the minimum of two values
3779dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a first value
3780dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param b second value
3781dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a if a is lesser or equal to b, b otherwise
3782dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3783dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static int min(final int a, final int b) {
3784dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (a <= b) ? a : b;
3785dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3786dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3787dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the minimum of two values
3788dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a first value
3789dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param b second value
3790dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a if a is lesser or equal to b, b otherwise
3791dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3792dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static long min(final long a, final long b) {
3793dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (a <= b) ? a : b;
3794dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3795dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3796dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the minimum of two values
3797dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a first value
3798dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param b second value
3799dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a if a is lesser or equal to b, b otherwise
3800dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3801dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static float min(final float a, final float b) {
3802dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a > b) {
3803dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return b;
3804dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3805dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a < b) {
3806dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return a;
3807dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3808dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* if either arg is NaN, return NaN */
3809dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a != b) {
3810dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Float.NaN;
3811dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3812dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* min(+0.0,-0.0) == -0.0 */
3813dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* 0x80000000 == Float.floatToRawIntBits(-0.0d) */
3814dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int bits = Float.floatToRawIntBits(a);
3815dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (bits == 0x80000000) {
3816dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return a;
3817dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3818dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return b;
3819dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3820dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3821dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the minimum of two values
3822dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a first value
3823dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param b second value
3824dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a if a is lesser or equal to b, b otherwise
3825dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3826dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double min(final double a, final double b) {
3827dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a > b) {
3828dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return b;
3829dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3830dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a < b) {
3831dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return a;
3832dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3833dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* if either arg is NaN, return NaN */
3834dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a != b) {
3835dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.NaN;
3836dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3837dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* min(+0.0,-0.0) == -0.0 */
3838dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* 0x8000000000000000L == Double.doubleToRawLongBits(-0.0d) */
3839dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long bits = Double.doubleToRawLongBits(a);
3840dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (bits == 0x8000000000000000L) {
3841dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return a;
3842dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3843dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return b;
3844dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3845dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3846dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the maximum of two values
3847dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a first value
3848dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param b second value
3849dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return b if a is lesser or equal to b, a otherwise
3850dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3851dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static int max(final int a, final int b) {
3852dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (a <= b) ? b : a;
3853dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3854dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3855dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the maximum of two values
3856dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a first value
3857dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param b second value
3858dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return b if a is lesser or equal to b, a otherwise
3859dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3860dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static long max(final long a, final long b) {
3861dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (a <= b) ? b : a;
3862dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3863dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3864dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the maximum of two values
3865dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a first value
3866dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param b second value
3867dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return b if a is lesser or equal to b, a otherwise
3868dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3869dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static float max(final float a, final float b) {
3870dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a > b) {
3871dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return a;
3872dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3873dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a < b) {
3874dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return b;
3875dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3876dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* if either arg is NaN, return NaN */
3877dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a != b) {
3878dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Float.NaN;
3879dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3880dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* min(+0.0,-0.0) == -0.0 */
3881dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* 0x80000000 == Float.floatToRawIntBits(-0.0d) */
3882dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int bits = Float.floatToRawIntBits(a);
3883dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (bits == 0x80000000) {
3884dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return b;
3885dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3886dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return a;
3887dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3888dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3889dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Compute the maximum of two values
3890dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param a first value
3891dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param b second value
3892dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return b if a is lesser or equal to b, a otherwise
3893dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3894dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double max(final double a, final double b) {
3895dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a > b) {
3896dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return a;
3897dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3898dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a < b) {
3899dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return b;
3900dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3901dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* if either arg is NaN, return NaN */
3902dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (a != b) {
3903dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.NaN;
3904dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3905dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* min(+0.0,-0.0) == -0.0 */
3906dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        /* 0x8000000000000000L == Double.doubleToRawLongBits(-0.0d) */
3907dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long bits = Double.doubleToRawLongBits(a);
3908dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (bits == 0x8000000000000000L) {
3909dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return b;
3910dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3911dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return a;
3912dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3913dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3914dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3915dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the hypotenuse of a triangle with sides {@code x} and {@code y}
3916dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * - sqrt(<i>x</i><sup>2</sup>&nbsp;+<i>y</i><sup>2</sup>)<br/>
3917dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * avoiding intermediate overflow or underflow.
3918dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
3919dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <ul>
3920dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li> If either argument is infinite, then the result is positive infinity.</li>
3921dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li> else, if either argument is NaN then the result is NaN.</li>
3922dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </ul>
3923dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
3924dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x a value
3925dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param y a value
3926dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return sqrt(<i>x</i><sup>2</sup>&nbsp;+<i>y</i><sup>2</sup>)
3927dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3928dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double hypot(final double x, final double y) {
3929dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Double.isInfinite(x) || Double.isInfinite(y)) {
3930dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.POSITIVE_INFINITY;
3931dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (Double.isNaN(x) || Double.isNaN(y)) {
3932dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return Double.NaN;
3933dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
3934dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3935dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final int expX = getExponent(x);
3936dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            final int expY = getExponent(y);
3937dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (expX > expY + 27) {
3938dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // y is neglectible with respect to x
3939dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return abs(x);
3940dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else if (expY > expX + 27) {
3941dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // x is neglectible with respect to y
3942dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return abs(y);
3943dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
3944dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3945dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // find an intermediate scale to avoid both overflow and underflow
3946dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                final int middleExp = (expX + expY) / 2;
3947dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3948dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // scale parameters without losing precision
3949dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                final double scaledX = scalb(x, -middleExp);
3950dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                final double scaledY = scalb(y, -middleExp);
3951dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3952dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // compute scaled hypotenuse
3953dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                final double scaledH = sqrt(scaledX * scaledX + scaledY * scaledY);
3954dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3955dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // remove scaling
3956dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return scalb(scaledH, middleExp);
3957dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3958dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
3959dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3960dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
3961dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3962dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3963dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3964dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Computes the remainder as prescribed by the IEEE 754 standard.
3965dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * The remainder value is mathematically equal to {@code x - y*n}
3966dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * where {@code n} is the mathematical integer closest to the exact mathematical value
3967dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * of the quotient {@code x/y}.
3968dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If two mathematical integers are equally close to {@code x/y} then
3969dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * {@code n} is the integer that is even.
3970dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
3971dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <ul>
3972dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>If either operand is NaN, the result is NaN.</li>
3973dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>If the result is not NaN, the sign of the result equals the sign of the dividend.</li>
3974dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>If the dividend is an infinity, or the divisor is a zero, or both, the result is NaN.</li>
3975dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>If the dividend is finite and the divisor is an infinity, the result equals the dividend.</li>
3976dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <li>If the dividend is a zero and the divisor is finite, the result equals the dividend.</li>
3977dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </ul>
3978dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p><b>Note:</b> this implementation currently delegates to {@link StrictMath#IEEEremainder}
3979dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param dividend the number to be divided
3980dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param divisor the number by which to divide
3981dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the remainder, rounded
3982dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3983dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double IEEEremainder(double dividend, double divisor) {
3984dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return StrictMath.IEEEremainder(dividend, divisor); // TODO provide our own implementation
3985dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
3986dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
3987dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
3988dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the first argument with the sign of the second argument.
3989dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * A NaN {@code sign} argument is treated as positive.
3990dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
3991dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param magnitude the value to return
3992dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param sign the sign for the returned value
3993dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the magnitude with the same sign as the {@code sign} argument
3994dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
3995dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static double copySign(double magnitude, double sign){
3996dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long m = Double.doubleToLongBits(magnitude);
3997dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        long s = Double.doubleToLongBits(sign);
3998dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK
3999dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return magnitude;
4000dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
4001dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return -magnitude; // flip sign
4002dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
4003dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
4004dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
4005dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the first argument with the sign of the second argument.
4006dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * A NaN {@code sign} argument is treated as positive.
4007dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
4008dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param magnitude the value to return
4009dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param sign the sign for the returned value
4010dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the magnitude with the same sign as the {@code sign} argument
4011dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
4012dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static float copySign(float magnitude, float sign){
4013dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int m = Float.floatToIntBits(magnitude);
4014dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int s = Float.floatToIntBits(sign);
4015dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK
4016dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return magnitude;
4017dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
4018dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return -magnitude; // flip sign
4019dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
4020dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
4021dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
4022dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Return the exponent of a double number, removing the bias.
4023dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
4024dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For double numbers of the form 2<sup>x</sup>, the unbiased
4025dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * exponent is exactly x.
4026dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </p>
4027dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param d number from which exponent is requested
4028dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return exponent for d in IEEE754 representation, without bias
4029dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
4030dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static int getExponent(final double d) {
4031dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (int) ((Double.doubleToLongBits(d) >>> 52) & 0x7ff) - 1023;
4032dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
4033dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
4034dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
4035dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Return the exponent of a float number, removing the bias.
4036dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
4037dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For float numbers of the form 2<sup>x</sup>, the unbiased
4038dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * exponent is exactly x.
4039dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * </p>
4040dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param f number from which exponent is requested
4041dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return exponent for d in IEEE754 representation, without bias
4042dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
4043dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public static int getExponent(final float f) {
4044dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return ((Float.floatToIntBits(f) >>> 23) & 0xff) - 127;
4045dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
4046dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
4047dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond}
4048