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 */ 17dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 18dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpackage org.apache.commons.math.dfp; 19dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 20dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/** Mathematical routines for use with {@link Dfp}. 21dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The constants are defined in {@link DfpField} 22dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 1042376 $ $Date: 2010-12-05 16:54:55 +0100 (dim. 05 déc. 2010) $ 23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @since 2.2 24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic class DfpMath { 26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Name for traps triggered by pow. */ 28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private static final String POW_TRAP = "pow"; 29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Private Constructor. 32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private DfpMath() { 34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Breaks a string representation up into two dfp's. 37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>The two dfp are such that the sum of them is equivalent 38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * to the input string, but has higher precision than using a 39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * single dfp. This is useful for improving accuracy of 40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * exponentiation and critical multiplies. 41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param field field to which the Dfp must belong 42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a string representation to split 43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return an array of two {@link Dfp} which sum is a 44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected static Dfp[] split(final DfpField field, final String a) { 46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp result[] = new Dfp[2]; 47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond char[] buf; 48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond boolean leading = true; 49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int sp = 0; 50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int sig = 0; 51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond buf = new char[a.length()]; 53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < buf.length; i++) { 55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond buf[i] = a.charAt(i); 56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (buf[i] >= '1' && buf[i] <= '9') { 58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond leading = false; 59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (buf[i] == '.') { 62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sig += (400 - sig) % 4; 63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond leading = false; 64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (sig == (field.getRadixDigits() / 2) * 4) { 67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sp = i; 68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond break; 69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (buf[i] >= '0' && buf[i] <= '9' && !leading) { 72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sig ++; 73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[0] = field.newDfp(new String(buf, 0, sp)); 77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < buf.length; i++) { 79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond buf[i] = a.charAt(i); 80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (buf[i] >= '0' && buf[i] <= '9' && i < sp) { 81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond buf[i] = '0'; 82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[1] = field.newDfp(new String(buf)); 86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return result; 88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Splits a {@link Dfp} into 2 {@link Dfp}'s such that their sum is equal to the input {@link Dfp}. 91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number to split 92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return two elements array containing the split number 93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected static Dfp[] split(final Dfp a) { 95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp[] result = new Dfp[2]; 96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp shift = a.multiply(a.power10K(a.getRadixDigits() / 2)); 97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[0] = a.add(shift).subtract(shift); 98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[1] = a.subtract(result[0]); 99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return result; 100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Multiply two numbers that are split in to two pieces that are 103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * meant to be added together. 104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Use binomial multiplication so ab = a0 b0 + a0 b1 + a1 b0 + a1 b1 105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Store the first term in result0, the rest in result1 106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a first factor of the multiplication, in split form 107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param b second factor of the multiplication, in split form 108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return a × b, in split form 109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected static Dfp[] splitMult(final Dfp[] a, final Dfp[] b) { 111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp[] result = new Dfp[2]; 112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[1] = a[0].getZero(); 114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[0] = a[0].multiply(b[0]); 115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /* If result[0] is infinite or zero, don't compute result[1]. 117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Attempting to do so may produce NaNs. 118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (result[0].classify() == Dfp.INFINITE || result[0].equals(result[1])) { 121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return result; 122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[1] = a[0].multiply(b[1]).add(a[1].multiply(b[0])).add(a[1].multiply(b[1])); 125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return result; 127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Divide two numbers that are split in to two pieces that are meant to be added together. 130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Inverse of split multiply above: 131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (a+b) / (c+d) = (a/c) + ( (bc-ad)/(c**2+cd) ) 132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a dividend, in split form 133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param b divisor, in split form 134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return a / b, in split form 135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected static Dfp[] splitDiv(final Dfp[] a, final Dfp[] b) { 137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp[] result; 138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result = new Dfp[2]; 140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[0] = a[0].divide(b[0]); 142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[1] = a[1].multiply(b[0]).subtract(a[0].multiply(b[1])); 143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[1] = result[1].divide(b[0].multiply(b[0]).add(b[0].multiply(b[1]))); 144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return result; 146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Raise a split base to the a power. 149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param base number to raise 150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a power 151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return base<sup>a</sup> 152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected static Dfp splitPow(final Dfp[] base, int a) { 154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond boolean invert = false; 155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp[] r = new Dfp[2]; 157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp[] result = new Dfp[2]; 159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[0] = base[0].getOne(); 160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[1] = base[0].getZero(); 161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (a == 0) { 163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Special case a = 0 164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return result[0].add(result[1]); 165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (a < 0) { 168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // If a is less than zero 169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond invert = true; 170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond a = -a; 171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Exponentiate by successive squaring 174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond do { 175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond r[0] = new Dfp(base[0]); 176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond r[1] = new Dfp(base[1]); 177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int trial = 1; 178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int prevtrial; 180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond while (true) { 181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond prevtrial = trial; 182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond trial = trial * 2; 183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (trial > a) { 184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond break; 185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond r = splitMult(r, r); 187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond trial = prevtrial; 190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond a -= trial; 192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result = splitMult(result, r); 193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } while (a >= 1); 195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[0] = result[0].add(result[1]); 197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (invert) { 199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result[0] = base[0].getOne().divide(result[0]); 200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return result[0]; 203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Raises base to the power a by successive squaring. 207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param base number to raise 208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a power 209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return base<sup>a</sup> 210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public static Dfp pow(Dfp base, int a) 212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond { 213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond boolean invert = false; 214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp result = base.getOne(); 216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (a == 0) { 218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Special case 219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return result; 220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (a < 0) { 223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond invert = true; 224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond a = -a; 225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Exponentiate by successive squaring 228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond do { 229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp r = new Dfp(base); 230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp prevr; 231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int trial = 1; 232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int prevtrial; 233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond do { 235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond prevr = new Dfp(r); 236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond prevtrial = trial; 237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond r = r.multiply(r); 238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond trial = trial * 2; 239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } while (a>trial); 240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond r = prevr; 242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond trial = prevtrial; 243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond a = a - trial; 245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result = result.multiply(r); 246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } while (a >= 1); 248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (invert) { 250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result = base.getOne().divide(result); 251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return base.newInstance(result); 254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Computes e to the given power. 258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * a is broken into two parts, such that a = n+m where n is an integer. 259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * We use pow() to compute e<sup>n</sup> and a Taylor series to compute 260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * e<sup>m</sup>. We return e*<sup>n</sup> × e<sup>m</sup> 261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a power at which e should be raised 262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return e<sup>a</sup> 263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public static Dfp exp(final Dfp a) { 265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp inta = a.rint(); 267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp fraca = a.subtract(inta); 268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int ia = inta.intValue(); 270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (ia > 2147483646) { 271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // return +Infinity 272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return a.newInstance((byte)1, Dfp.INFINITE); 273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (ia < -2147483646) { 276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // return 0; 277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return a.newInstance(); 278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp einta = splitPow(a.getField().getESplit(), ia); 281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp efraca = expInternal(fraca); 282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return einta.multiply(efraca); 284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Computes e to the given power. 287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Where -1 < a < 1. Use the classic Taylor series. 1 + x**2/2! + x**3/3! + x**4/4! ... 288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a power at which e should be raised 289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return e<sup>a</sup> 290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected static Dfp expInternal(final Dfp a) { 292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp y = a.getOne(); 293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp x = a.getOne(); 294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp fact = a.getOne(); 295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp py = new Dfp(y); 296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 1; i < 90; i++) { 298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.multiply(a); 299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond fact = fact.divide(i); 300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = y.add(x.multiply(fact)); 301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.equals(py)) { 302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond break; 303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond py = new Dfp(y); 305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return y; 308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Returns the natural logarithm of a. 311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * a is first split into three parts such that a = (10000^h)(2^j)k. 312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * ln(a) is computed by ln(a) = ln(5)*h + ln(2)*(h+j) + ln(k) 313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * k is in the range 2/3 < k <4/3 and is passed on to a series expansion. 314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number from which logarithm is requested 315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return log(a) 316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public static Dfp log(Dfp a) { 318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int lr; 319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp x; 320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int ix; 321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int p2 = 0; 322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Check the arguments somewhat here 324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (a.equals(a.getZero()) || a.lessThan(a.getZero()) || a.isNaN()) { 325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // negative, zero or NaN 326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond a.getField().setIEEEFlagsBits(DfpField.FLAG_INVALID); 327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return a.dotrap(DfpField.FLAG_INVALID, "ln", a, a.newInstance((byte)1, Dfp.QNAN)); 328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (a.classify() == Dfp.INFINITE) { 331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return a; 332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = new Dfp(a); 335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond lr = x.log10K(); 336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.divide(pow(a.newInstance(10000), lr)); /* This puts x in the range 0-10000 */ 338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond ix = x.floor().intValue(); 339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond while (ix > 2) { 341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond ix >>= 1; 342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond p2++; 343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp[] spx = split(x); 347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp[] spy = new Dfp[2]; 348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spy[0] = pow(a.getTwo(), p2); // use spy[0] temporarily as a divisor 349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spx[0] = spx[0].divide(spy[0]); 350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spx[1] = spx[1].divide(spy[0]); 351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spy[0] = a.newInstance("1.33333"); // Use spy[0] for comparison 353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond while (spx[0].add(spx[1]).greaterThan(spy[0])) { 354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spx[0] = spx[0].divide(2); 355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spx[1] = spx[1].divide(2); 356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond p2++; 357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // X is now in the range of 2/3 < x < 4/3 360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp[] spz = logInternal(spx); 361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spx[0] = a.newInstance(new StringBuilder().append(p2+4*lr).toString()); 363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spx[1] = a.getZero(); 364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spy = splitMult(a.getField().getLn2Split(), spx); 365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spz[0] = spz[0].add(spy[0]); 367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spz[1] = spz[1].add(spy[1]); 368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spx[0] = a.newInstance(new StringBuilder().append(4*lr).toString()); 370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spx[1] = a.getZero(); 371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spy = splitMult(a.getField().getLn5Split(), spx); 372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spz[0] = spz[0].add(spy[0]); 374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond spz[1] = spz[1].add(spy[1]); 375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return a.newInstance(spz[0].add(spz[1])); 377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Computes the natural log of a number between 0 and 2. 381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Let f(x) = ln(x), 382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * We know that f'(x) = 1/x, thus from Taylor's theorum we have: 384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * ----- n+1 n 386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * f(x) = \ (-1) (x - 1) 387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * / ---------------- for 1 <= n <= infinity 388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * ----- n 389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * or 391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 2 3 4 392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (x-1) (x-1) (x-1) 393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * ln(x) = (x-1) - ----- + ------ - ------ + ... 394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 2 3 4 395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * alternatively, 397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 2 3 4 399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * x x x 400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * ln(x+1) = x - - + - - - + ... 401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 2 3 4 402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * This series can be used to compute ln(x), but it converges too slowly. 404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * If we substitute -x for x above, we get 406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 2 3 4 408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * x x x 409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * ln(1-x) = -x - - - - - - + ... 410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 2 3 4 411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Note that all terms are now negative. Because the even powered ones 413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * absorbed the sign. Now, subtract the series above from the previous 414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * one to get ln(x+1) - ln(1-x). Note the even terms cancel out leaving 415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * only the odd ones 416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 3 5 7 418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 2x 2x 2x 419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * ln(x+1) - ln(x-1) = 2x + --- + --- + ---- + ... 420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 3 5 7 421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 422dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * By the property of logarithms that ln(a) - ln(b) = ln (a/b) we have: 423dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 424dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 3 5 7 425dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * x+1 / x x x \ 426dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * ln ----- = 2 * | x + ---- + ---- + ---- + ... | 427dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * x-1 \ 3 5 7 / 428dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 429dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * But now we want to find ln(a), so we need to find the value of x 430dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * such that a = (x+1)/(x-1). This is easily solved to find that 431dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * x = (a-1)/(a+1). 432dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number from which logarithm is requested, in split form 433dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return log(a) 434dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 435dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected static Dfp[] logInternal(final Dfp a[]) { 436dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 437dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /* Now we want to compute x = (a-1)/(a+1) but this is prone to 438dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * loss of precision. So instead, compute x = (a/4 - 1/4) / (a/4 + 1/4) 439dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 440dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp t = a[0].divide(4).add(a[1].divide(4)); 441dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp x = t.add(a[0].newInstance("-0.25")).divide(t.add(a[0].newInstance("0.25"))); 442dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 443dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp y = new Dfp(x); 444dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp num = new Dfp(x); 445dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp py = new Dfp(y); 446dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int den = 1; 447dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < 10000; i++) { 448dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond num = num.multiply(x); 449dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond num = num.multiply(x); 450dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond den = den + 2; 451dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond t = num.divide(den); 452dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = y.add(t); 453dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.equals(py)) { 454dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond break; 455dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 456dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond py = new Dfp(y); 457dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 458dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 459dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = y.multiply(a[0].getTwo()); 460dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 461dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return split(y); 462dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 463dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 464dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 465dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Computes x to the y power.<p> 466dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 467dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Uses the following method:<p> 468dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 469dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <ol> 470dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> Set u = rint(y), v = y-u 471dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> Compute a = v * ln(x) 472dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> Compute b = rint( a/ln(2) ) 473dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> Compute c = a - b*ln(2) 474dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> x<sup>y</sup> = x<sup>u</sup> * 2<sup>b</sup> * e<sup>c</sup> 475dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </ol> 476dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * if |y| > 1e8, then we compute by exp(y*ln(x)) <p> 477dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 478dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <b>Special Cases</b><p> 479dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <ul> 480dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if y is 0.0 or -0.0 then result is 1.0 481dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if y is 1.0 then result is x 482dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if y is NaN then result is NaN 483dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x is NaN and y is not zero then result is NaN 484dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if |x| > 1.0 and y is +Infinity then result is +Infinity 485dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if |x| < 1.0 and y is -Infinity then result is +Infinity 486dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if |x| > 1.0 and y is -Infinity then result is +0 487dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if |x| < 1.0 and y is +Infinity then result is +0 488dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if |x| = 1.0 and y is +/-Infinity then result is NaN 489dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x = +0 and y > 0 then result is +0 490dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x = +Inf and y < 0 then result is +0 491dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x = +0 and y < 0 then result is +Inf 492dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x = +Inf and y > 0 then result is +Inf 493dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x = -0 and y > 0, finite, not odd integer then result is +0 494dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x = -0 and y < 0, finite, and odd integer then result is -Inf 495dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x = -Inf and y > 0, finite, and odd integer then result is -Inf 496dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x = -0 and y < 0, not finite odd integer then result is +Inf 497dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x = -Inf and y > 0, not finite odd integer then result is +Inf 498dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x < 0 and y > 0, finite, and odd integer then result is -(|x|<sup>y</sup>) 499dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <li> if x < 0 and y > 0, finite, and not integer then result is NaN 500dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </ul> 501dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param x base to be raised 502dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param y power to which base should be raised 503dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return x<sup>y</sup> 504dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 505dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public static Dfp pow(Dfp x, final Dfp y) { 506dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 507dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // make sure we don't mix number with different precision 508dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.getField().getRadixDigits() != y.getField().getRadixDigits()) { 509dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x.getField().setIEEEFlagsBits(DfpField.FLAG_INVALID); 510dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp result = x.newInstance(x.getZero()); 511dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result.nans = Dfp.QNAN; 512dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.dotrap(DfpField.FLAG_INVALID, POW_TRAP, x, result); 513dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 514dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 515dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp zero = x.getZero(); 516dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp one = x.getOne(); 517dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp two = x.getTwo(); 518dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond boolean invert = false; 519dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int ui; 520dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 521dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /* Check for special cases */ 522dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.equals(zero)) { 523dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(one); 524dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 525dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 526dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.equals(one)) { 527dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.isNaN()) { 528dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Test for NaNs 529dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x.getField().setIEEEFlagsBits(DfpField.FLAG_INVALID); 530dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.dotrap(DfpField.FLAG_INVALID, POW_TRAP, x, x); 531dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 532dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x; 533dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 534dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 535dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.isNaN() || y.isNaN()) { 536dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Test for NaNs 537dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x.getField().setIEEEFlagsBits(DfpField.FLAG_INVALID); 538dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.dotrap(DfpField.FLAG_INVALID, POW_TRAP, x, x.newInstance((byte)1, Dfp.QNAN)); 539dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 540dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 541dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // X == 0 542dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.equals(zero)) { 543dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (Dfp.copysign(one, x).greaterThan(zero)) { 544dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // X == +0 545dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.greaterThan(zero)) { 546dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(zero); 547dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 548dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(x.newInstance((byte)1, Dfp.INFINITE)); 549dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 550dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 551dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // X == -0 552dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.classify() == Dfp.FINITE && y.rint().equals(y) && !y.remainder(two).equals(zero)) { 553dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // If y is odd integer 554dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.greaterThan(zero)) { 555dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(zero.negate()); 556dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 557dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(x.newInstance((byte)-1, Dfp.INFINITE)); 558dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 559dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 560dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Y is not odd integer 561dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.greaterThan(zero)) { 562dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(zero); 563dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 564dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(x.newInstance((byte)1, Dfp.INFINITE)); 565dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 566dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 567dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 568dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 569dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 570dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.lessThan(zero)) { 571dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Make x positive, but keep track of it 572dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.negate(); 573dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond invert = true; 574dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 575dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 576dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.greaterThan(one) && y.classify() == Dfp.INFINITE) { 577dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.greaterThan(zero)) { 578dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return y; 579dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 580dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(zero); 581dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 582dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 583dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 584dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.lessThan(one) && y.classify() == Dfp.INFINITE) { 585dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.greaterThan(zero)) { 586dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(zero); 587dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 588dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(Dfp.copysign(y, one)); 589dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 590dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 591dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 592dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.equals(one) && y.classify() == Dfp.INFINITE) { 593dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x.getField().setIEEEFlagsBits(DfpField.FLAG_INVALID); 594dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.dotrap(DfpField.FLAG_INVALID, POW_TRAP, x, x.newInstance((byte)1, Dfp.QNAN)); 595dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 596dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 597dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.classify() == Dfp.INFINITE) { 598dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // x = +/- inf 599dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (invert) { 600dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // negative infinity 601dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.classify() == Dfp.FINITE && y.rint().equals(y) && !y.remainder(two).equals(zero)) { 602dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // If y is odd integer 603dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.greaterThan(zero)) { 604dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(x.newInstance((byte)-1, Dfp.INFINITE)); 605dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 606dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(zero.negate()); 607dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 608dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 609dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // Y is not odd integer 610dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.greaterThan(zero)) { 611dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(x.newInstance((byte)1, Dfp.INFINITE)); 612dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 613dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(zero); 614dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 615dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 616dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 617dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // positive infinity 618dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.greaterThan(zero)) { 619dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x; 620dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 621dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(zero); 622dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 623dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 624dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 625dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 626dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (invert && !y.rint().equals(y)) { 627dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x.getField().setIEEEFlagsBits(DfpField.FLAG_INVALID); 628dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.dotrap(DfpField.FLAG_INVALID, POW_TRAP, x, x.newInstance((byte)1, Dfp.QNAN)); 629dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 630dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 631dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // End special cases 632dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 633dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp r; 634dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.lessThan(x.newInstance(100000000)) && y.greaterThan(x.newInstance(-100000000))) { 635dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp u = y.rint(); 636dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond ui = u.intValue(); 637dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 638dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp v = y.subtract(u); 639dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 640dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (v.unequal(zero)) { 641dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp a = v.multiply(log(x)); 642dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp b = a.divide(x.getField().getLn2()).rint(); 643dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 644dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp c = a.subtract(b.multiply(x.getField().getLn2())); 645dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond r = splitPow(split(x), ui); 646dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond r = r.multiply(pow(two, b.intValue())); 647dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond r = r.multiply(exp(c)); 648dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 649dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond r = splitPow(split(x), ui); 650dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 651dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 652dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // very large exponent. |y| > 1e8 653dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond r = exp(log(x).multiply(y)); 654dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 655dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 656dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (invert) { 657dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // if y is odd integer 658dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.rint().equals(y) && !y.remainder(two).equals(zero)) { 659dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond r = r.negate(); 660dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 661dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 662dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 663dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return x.newInstance(r); 664dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 665dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 666dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 667dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Computes sin(a) Used when 0 < a < pi/4. 668dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Uses the classic Taylor series. x - x**3/3! + x**5/5! ... 669dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number from which sine is desired, in split form 670dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return sin(a) 671dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 672dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected static Dfp sinInternal(Dfp a[]) { 673dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 674dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp c = a[0].add(a[1]); 675dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp y = c; 676dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond c = c.multiply(c); 677dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp x = y; 678dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp fact = a[0].getOne(); 679dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp py = new Dfp(y); 680dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 681dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 3; i < 90; i += 2) { 682dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.multiply(c); 683dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.negate(); 684dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 685dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond fact = fact.divide((i-1)*i); // 1 over fact 686dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = y.add(x.multiply(fact)); 687dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.equals(py)) 688dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond break; 689dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond py = new Dfp(y); 690dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 691dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 692dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return y; 693dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 694dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 695dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 696dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Computes cos(a) Used when 0 < a < pi/4. 697dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Uses the classic Taylor series for cosine. 1 - x**2/2! + x**4/4! ... 698dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number from which cosine is desired, in split form 699dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return cos(a) 700dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 701dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected static Dfp cosInternal(Dfp a[]) { 702dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp one = a[0].getOne(); 703dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 704dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 705dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp x = one; 706dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp y = one; 707dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp c = a[0].add(a[1]); 708dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond c = c.multiply(c); 709dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 710dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp fact = one; 711dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp py = new Dfp(y); 712dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 713dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 2; i < 90; i += 2) { 714dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.multiply(c); 715dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.negate(); 716dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 717dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond fact = fact.divide((i - 1) * i); // 1 over fact 718dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 719dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = y.add(x.multiply(fact)); 720dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.equals(py)) { 721dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond break; 722dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 723dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond py = new Dfp(y); 724dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 725dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 726dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return y; 727dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 728dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 729dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 730dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** computes the sine of the argument. 731dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number from which sine is desired 732dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return sin(a) 733dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 734dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public static Dfp sin(final Dfp a) { 735dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp pi = a.getField().getPi(); 736dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp zero = a.getField().getZero(); 737dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond boolean neg = false; 738dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 739dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /* First reduce the argument to the range of +/- PI */ 740dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp x = a.remainder(pi.multiply(2)); 741dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 742dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /* if x < 0 then apply identity sin(-x) = -sin(x) */ 743dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /* This puts x in the range 0 < x < PI */ 744dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.lessThan(zero)) { 745dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.negate(); 746dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond neg = true; 747dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 748dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 749dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /* Since sine(x) = sine(pi - x) we can reduce the range to 750dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 0 < x < pi/2 751dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 752dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 753dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.greaterThan(pi.divide(2))) { 754dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = pi.subtract(x); 755dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 756dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 757dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp y; 758dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.lessThan(pi.divide(4))) { 759dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp c[] = new Dfp[2]; 760dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond c[0] = x; 761dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond c[1] = zero; 762dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 763dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond //y = sinInternal(c); 764dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = sinInternal(split(x)); 765dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 766dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp c[] = new Dfp[2]; 767dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp[] piSplit = a.getField().getPiSplit(); 768dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond c[0] = piSplit[0].divide(2).subtract(x); 769dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond c[1] = piSplit[1].divide(2); 770dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = cosInternal(c); 771dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 772dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 773dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (neg) { 774dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = y.negate(); 775dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 776dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 777dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return a.newInstance(y); 778dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 779dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 780dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 781dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** computes the cosine of the argument. 782dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number from which cosine is desired 783dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return cos(a) 784dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 785dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public static Dfp cos(Dfp a) { 786dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp pi = a.getField().getPi(); 787dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp zero = a.getField().getZero(); 788dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond boolean neg = false; 789dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 790dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /* First reduce the argument to the range of +/- PI */ 791dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp x = a.remainder(pi.multiply(2)); 792dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 793dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /* if x < 0 then apply identity cos(-x) = cos(x) */ 794dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /* This puts x in the range 0 < x < PI */ 795dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.lessThan(zero)) { 796dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.negate(); 797dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 798dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 799dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /* Since cos(x) = -cos(pi - x) we can reduce the range to 800dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 0 < x < pi/2 801dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 802dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 803dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.greaterThan(pi.divide(2))) { 804dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = pi.subtract(x); 805dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond neg = true; 806dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 807dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 808dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp y; 809dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.lessThan(pi.divide(4))) { 810dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp c[] = new Dfp[2]; 811dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond c[0] = x; 812dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond c[1] = zero; 813dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 814dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = cosInternal(c); 815dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 816dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp c[] = new Dfp[2]; 817dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp[] piSplit = a.getField().getPiSplit(); 818dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond c[0] = piSplit[0].divide(2).subtract(x); 819dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond c[1] = piSplit[1].divide(2); 820dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = sinInternal(c); 821dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 822dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 823dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (neg) { 824dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = y.negate(); 825dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 826dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 827dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return a.newInstance(y); 828dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 829dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 830dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 831dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** computes the tangent of the argument. 832dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number from which tangent is desired 833dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return tan(a) 834dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 835dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public static Dfp tan(final Dfp a) { 836dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return sin(a).divide(cos(a)); 837dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 838dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 839dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** computes the arc-tangent of the argument. 840dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number from which arc-tangent is desired 841dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return atan(a) 842dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 843dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond protected static Dfp atanInternal(final Dfp a) { 844dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 845dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp y = new Dfp(a); 846dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp x = new Dfp(y); 847dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp py = new Dfp(y); 848dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 849dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 3; i < 90; i += 2) { 850dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.multiply(a); 851dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.multiply(a); 852dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.negate(); 853dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = y.add(x.divide(i)); 854dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (y.equals(py)) { 855dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond break; 856dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 857dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond py = new Dfp(y); 858dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 859dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 860dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return y; 861dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 862dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 863dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 864dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** computes the arc tangent of the argument 865dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 866dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Uses the typical taylor series 867dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 868dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * but may reduce arguments using the following identity 869dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * tan(x+y) = (tan(x) + tan(y)) / (1 - tan(x)*tan(y)) 870dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 871dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * since tan(PI/8) = sqrt(2)-1, 872dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 873dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * atan(x) = atan( (x - sqrt(2) + 1) / (1+x*sqrt(2) - x) + PI/8.0 874dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number from which arc-tangent is desired 875dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return atan(a) 876dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 877dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public static Dfp atan(final Dfp a) { 878dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp zero = a.getField().getZero(); 879dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp one = a.getField().getOne(); 880dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp[] sqr2Split = a.getField().getSqr2Split(); 881dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp[] piSplit = a.getField().getPiSplit(); 882dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond boolean recp = false; 883dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond boolean neg = false; 884dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond boolean sub = false; 885dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 886dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final Dfp ty = sqr2Split[0].subtract(one).add(sqr2Split[1]); 887dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 888dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp x = new Dfp(a); 889dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.lessThan(zero)) { 890dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond neg = true; 891dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = x.negate(); 892dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 893dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 894dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.greaterThan(one)) { 895dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond recp = true; 896dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = one.divide(x); 897dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 898dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 899dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (x.greaterThan(ty)) { 900dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp sty[] = new Dfp[2]; 901dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sub = true; 902dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 903dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sty[0] = sqr2Split[0].subtract(one); 904dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond sty[1] = sqr2Split[1]; 905dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 906dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp[] xs = split(x); 907dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 908dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp[] ds = splitMult(xs, sty); 909dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond ds[0] = ds[0].add(one); 910dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 911dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond xs[0] = xs[0].subtract(sty[0]); 912dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond xs[1] = xs[1].subtract(sty[1]); 913dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 914dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond xs = splitDiv(xs, ds); 915dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond x = xs[0].add(xs[1]); 916dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 917dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond //x = x.subtract(ty).divide(dfp.one.add(x.multiply(ty))); 918dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 919dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 920dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp y = atanInternal(x); 921dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 922dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (sub) { 923dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = y.add(piSplit[0].divide(8)).add(piSplit[1].divide(8)); 924dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 925dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 926dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (recp) { 927dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = piSplit[0].divide(2).subtract(y).add(piSplit[1].divide(2)); 928dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 929dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 930dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (neg) { 931dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond y = y.negate(); 932dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 933dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 934dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return a.newInstance(y); 935dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 936dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 937dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 938dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** computes the arc-sine of the argument. 939dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number from which arc-sine is desired 940dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return asin(a) 941dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 942dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public static Dfp asin(final Dfp a) { 943dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return atan(a.divide(a.getOne().subtract(a.multiply(a)).sqrt())); 944dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 945dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 946dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** computes the arc-cosine of the argument. 947dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param a number from which arc-cosine is desired 948dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return acos(a) 949dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 950dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public static Dfp acos(Dfp a) { 951dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond Dfp result; 952dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond boolean negative = false; 953dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 954dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (a.lessThan(a.getZero())) { 955dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond negative = true; 956dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 957dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 958dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond a = Dfp.copysign(a, a.getOne()); // absolute value 959dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 960dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result = atan(a.getOne().subtract(a.multiply(a)).sqrt().divide(a)); 961dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 962dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (negative) { 963dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond result = a.getField().getPi().subtract(result); 964dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 965dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 966dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return a.newInstance(result); 967dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 968dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 969dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond} 970