Hi,

the attached patch implements java.lang.StrictMath#cbrt, but I'm
actually quite ashamed to post it: I'm not very knowledgeable about
floating point arithmetic, so I just followed the implementation in
fdlibm (www.netlib.org/fdlibm). Unfortunately this library does some
weird manipulations of the bits of a double, which I simply mimicked in
java.

        Cheers,
                Carsten



2006-07-13  Carsten Neumann  <[EMAIL PROTECTED]>

        * StrictMath.java (cbrt): New public method.
        (doubleToLowWord): New helper method.
        (doubleToHighWord): Likewise.
        (doubleToWords): Likewise.
        (wordsToDouble): Likewise.
        (wordsToDouble): Likewise.

Index: java/lang/StrictMath.java
===================================================================
RCS file: /sources/classpath/classpath/java/lang/StrictMath.java,v
retrieving revision 1.8
diff -u -r1.8 StrictMath.java
--- java/lang/StrictMath.java	15 Mar 2006 21:57:44 -0000	1.8
+++ java/lang/StrictMath.java	13 Jul 2006 17:29:15 -0000
@@ -633,6 +633,147 @@
   }
 
   /**
+   * Helper method to obtain the lower 32 bits of a double in IEEE 754
+   * representation.
+   */
+  private static int doubleToLowWord(double x)
+  {
+    return (int) (Double.doubleToLongBits(x) & 0x00000000ffffffffL);
+  }
+
+  /**
+   * Helper method to obtain the upper 32 bits of a double in IEEE 754
+   * representation.
+   */
+  private static int doubleToHighWord(double x)
+  {
+    return (int) ((Double.doubleToLongBits(x) & 0xffffffff00000000L ) >> 32);
+  }
+
+  /**
+   * Helper method to obtain the upper and lower 32 bits of a double
+   * in IEEE 754 representation.
+   */
+  private static void doubleToWords(double x, int[] words)
+  {
+    long longBits = Double.doubleToLongBits(x);
+
+    words[0] = (int) (longBits & 0x00000000ffffffffL);
+    words[1] = (int) ((longBits & 0xffffffff00000000L) >> 32);
+  }
+
+  /**
+   * Helper method to construct a double from the upper and lower 32
+   * bits in words[1] and words[0] resprectively.
+   */
+  private static double wordsToDouble(int[] words)
+  {
+    return wordsToDouble(words[0], words[1]);
+  }
+
+  /**
+   * Helper method to construct a double from the upper and lower 32
+   * bits in highWord and lowWord resprectively.
+   */
+  private static double wordsToDouble(int lowWord, int highWord)
+  {
+    return Double.longBitsToDouble((((long) highWord) << 32) | ((long) lowWord));
+  }
+
+  /**
+   * Returns the cube root of <code>x</code>. The sign of the cube root
+   * is equal to the sign of the sign of <code>x</code>.
+   * Special cases:
+   * <ul>
+   * <li>If the argument is NaN, the result is NaN</li>
+   * <li>If the argument is positive infinity, the result is positive
+   * infinity.</li>
+   * <li>If the argument is negative infinity, the result is negative
+   * infinity.</li>
+   * <li>If the argument is zero, the result is zero with the same
+   * sign as the argument.</li>
+   * </ul>
+   *
+   * @param x the number to take the cube root of
+   * @return the cube root of <code>x</code>
+   * @see #sqrt(double)
+   * @since 1.5
+   */
+  public static double cbrt(double x)
+  {
+    boolean negative = (x < 0);
+    double r;
+    double s;
+    double t = 0.0;
+    double w;
+    int    hx;
+    int[]  words = new int[2];
+
+    if (negative)
+      {
+	x = -x;
+      }
+
+    // handle the special cases
+    if (x != x)
+      {
+	return Double.NaN;
+      }
+    else if (x == Double.POSITIVE_INFINITY)
+      {
+	return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+      }
+    else if (x == 0)
+      {
+	return negative ? - 0.0 : 0.0;
+      }
+
+    hx = doubleToHighWord(x);
+
+    if (hx < 0x00100000)   // subnormal number
+      {
+	t = TWO_54;
+	t *= x;
+
+	// __HI(t)=__HI(t)/3+B2;
+	doubleToWords(t, words);
+	words[1] = words[1] / 3 + CBRT_B2;
+	t = wordsToDouble(words);
+      }
+    else
+      {
+	// __HI(t)=hx/3+B1;
+	doubleToWords(t, words);
+	words[1] = hx / 3 + CBRT_B1;
+	t = wordsToDouble(words);
+      }
+
+    // new cbrt to 23 bits
+    r =  t * t / x;
+    s =  CBRT_C + r * t;
+    t *= CBRT_G + CBRT_F / (s + CBRT_E + CBRT_D / s);
+
+    // chopped to 20 bits and make it larger than cbrt(x)
+    doubleToWords(t, words);
+
+    // __LO(t)=0;
+    // __HI(t)+=0x00000001;
+    words[0] =  0;
+    words[1] += 1;
+
+    t = wordsToDouble(words);
+
+    // one step newton iteration to 53 bits with error less than 0.667 ulps
+    s = t * t;		    // t * t is exact
+    r = x / s;
+    w = t + t;
+    r = (r - t) / (w + r);  // r - s is exact
+    t = t + t * r;
+
+    return negative ? -t : t;
+  }
+
+  /**
    * Take <em>e</em><sup>a</sup>.  The opposite of <code>log()</code>. If the
    * argument is NaN, the result is NaN; if the argument is positive infinity,
    * the result is positive infinity; and if the argument is negative
@@ -1429,6 +1570,23 @@
     AT10 = 0.016285820115365782; // Long bits 0x3f90ad3ae322da11L.
 
   /**
+   * Constants for computing [EMAIL PROTECTED] #cbrt(double)}.
+   */
+  private static final int
+    CBRT_B1 = 715094163, // B1 = (682-0.03306235651)*2**20
+    CBRT_B2 = 696219795; // B2 = (664-0.03306235651)*2**20
+
+  /**
+   * Constants for computing [EMAIL PROTECTED] #cbrt(double)}.
+   */
+  private static final double
+    CBRT_C =  5.42857142857142815906e-01, // Long bits  0x3fe15f15f15f15f1L
+    CBRT_D = -7.05306122448979611050e-01, // Long bits  0xbfe691de2532c834L
+    CBRT_E =  1.41428571428571436819e+00, // Long bits  0x3ff6a0ea0ea0ea0fL
+    CBRT_F =  1.60714285714285720630e+00, // Long bits  0x3ff9b6db6db6db6eL
+    CBRT_G =  3.57142857142857150787e-01; // Long bits  0x3fd6db6db6db6db7L
+
+  /**
    * Helper function for reducing an angle to a multiple of pi/2 within
    * [-pi/4, pi/4].
    *

Reply via email to