DfpField.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      https://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */

  21. package org.hipparchus.dfp;

  22. import org.hipparchus.Field;

  23. /** Field for Decimal floating point instances.
  24.  */
  25. public class DfpField implements Field<Dfp> {

  26.     /** Enumerate for rounding modes. */
  27.     public enum RoundingMode {

  28.         /** Rounds toward zero (truncation). */
  29.         ROUND_DOWN,

  30.         /** Rounds away from zero if discarded digit is non-zero. */
  31.         ROUND_UP,

  32.         /** Rounds towards nearest unless both are equidistant in which case it rounds away from zero. */
  33.         ROUND_HALF_UP,

  34.         /** Rounds towards nearest unless both are equidistant in which case it rounds toward zero. */
  35.         ROUND_HALF_DOWN,

  36.         /** Rounds towards nearest unless both are equidistant in which case it rounds toward the even neighbor.
  37.          * This is the default as  specified by IEEE 854-1987
  38.          */
  39.         ROUND_HALF_EVEN,

  40.         /** Rounds towards nearest unless both are equidistant in which case it rounds toward the odd neighbor.  */
  41.         ROUND_HALF_ODD,

  42.         /** Rounds towards positive infinity. */
  43.         ROUND_CEIL,

  44.         /** Rounds towards negative infinity. */
  45.         ROUND_FLOOR

  46.     }

  47.     /** IEEE 854-1987 flag for invalid operation. */
  48.     public static final int FLAG_INVALID   =  1;

  49.     /** IEEE 854-1987 flag for division by zero. */
  50.     public static final int FLAG_DIV_ZERO  =  2;

  51.     /** IEEE 854-1987 flag for overflow. */
  52.     public static final int FLAG_OVERFLOW  =  4;

  53.     /** IEEE 854-1987 flag for underflow. */
  54.     public static final int FLAG_UNDERFLOW =  8;

  55.     /** IEEE 854-1987 flag for inexact result. */
  56.     public static final int FLAG_INEXACT   = 16;

  57.     /** High precision string representation of &radic;2. */
  58.     private static String sqr2String;

  59.     // Note: the static strings are set up (once) by the ctor and @GuardedBy("DfpField.class")

  60.     /** High precision string representation of &radic;2 / 2. */
  61.     private static String sqr2ReciprocalString;

  62.     /** High precision string representation of &radic;3. */
  63.     private static String sqr3String;

  64.     /** High precision string representation of &radic;3 / 3. */
  65.     private static String sqr3ReciprocalString;

  66.     /** High precision string representation of &pi;. */
  67.     private static String piString;

  68.     /** High precision string representation of e. */
  69.     private static String eString;

  70.     /** High precision string representation of ln(2). */
  71.     private static String ln2String;

  72.     /** High precision string representation of ln(5). */
  73.     private static String ln5String;

  74.     /** High precision string representation of ln(10). */
  75.     private static String ln10String;

  76.     /** The number of radix digits.
  77.      * Note these depend on the radix which is 10000 digits,
  78.      * so each one is equivalent to 4 decimal digits.
  79.      */
  80.     private final int radixDigits;

  81.     /** A {@link Dfp} with value 0. */
  82.     private final Dfp zero;

  83.     /** A {@link Dfp} with value 1. */
  84.     private final Dfp one;

  85.     /** A {@link Dfp} with value 2. */
  86.     private final Dfp two;

  87.     /** A {@link Dfp} with value &radic;2. */
  88.     private final Dfp sqr2;

  89.     /** A two elements {@link Dfp} array with value &radic;2 split in two pieces. */
  90.     private final Dfp[] sqr2Split;

  91.     /** A {@link Dfp} with value &radic;2 / 2. */
  92.     private final Dfp sqr2Reciprocal;

  93.     /** A {@link Dfp} with value &radic;3. */
  94.     private final Dfp sqr3;

  95.     /** A {@link Dfp} with value &radic;3 / 3. */
  96.     private final Dfp sqr3Reciprocal;

  97.     /** A {@link Dfp} with value &pi;. */
  98.     private final Dfp pi;

  99.     /** A {@link Dfp} for converting degrees to radians. */
  100.     private final Dfp degToRad;

  101.     /** A {@link Dfp} for converting radians to degrees. */
  102.     private final Dfp radToDeg;

  103.     /** A two elements {@link Dfp} array with value &pi; split in two pieces. */
  104.     private final Dfp[] piSplit;

  105.     /** A {@link Dfp} with value e. */
  106.     private final Dfp e;

  107.     /** A two elements {@link Dfp} array with value e split in two pieces. */
  108.     private final Dfp[] eSplit;

  109.     /** A {@link Dfp} with value ln(2). */
  110.     private final Dfp ln2;

  111.     /** A two elements {@link Dfp} array with value ln(2) split in two pieces. */
  112.     private final Dfp[] ln2Split;

  113.     /** A {@link Dfp} with value ln(5). */
  114.     private final Dfp ln5;

  115.     /** A two elements {@link Dfp} array with value ln(5) split in two pieces. */
  116.     private final Dfp[] ln5Split;

  117.     /** A {@link Dfp} with value ln(10). */
  118.     private final Dfp ln10;

  119.     /** Current rounding mode. */
  120.     private RoundingMode rMode;

  121.     /** IEEE 854-1987 signals. */
  122.     private int ieeeFlags;

  123.     /** Create a factory for the specified number of radix digits.
  124.      * <p>
  125.      * Note that since the {@link Dfp} class uses 10000 as its radix, each radix
  126.      * digit is equivalent to 4 decimal digits. This implies that asking for
  127.      * 13, 14, 15 or 16 decimal digits will really lead to a 4 radix 10000 digits in
  128.      * all cases.
  129.      * </p>
  130.      * @param decimalDigits minimal number of decimal digits.
  131.      */
  132.     public DfpField(final int decimalDigits) {
  133.         this(decimalDigits, true);
  134.     }

  135.     /** Create a factory for the specified number of radix digits.
  136.      * <p>
  137.      * Note that since the {@link Dfp} class uses 10000 as its radix, each radix
  138.      * digit is equivalent to 4 decimal digits. This implies that asking for
  139.      * 13, 14, 15 or 16 decimal digits will really lead to a 4 radix 10000 digits in
  140.      * all cases.
  141.      * </p>
  142.      * @param decimalDigits minimal number of decimal digits
  143.      * @param computeConstants if true, the transcendental constants for the given precision
  144.      * must be computed (setting this flag to false is RESERVED for the internal recursive call)
  145.      */
  146.     private DfpField(final int decimalDigits, final boolean computeConstants) {

  147.         this.radixDigits = (decimalDigits < 13) ? 4 : (decimalDigits + 3) / 4;
  148.         this.rMode       = RoundingMode.ROUND_HALF_EVEN;
  149.         this.ieeeFlags   = 0;
  150.         this.zero        = new Dfp(this, 0);
  151.         this.one         = new Dfp(this, 1);
  152.         this.two         = new Dfp(this, 2);

  153.         if (computeConstants) {
  154.             // set up transcendental constants
  155.             synchronized (DfpField.class) {

  156.                 // as a heuristic to circumvent Table-Maker's Dilemma, we set the string
  157.                 // representation of the constants to be at least 3 times larger than the
  158.                 // number of decimal digits, also as an attempt to really compute these
  159.                 // constants only once, we set a minimum number of digits
  160.                 computeStringConstants((decimalDigits < 67) ? 200 : (3 * decimalDigits));

  161.                 // set up the constants at current field accuracy
  162.                 sqr2           = new Dfp(this, sqr2String);
  163.                 sqr2Split      = split(sqr2String);
  164.                 sqr2Reciprocal = new Dfp(this, sqr2ReciprocalString);
  165.                 sqr3           = new Dfp(this, sqr3String);
  166.                 sqr3Reciprocal = new Dfp(this, sqr3ReciprocalString);
  167.                 pi             = new Dfp(this, piString);
  168.                 degToRad       = pi.divide(180.0);
  169.                 radToDeg       = pi.divide(180.0).reciprocal();
  170.                 piSplit        = split(piString);
  171.                 e              = new Dfp(this, eString);
  172.                 eSplit         = split(eString);
  173.                 ln2            = new Dfp(this, ln2String);
  174.                 ln2Split       = split(ln2String);
  175.                 ln5            = new Dfp(this, ln5String);
  176.                 ln5Split       = split(ln5String);
  177.                 ln10           = new Dfp(this, ln10String);

  178.             }
  179.         } else {
  180.             // dummy settings for unused constants
  181.             sqr2           = null;
  182.             sqr2Split      = null;
  183.             sqr2Reciprocal = null;
  184.             sqr3           = null;
  185.             sqr3Reciprocal = null;
  186.             pi             = null;
  187.             degToRad       = null;
  188.             radToDeg       = null;
  189.             piSplit        = null;
  190.             e              = null;
  191.             eSplit         = null;
  192.             ln2            = null;
  193.             ln2Split       = null;
  194.             ln5            = null;
  195.             ln5Split       = null;
  196.             ln10           = null;
  197.         }

  198.     }

  199.     /** Get the number of radix digits of the {@link Dfp} instances built by this factory.
  200.      * @return number of radix digits
  201.      */
  202.     public int getRadixDigits() {
  203.         return radixDigits;
  204.     }

  205.     /** Set the rounding mode.
  206.      *  If not set, the default value is {@link RoundingMode#ROUND_HALF_EVEN}.
  207.      * @param mode desired rounding mode
  208.      * Note that the rounding mode is common to all {@link Dfp} instances
  209.      * belonging to the current {@link DfpField} in the system and will
  210.      * affect all future calculations.
  211.      */
  212.     public void setRoundingMode(final RoundingMode mode) {
  213.         rMode = mode;
  214.     }

  215.     /** Get the current rounding mode.
  216.      * @return current rounding mode
  217.      */
  218.     public RoundingMode getRoundingMode() {
  219.         return rMode;
  220.     }

  221.     /** Get the IEEE 854 status flags.
  222.      * @return IEEE 854 status flags
  223.      * @see #clearIEEEFlags()
  224.      * @see #setIEEEFlags(int)
  225.      * @see #setIEEEFlagsBits(int)
  226.      * @see #FLAG_INVALID
  227.      * @see #FLAG_DIV_ZERO
  228.      * @see #FLAG_OVERFLOW
  229.      * @see #FLAG_UNDERFLOW
  230.      * @see #FLAG_INEXACT
  231.      */
  232.     public int getIEEEFlags() {
  233.         return ieeeFlags;
  234.     }

  235.     /** Clears the IEEE 854 status flags.
  236.      * @see #getIEEEFlags()
  237.      * @see #setIEEEFlags(int)
  238.      * @see #setIEEEFlagsBits(int)
  239.      * @see #FLAG_INVALID
  240.      * @see #FLAG_DIV_ZERO
  241.      * @see #FLAG_OVERFLOW
  242.      * @see #FLAG_UNDERFLOW
  243.      * @see #FLAG_INEXACT
  244.      */
  245.     public void clearIEEEFlags() {
  246.         ieeeFlags = 0;
  247.     }

  248.     /** Sets the IEEE 854 status flags.
  249.      * @param flags desired value for the flags
  250.      * @see #getIEEEFlags()
  251.      * @see #clearIEEEFlags()
  252.      * @see #setIEEEFlagsBits(int)
  253.      * @see #FLAG_INVALID
  254.      * @see #FLAG_DIV_ZERO
  255.      * @see #FLAG_OVERFLOW
  256.      * @see #FLAG_UNDERFLOW
  257.      * @see #FLAG_INEXACT
  258.      */
  259.     public void setIEEEFlags(final int flags) {
  260.         ieeeFlags = flags & (FLAG_INVALID | FLAG_DIV_ZERO | FLAG_OVERFLOW | FLAG_UNDERFLOW | FLAG_INEXACT);
  261.     }

  262.     /** Sets some bits in the IEEE 854 status flags, without changing the already set bits.
  263.      * <p>
  264.      * Calling this method is equivalent to call {@code setIEEEFlags(getIEEEFlags() | bits)}
  265.      * </p>
  266.      * @param bits bits to set
  267.      * @see #getIEEEFlags()
  268.      * @see #clearIEEEFlags()
  269.      * @see #setIEEEFlags(int)
  270.      * @see #FLAG_INVALID
  271.      * @see #FLAG_DIV_ZERO
  272.      * @see #FLAG_OVERFLOW
  273.      * @see #FLAG_UNDERFLOW
  274.      * @see #FLAG_INEXACT
  275.      */
  276.     public void setIEEEFlagsBits(final int bits) {
  277.         ieeeFlags |= bits & (FLAG_INVALID | FLAG_DIV_ZERO | FLAG_OVERFLOW | FLAG_UNDERFLOW | FLAG_INEXACT);
  278.     }

  279.     /** Makes a {@link Dfp} with a value of 0.
  280.      * @return a new {@link Dfp} with a value of 0
  281.      */
  282.     public Dfp newDfp() {
  283.         return new Dfp(this);
  284.     }

  285.     /** Create an instance from a byte value.
  286.      * @param x value to convert to an instance
  287.      * @return a new {@link Dfp} with the same value as x
  288.      */
  289.     public Dfp newDfp(final byte x) {
  290.         return new Dfp(this, x);
  291.     }

  292.     /** Create an instance from an int value.
  293.      * @param x value to convert to an instance
  294.      * @return a new {@link Dfp} with the same value as x
  295.      */
  296.     public Dfp newDfp(final int x) {
  297.         return new Dfp(this, x);
  298.     }

  299.     /** Create an instance from a long value.
  300.      * @param x value to convert to an instance
  301.      * @return a new {@link Dfp} with the same value as x
  302.      */
  303.     public Dfp newDfp(final long x) {
  304.         return new Dfp(this, x);
  305.     }

  306.     /** Create an instance from a double value.
  307.      * @param x value to convert to an instance
  308.      * @return a new {@link Dfp} with the same value as x
  309.      */
  310.     public Dfp newDfp(final double x) {
  311.         return new Dfp(this, x);
  312.     }

  313.     /** Copy constructor.
  314.      * @param d instance to copy
  315.      * @return a new {@link Dfp} with the same value as d
  316.      */
  317.     public Dfp newDfp(Dfp d) {
  318.         return new Dfp(d);
  319.     }

  320.     /** Create a {@link Dfp} given a String representation.
  321.      * @param s string representation of the instance
  322.      * @return a new {@link Dfp} parsed from specified string
  323.      */
  324.     public Dfp newDfp(final String s) {
  325.         return new Dfp(this, s);
  326.     }

  327.     /** Creates a {@link Dfp} with a non-finite value.
  328.      * @param sign sign of the Dfp to create
  329.      * @param nans code of the value, must be one of {@link Dfp#INFINITE},
  330.      * {@link Dfp#SNAN},  {@link Dfp#QNAN}
  331.      * @return a new {@link Dfp} with a non-finite value
  332.      */
  333.     public Dfp newDfp(final byte sign, final byte nans) {
  334.         return new Dfp(this, sign, nans);
  335.     }

  336.     /** Get the constant 0.
  337.      * @return a {@link Dfp} with value 0
  338.      */
  339.     @Override
  340.     public Dfp getZero() {
  341.         return zero;
  342.     }

  343.     /** Get the constant 1.
  344.      * @return a {@link Dfp} with value 1
  345.      */
  346.     @Override
  347.     public Dfp getOne() {
  348.         return one;
  349.     }

  350.     /** {@inheritDoc} */
  351.     @Override
  352.     public Class<Dfp> getRuntimeClass() {
  353.         return Dfp.class;
  354.     }

  355.     /** Get the constant 2.
  356.      * @return a {@link Dfp} with value 2
  357.      */
  358.     public Dfp getTwo() {
  359.         return two;
  360.     }

  361.     /** Get the constant &radic;2.
  362.      * @return a {@link Dfp} with value &radic;2
  363.      */
  364.     public Dfp getSqr2() {
  365.         return sqr2;
  366.     }

  367.     /** Get the constant &radic;2 split in two pieces.
  368.      * @return a {@link Dfp} with value &radic;2 split in two pieces
  369.      */
  370.     public Dfp[] getSqr2Split() {
  371.         return sqr2Split.clone();
  372.     }

  373.     /** Get the constant &radic;2 / 2.
  374.      * @return a {@link Dfp} with value &radic;2 / 2
  375.      */
  376.     public Dfp getSqr2Reciprocal() {
  377.         return sqr2Reciprocal;
  378.     }

  379.     /** Get the constant &radic;3.
  380.      * @return a {@link Dfp} with value &radic;3
  381.      */
  382.     public Dfp getSqr3() {
  383.         return sqr3;
  384.     }

  385.     /** Get the constant &radic;3 / 3.
  386.      * @return a {@link Dfp} with value &radic;3 / 3
  387.      */
  388.     public Dfp getSqr3Reciprocal() {
  389.         return sqr3Reciprocal;
  390.     }

  391.     /** Get the constant &pi;.
  392.      * @return a {@link Dfp} with value &pi;
  393.      */
  394.     public Dfp getPi() {
  395.         return pi;
  396.     }

  397.     /** Get the degrees to radians conversion factor.
  398.      * @return a {@link Dfp} for degrees to radians conversion factor
  399.      */
  400.     public Dfp getDegToRad() {
  401.         return degToRad;
  402.     }

  403.     /** Get the radians to degrees conversion factor.
  404.      * @return a {@link Dfp} for radians to degrees conversion factor
  405.      */
  406.     public Dfp getRadToDeg() {
  407.         return radToDeg;
  408.     }

  409.     /** Get the constant &pi; split in two pieces.
  410.      * @return a {@link Dfp} with value &pi; split in two pieces
  411.      */
  412.     public Dfp[] getPiSplit() {
  413.         return piSplit.clone();
  414.     }

  415.     /** Get the constant e.
  416.      * @return a {@link Dfp} with value e
  417.      */
  418.     public Dfp getE() {
  419.         return e;
  420.     }

  421.     /** Get the constant e split in two pieces.
  422.      * @return a {@link Dfp} with value e split in two pieces
  423.      */
  424.     public Dfp[] getESplit() {
  425.         return eSplit.clone();
  426.     }

  427.     /** Get the constant ln(2).
  428.      * @return a {@link Dfp} with value ln(2)
  429.      */
  430.     public Dfp getLn2() {
  431.         return ln2;
  432.     }

  433.     /** Get the constant ln(2) split in two pieces.
  434.      * @return a {@link Dfp} with value ln(2) split in two pieces
  435.      */
  436.     public Dfp[] getLn2Split() {
  437.         return ln2Split.clone();
  438.     }

  439.     /** Get the constant ln(5).
  440.      * @return a {@link Dfp} with value ln(5)
  441.      */
  442.     public Dfp getLn5() {
  443.         return ln5;
  444.     }

  445.     /** Get the constant ln(5) split in two pieces.
  446.      * @return a {@link Dfp} with value ln(5) split in two pieces
  447.      */
  448.     public Dfp[] getLn5Split() {
  449.         return ln5Split.clone();
  450.     }

  451.     /** Get the constant ln(10).
  452.      * @return a {@link Dfp} with value ln(10)
  453.      */
  454.     public Dfp getLn10() {
  455.         return ln10;
  456.     }

  457.     /** {@inheritDoc}
  458.      * <p>
  459.      * Two fields are considered equals if they have the same number
  460.      * of radix digits and the same rounding mode.
  461.      * </p>
  462.      */
  463.     @Override
  464.     public boolean equals(final Object other) {
  465.         if (this == other) {
  466.             return true;
  467.         } else if (other instanceof DfpField) {
  468.             DfpField rhs = (DfpField) other;
  469.             return getRadixDigits()  == rhs.getRadixDigits()  &&
  470.                    getRoundingMode() == rhs.getRoundingMode();
  471.         } else {
  472.             return false;
  473.         }
  474.     }

  475.     /** {@inheritDoc} */
  476.     @Override
  477.     public int hashCode() {
  478.         return 0xdf49a2ca ^ ((radixDigits << 16) & (rMode.ordinal() << 5) & ieeeFlags);
  479.     }

  480.     /** Breaks a string representation up into two {@link Dfp}'s.
  481.      * The split is such that the sum of them is equivalent to the input string,
  482.      * but has higher precision than using a single Dfp.
  483.      * @param a string representation of the number to split
  484.      * @return an array of two {@link Dfp Dfp} instances which sum equals a
  485.      */
  486.     private Dfp[] split(final String a) {
  487.       Dfp[] result = new Dfp[2];
  488.       boolean leading = true;
  489.       int sp = 0;
  490.       int sig = 0;

  491.       StringBuilder builder1 = new StringBuilder(a.length());

  492.       for (int i = 0; i < a.length(); i++) {
  493.         final char c = a.charAt(i);
  494.         builder1.append(c);

  495.         if (c >= '1' && c <= '9') {
  496.             leading = false;
  497.         }

  498.         if (c == '.') {
  499.           sig += (400 - sig) % 4;
  500.           leading = false;
  501.         }

  502.         if (sig == (radixDigits / 2) * 4) {
  503.           sp = i;
  504.           break;
  505.         }

  506.         if (c >= '0' &&c <= '9' && !leading) {
  507.             sig ++;
  508.         }
  509.       }

  510.       result[0] = new Dfp(this, builder1.substring(0, sp));

  511.       StringBuilder builder2 = new StringBuilder(a.length());
  512.       for (int i = 0; i < a.length(); i++) {
  513.           final char c = a.charAt(i);
  514.           if (c >= '0' && c <= '9' && i < sp) {
  515.               builder2.append('0');
  516.           } else {
  517.               builder2.append(c);
  518.         }
  519.       }

  520.       result[1] = new Dfp(this, builder2.toString());

  521.       return result;

  522.     }

  523.     /** Recompute the high precision string constants.
  524.      * @param highPrecisionDecimalDigits precision at which the string constants mus be computed
  525.      */
  526.     private static void computeStringConstants(final int highPrecisionDecimalDigits) {
  527.         synchronized (DfpField.class) {
  528.             if (sqr2String == null || sqr2String.length() < highPrecisionDecimalDigits - 3) {

  529.                 // recompute the string representation of the transcendental constants
  530.                 final DfpField highPrecisionField = new DfpField(highPrecisionDecimalDigits, false);
  531.                 final Dfp highPrecisionOne        = new Dfp(highPrecisionField, 1);
  532.                 final Dfp highPrecisionTwo        = new Dfp(highPrecisionField, 2);
  533.                 final Dfp highPrecisionThree      = new Dfp(highPrecisionField, 3);

  534.                 final Dfp highPrecisionSqr2 = highPrecisionTwo.sqrt();
  535.                 sqr2String           = highPrecisionSqr2.toString();
  536.                 sqr2ReciprocalString = highPrecisionOne.divide(highPrecisionSqr2).toString();

  537.                 final Dfp highPrecisionSqr3 = highPrecisionThree.sqrt();
  538.                 sqr3String           = highPrecisionSqr3.toString();
  539.                 sqr3ReciprocalString = highPrecisionOne.divide(highPrecisionSqr3).toString();

  540.                 piString   = computePi(highPrecisionOne, highPrecisionTwo, highPrecisionThree).toString();
  541.                 eString    = computeExp(highPrecisionOne, highPrecisionOne).toString();
  542.                 ln2String  = computeLn(highPrecisionTwo, highPrecisionOne, highPrecisionTwo).toString();
  543.                 ln5String  = computeLn(new Dfp(highPrecisionField, 5),  highPrecisionOne, highPrecisionTwo).toString();
  544.                 ln10String = computeLn(new Dfp(highPrecisionField, 10), highPrecisionOne, highPrecisionTwo).toString();

  545.             }
  546.         }
  547.     }

  548.     /** Compute &pi; using Jonathan and Peter Borwein quartic formula.
  549.      * @param one constant with value 1 at desired precision
  550.      * @param two constant with value 2 at desired precision
  551.      * @param three constant with value 3 at desired precision
  552.      * @return &pi;
  553.      */
  554.     private static Dfp computePi(final Dfp one, final Dfp two, final Dfp three) {

  555.         Dfp sqrt2   = two.sqrt();
  556.         Dfp yk      = sqrt2.subtract(one);
  557.         Dfp four    = two.add(two);
  558.         Dfp two2kp3 = two;
  559.         Dfp ak      = two.multiply(three.subtract(two.multiply(sqrt2)));

  560.         // The formula converges quartically. This means the number of correct
  561.         // digits is multiplied by 4 at each iteration! Five iterations are
  562.         // sufficient for about 160 digits, eight iterations give about
  563.         // 10000 digits (this has been checked) and 20 iterations more than
  564.         // 160 billions of digits (this has NOT been checked).
  565.         // So the limit here is considered sufficient for most purposes ...
  566.         for (int i = 1; i < 20; i++) {
  567.             final Dfp ykM1 = yk;

  568.             final Dfp y2         = yk.multiply(yk);
  569.             final Dfp oneMinusY4 = one.subtract(y2.multiply(y2));
  570.             final Dfp s          = oneMinusY4.sqrt().sqrt();
  571.             yk = one.subtract(s).divide(one.add(s));

  572.             two2kp3 = two2kp3.multiply(four);

  573.             final Dfp p = one.add(yk);
  574.             final Dfp p2 = p.multiply(p);
  575.             ak = ak.multiply(p2.multiply(p2)).subtract(two2kp3.multiply(yk).multiply(one.add(yk).add(yk.multiply(yk))));

  576.             if (yk.equals(ykM1)) {
  577.                 break;
  578.             }
  579.         }

  580.         return one.divide(ak);

  581.     }

  582.     /** Compute exp(a).
  583.      * @param a number for which we want the exponential
  584.      * @param one constant with value 1 at desired precision
  585.      * @return exp(a)
  586.      */
  587.     public static Dfp computeExp(final Dfp a, final Dfp one) {

  588.         Dfp y  = new Dfp(one);
  589.         Dfp py = new Dfp(one);
  590.         Dfp f  = new Dfp(one);
  591.         Dfp fi = new Dfp(one);
  592.         Dfp x  = new Dfp(one);

  593.         for (int i = 0; i < 10000; i++) {
  594.             x = x.multiply(a);
  595.             y = y.add(x.divide(f));
  596.             fi = fi.add(one);
  597.             f = f.multiply(fi);
  598.             if (y.equals(py)) {
  599.                 break;
  600.             }
  601.             py = new Dfp(y);
  602.         }

  603.         return y;

  604.     }


  605.     /** Compute ln(a).
  606.      *
  607.      *  Let f(x) = ln(x),
  608.      *
  609.      *  We know that f'(x) = 1/x, thus from Taylor's theorem we have:
  610.      *
  611.      *           -----          n+1         n
  612.      *  f(x) =   \           (-1)    (x - 1)
  613.      *           /          ----------------    for 1 &lt;= n &lt;= infinity
  614.      *           -----             n
  615.      *
  616.      *  or
  617.      *                       2        3       4
  618.      *                   (x-1)   (x-1)    (x-1)
  619.      *  ln(x) =  (x-1) - ----- + ------ - ------ + ...
  620.      *                     2       3        4
  621.      *
  622.      *  alternatively,
  623.      *
  624.      *                  2    3   4
  625.      *                 x    x   x
  626.      *  ln(x+1) =  x - -  + - - - + ...
  627.      *                 2    3   4
  628.      *
  629.      *  This series can be used to compute ln(x), but it converges too slowly.
  630.      *
  631.      *  If we substitute -x for x above, we get
  632.      *
  633.      *                   2    3    4
  634.      *                  x    x    x
  635.      *  ln(1-x) =  -x - -  - -  - - + ...
  636.      *                  2    3    4
  637.      *
  638.      *  Note that all terms are now negative.  Because the even powered ones
  639.      *  absorbed the sign.  Now, subtract the series above from the previous
  640.      *  one to get ln(x+1) - ln(1-x).  Note the even terms cancel out leaving
  641.      *  only the odd ones
  642.      *
  643.      *                             3     5      7
  644.      *                           2x    2x     2x
  645.      *  ln(x+1) - ln(x-1) = 2x + --- + --- + ---- + ...
  646.      *                            3     5      7
  647.      *
  648.      *  By the property of logarithms that ln(a) - ln(b) = ln (a/b) we have:
  649.      *
  650.      *                                3        5        7
  651.      *      x+1           /          x        x        x          \
  652.      *  ln ----- =   2 *  |  x  +   ----  +  ----  +  ---- + ...  |
  653.      *      x-1           \          3        5        7          /
  654.      *
  655.      *  But now we want to find ln(a), so we need to find the value of x
  656.      *  such that a = (x+1)/(x-1).   This is easily solved to find that
  657.      *  x = (a-1)/(a+1).
  658.      * @param a number for which we want the exponential
  659.      * @param one constant with value 1 at desired precision
  660.      * @param two constant with value 2 at desired precision
  661.      * @return ln(a)
  662.      */

  663.     public static Dfp computeLn(final Dfp a, final Dfp one, final Dfp two) {

  664.         int den = 1;
  665.         Dfp x = a.add(new Dfp(a.getField(), -1)).divide(a.add(one));

  666.         Dfp y = new Dfp(x);
  667.         Dfp num = new Dfp(x);
  668.         Dfp py = new Dfp(y);
  669.         for (int i = 0; i < 10000; i++) {
  670.             num = num.multiply(x);
  671.             num = num.multiply(x);
  672.             den += 2;
  673.             Dfp t = num.divide(den);
  674.             y = y.add(t);
  675.             if (y.equals(py)) {
  676.                 break;
  677.             }
  678.             py = new Dfp(y);
  679.         }

  680.         return y.multiply(two);

  681.     }

  682.     /** Get extended field for accuracy conversion.
  683.      * @param digitsFactor multiplication factor for number of digits
  684.      * @param computeConstants if true, the transcendental constants for the given precision
  685.      * must be computed (setting this flag to false is RESERVED for the internal recursive call)
  686.      * @return field with extended precision
  687.      * @since 1.7
  688.      */
  689.     public DfpField getExtendedField(final int digitsFactor, final boolean computeConstants) {
  690.         final int oldDecimalDigits = getRadixDigits() * 4;
  691.         return new DfpField(oldDecimalDigits * digitsFactor, computeConstants);
  692.     }

  693. }