JDK-4347132 : Want Math.cbrt() function for cube root
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.3.0,1.4.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,linux
  • CPU: generic,x86
  • Submitted: 2000-06-21
  • Updated: 2017-05-16
  • Resolved: 2003-05-16
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 tigerFixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description

Name: sl110371			Date: 06/21/2000


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)


It would be nice to have a Math.cbrt() function (cube root of a real number),
for those of us involved in numerical/graphics programming.

Looking at the JDK source code (publically available), there is a cbrt() native
method defined in the library but it is unused.  The Math class would need to
be altered to call this method, similar to the way it invokes sqrt().

Math.pow(x, 1/3.0) can be used to compute a cube root, but is much less
efficient than a true cube root function.  Also, special care must be taken for
negative values of x.  (See work-around).
(Review ID: 105412) 
======================================================================

Name: rmT116609			Date: 02/19/2002


DESCRIPTION OF THE PROBLEM :

It would be nice to have a cubic root method in java.lang.Math, for example :

public static double cbrt (double x)

This mathematical function is defined for all real values regardless of their sign, but computing it with Math.pow cannot be done directly for non positive values. We have to end up with this kind of code :

if (x >= 0)
  c = Math.pow (x, 1.0 / 3.0);
else
  c = -Math.pow (-x, 1.0 / 3.0);

(Review ID: 139858)
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger FIXED IN: tiger INTEGRATED IN: tiger tiger-b07
14-06-2004

WORK AROUND Name: sl110371 Date: 06/21/2000 public double cbrt(double x) { // cube root function // Cube root of negative number is negative // Take cbrt of magnitude then negate result // Need to do this as pow returns complex (NaN) for negative x, which // is a technically correct answer, but not the one we want if(x < 0) return -Math.pow(-x, ONETHIRD); return Math.pow(x, ONETHIRD); } ======================================================================
11-06-2004

SUGGESTED FIX gative of the cube root of that value's magnitude. > * Special cases: > * > * <ul> > * > * <li>If the argument is NaN, then the result is NaN. > * > * <li>If the argument is infinite, then the result is an infinity > * with the same sign as the argument. > * > * <li>If the argument is zero, then the result is a zero with the > * same sign as the argument. > * > * </ul> > * > * @param a a value. > * @return the cube root of <code>a</code>. > * @since 1.5 > */ > public static native double cbrt(double a); > > /** 529,539c579,589 < * <p> < * When this method is first called, it creates a single new < * pseudorandom-number generator, exactly as if by the expression < * <blockquote><pre>new java.util.Random</pre></blockquote> < * This new pseudorandom-number generator is used thereafter for all < * calls to this method and is used nowhere else. < * <p> < * This method is properly synchronized to allow correct use by more < * than one thread. However, if many threads need to generate < * pseudorandom numbers at a great rate, it may reduce contention for < * each thread to have its own pseudorandom number generator. --- > * > * <p>When this method is first called, it creates a single new > * pseudorandom-number generator, exactly as if by the expression > * <blockquote><pre>new java.util.Random</pre></blockquote> This > * new pseudorandom-number generator is used thereafter for all > * calls to this method and is used nowhere else. > * > * <p>This method is properly synchronized to allow correct use by > * more than one thread. However, if many threads need to generate > * pseudorandom numbers at a great rate, it may reduce contention > * for each thread to have its own pseudorandom number generator. 554,558c604,608 < * <p> < * Note that if the argument is equal to the value of < * <code>Integer.MIN_VALUE</code>, the most negative representable < * <code>int</code> value, the result is that same value, which is < * negative. --- > * > * <p>Note that if the argument is equal to the value of > * <code>Integer.MIN_VALUE</code>, the most negative representable > * <code>int</code> value, the result is that same value, which is > * negative. 572,576c622,626 < * <p> < * Note that if the argument is equal to the value of < * <code>Long.MIN_VALUE</code>, the most negative representable < * <code>long</code> value, the result is that same value, which is < * negative. --- > * > * <p>Note that if the argument is equal to the value of > * <code>Long.MIN_VALUE</code>, the most negative representable > * <code>long</code> value, the result is that same value, which > * is negative. 778a829,923 > /** > * Returns the size of an ulp of the argument. An ulp of a > * <code>double</code> value is the positive distance between this > * floating-point value and the <code>double</code> value next > * larger in magnitude. Note that for non-NaN <i>x</i>, > * <code>ulp(-<i>x</i>) == ulp(<i>x</i>)</code>. > * > * <p>Special Cases: > * <ul> > * <li> If the argument is NaN, then the result is NaN. > * <li> If the argument is positive or negative infinity, then the > * result is positive infinity. > * <li> If the argument is positive or negative zero, then the result is > * <code>Double.MIN_VALUE</code>. > * <li> If the argument is &plusmn;<code>Double.MAX_VALUE</code>, then > * the result is equal to 2<sup>971</sup>. > * </ul> > * > * @param d the floating-point value whose ulp is to be returned > * @return the size of an ulp of the argument > * @author Joseph D. Darcy > * @since 1.5 > */ > public static double ulp(double d) { > return sun.misc.FpUtils.ulp(d); > } > > /** > * Returns the size of an ulp of the argument. An ulp of a > * <code>float</code> value is the positive distance between this > * floating-point value and the <code>float</code> value next > * larger in magnitude. Note that for non-NaN <i>x</i>, > * <code>ulp(-<i>x</i>) == ulp(<i>x</i>)</code>. > * > * <p>Special Cases: > * <ul> > * <li> If the argument is NaN, then the result is NaN. > * <li> If the argument is positive or negative infinity, then the > * result is positive infinity. > * <li> If the argument is positive or negative zero, then the result is > * <code>Float.MIN_VALUE</code>. > * <li> If the argument is &plusmn;<code>Float.MAX_VALUE</code>, then > * the result is equal to 2<sup>104</sup>. > * </ul> > * > * @param f the floating-point value whose ulp is to be returned > * @return the size of an ulp of the argument > * @author Joseph D. Darcy > * @since 1.5 > */ > public static float ulp(float f) { > return sun.misc.FpUtils.ulp(f); > } > > /** > * Returns the signum function of the argument; zero if the argument > * is zero, 1.0 if the argument is greater than zero, -1.0 if the > * argument is less than zero. > * > * <p>Special Cases: > * <ul> > * <li> If the argument is NaN, then the result is NaN. > * <li> If the argument is positive zero or negative zero, then the > * result is the same as the argument. > * </ul> > * > * @param d the floating-point value whose signum is to be returned > * @return the signum function of the argument > * @author Joseph D. Darcy > * @since 1.5 > */ > public static double signum(double d) { > return sun.misc.FpUtils.signum(d); > } > > /** > * Returns the signum function of the argument; zero if the argument > * is zero, 1.0f if the argument is greater than zero, -1.0f if the > * argument is less than zero. > * > * <p>Special Cases: > * <ul> > * <li> If the argument is NaN, then the result is NaN. > * <li> If the argument is positive zero or negative zero, then the > * result is the same as the argument. > * </ul> > * > * @param f the floating-point value whose signum is to be returned > * @return the signum function of the argument > * @author Joseph D. Darcy > * @since 1.5 > */ > public static float signum(float f) { > return sun.misc.FpUtils.signum(f); > }
11-06-2004

SUGGESTED FIX Directory make/java/java sccs sccsdiff -r1.51 -r1.52 mapfile-vers ------- mapfile-vers ------- 141a142 > Java_java_lang_StrictMath_log10; 145a147 > Java_java_lang_StrictMath_cbrt; Directory src/share/native/java/lang/fdlibm/include sccs sccsdiff -r1.8 -r1.9 jfdlibm.h ------- jfdlibm.h ------- 26a27 > #define log10 jlog10 29a31 > #define cbrt jcbrt Directory src/share/native/java/lang sccs sccsdiff -r1.51 -r1.52 StrictMath.c ------- StrictMath.c ------- 61a62,67 > Java_java_lang_StrictMath_log10(JNIEnv *env, jclass unused, jdouble d) > { > return (jdouble) jlog10((double)d); > } > > JNIEXPORT jdouble JNICALL 66a73,78 > JNIEXPORT jdouble JNICALL > Java_java_lang_StrictMath_cbrt(JNIEnv *env, jclass unused, jdouble d) > { > return (jdouble) jcbrt((double)d); > } > Directory src/share/classes/java/lang ------- Math.java ------- 4c4 < * Copyright 2003 Sun Microsystems, Inc. All rights reserved. --- > * Copyright 2002 Sun Microsystems, Inc. All rights reserved. 16,17c16,17 < * <p> < * Unlike some of the numeric methods of class --- > * > * <p>Unlike some of the numeric methods of class 23,24c23,24 < * <p> < * By default many of the <code>Math</code> methods simply call --- > * > * <p>By default many of the <code>Math</code> methods simply call 32,33c32,33 < * <p> < * The quality of implementation specifications concern two --- > * > * <p>The quality of implementation specifications concern two 93,95c93,95 < * <p> < * A result must be within 1 ulp of the correctly rounded result. Results < * must be semi-monotonic. --- > * > * <p>A result must be within 1 ulp of the correctly rounded > * result. Results must be semi-monotonic. 108,110c108,110 < * <p> < * A result must be within 1 ulp of the correctly rounded result. Results < * must be semi-monotonic. --- > * > * <p>A result must be within 1 ulp of the correctly rounded > * result. Results must be semi-monotonic. 125,127c125,127 < * <p> < * A result must be within 1 ulp of the correctly rounded result. Results < * must be semi-monotonic. --- > * > * <p>A result must be within 1 ulp of the correctly rounded > * result. Results must be semi-monotonic. 143,145c143,145 < * <p> < * A result must be within 1 ulp of the correctly rounded result. Results < * must be semi-monotonic. --- > * > * <p>A result must be within 1 ulp of the correctly rounded > * result. Results must be semi-monotonic. 159,161c159,161 < * <p> < * A result must be within 1 ulp of the correctly rounded result. Results < * must be semi-monotonic. --- > * > * <p>A result must be within 1 ulp of the correctly rounded > * result. Results must be semi-monotonic. 176,178c176,178 < * <p> < * A result must be within 1 ulp of the correctly rounded result. Results < * must be semi-monotonic. --- > * > * <p>A result must be within 1 ulp of the correctly rounded > * result. Results must be semi-monotonic. 225,227c225,227 < * <p> < * A result must be within 1 ulp of the correctly rounded result. Results < * must be semi-monotonic. --- > * > * <p>A result must be within 1 ulp of the correctly rounded > * result. Results must be semi-monotonic. 246,248c246,248 < * <p> < * A result must be within 1 ulp of the correctly rounded result. Results < * must be semi-monotonic. --- > * > * <p>A result must be within 1 ulp of the correctly rounded > * result. Results must be semi-monotonic. 250c250 < * @param a a number greater than <code>0.0</code>. --- > * @param a a value 258a259,283 > * Returns the base 10 logarithm of a <code>double</code> value. > * Special cases: > * > * <ul><li>If the argument is NaN or less than zero, then the result > * is NaN. > * <li>If the argument is positive infinity, then the result is > * positive infinity. > * <li>If the argument is positive zero or negative zero, then the > * result is negative infinity. > * <li> If the argument is equal to 10<sup><i>n</i></sup> for > * integer <i>n</i>, then the result is <i>n</i>. > * </ul> > * > * <p>A result must be within 1 ulp of the correctly rounded > * result. Results must be semi-monotonic. > * > * @param a a value > * @return the base 10 logarithm of <code>a</code>. > * @since 1.5 > */ > public static double log10(double a) { > return StrictMath.log10(a); // default impl. delegates to StrictMath > } > > /** 283a309 > 284a311,340 > * Returns the cube root of a <code>double</code> value. For > * positive finite <code>x</code>, <code>cbrt(-x) == > * -cbrt(x)</code>; that is, the cube root of a negative value is > * the negative of the cube root of that value's magnitude. > * > * Special cases: > * > * <ul> > * > * <li>If the argument is NaN, then the result is NaN. > * > * <li>If the argument is infinite, then the result is an infinity > * with the same sign as the argument. > * > * <li>If the argument is zero, then the result is a zero with the > * same sign as the argument. > * > * </ul> > * > * A result must be within 1 ulp of the correctly rounded result. > * > * @param a a value. > * @return the cube root of <code>a</code>. > * @since 1.5 > */ > public static double cbrt(double a) { > return StrictMath.cbrt(a); > } > > /** 411,413c467,469 < * <p> < * A result must be within 2 ulps of the correctly rounded result. Results < * must be semi-monotonic. --- > * > * <p>A result must be within 2 ulps of the correctly rounded > * result. Results must be semi-monotonic. 618,628c674,684 < * <p> < * When this method is first called, it creates a single new < * pseudorandom-number generator, exactly as if by the expression < * <blockquote><pre>new java.util.Random</pre></blockquote> < * This new pseudorandom-number generator is used thereafter for all < * calls to this method and is used nowhere else. < * <p> < * This method is properly synchronized to allow correct use by more < * than one thread. However, if many threads need to generate < * pseudorandom numbers at a great rate, it may reduce contention for < * each thread to have its own pseudorandom-number generator. --- > * > * <p>When this method is first called, it creates a single new > * pseudorandom-number generator, exactly as if by the expression > * <blockquote><pre>new java.util.Random</pre></blockquote> This > * new pseudorandom-number generator is used thereafter for all > * calls to this method and is used nowhere else. > * > * <p>This method is properly synchronized to allow correct use by > * more than one thread. However, if many threads need to generate > * pseudorandom numbers at a great rate, it may reduce contention > * for each thread to have its own pseudorandom-number generator. 643,647c699,703 < * <p> < * Note that if the argument is equal to the value of < * <code>Integer.MIN_VALUE</code>, the most negative representable < * <code>int</code> value, the result is that same value, which is < * negative. --- > * > * <p>Note that if the argument is equal to the value of > * <code>Integer.MIN_VALUE</code>, the most negative representable > * <code>int</code> value, the result is that same value, which is > * negative. 661,665c717,721 < * <p> < * Note that if the argument is equal to the value of < * <code>Long.MIN_VALUE</code>, the most negative representable < * <code>long</code> value, the result is that same value, which is < * negative. --- > * > * <p>Note that if the argument is equal to the value of > * <code>Long.MIN_VALUE</code>, the most negative representable > * <code>long</code> value, the result is that same value, which > * is negative. 867a924,1018 > /** > * Returns the size of an ulp of the argument. An ulp of a > * <code>double</code> value is the positive distance between this > * floating-point value and the <code>double</code> value next > * larger in magnitude. Note that for non-NaN <i>x</i>, > * <code>ulp(-<i>x</i>) == ulp(<i>x</i>)</code>. > * > * <p>Special Cases: > * <ul> > * <li> If the argument is NaN, then the result is NaN. > * <li> If the argument is positive or negative infinity, then the > * result is positive infinity. > * <li> If the argument is positive or negative zero, then the result is > * <code>Double.MIN_VALUE</code>. > * <li> If the argument is &plusmn;<code>Double.MAX_VALUE</code>, then > * the result is equal to 2<sup>971</sup>. > * </ul> > * > * @param d the floating-point value whose ulp is to be returned > * @return the size of an ulp of the argument > * @author Joseph D. Darcy > * @since 1.5 > */ > public static double ulp(double d) { > return sun.misc.FpUtils.ulp(d); > } > > /** > * Returns the size of an ulp of the argument. An ulp of a > * <code>float</code> value is the positive distance between this > * floating-point value and the <code>float</code> value next > * larger in magnitude. Note that for non-NaN <i>x</i>, > * <code>ulp(-<i>x</i>) == ulp(<i>x</i>)</code>. > * > * <p>Special Cases: > * <ul> > * <li> If the argument is NaN, then the result is NaN. > * <li> If the argument is positive or negative infinity, then the > * result is positive infinity. > * <li> If the argument is positive or negative zero, then the result is > * <code>Float.MIN_VALUE</code>. > * <li> If the argument is &plusmn;<code>Float.MAX_VALUE</code>, then > * the result is equal to 2<sup>104</sup>. > * </ul> > * > * @param f the floating-point value whose ulp is to be returned > * @return the size of an ulp of the argument > * @author Joseph D. Darcy > * @since 1.5 > */ > public static float ulp(float f) { > return sun.misc.FpUtils.ulp(f); > } > > /** > * Returns the signum function of the argument; zero if the argument > * is zero, 1.0 if the argument is greater than zero, -1.0 if the > * argument is less than zero. > * > * <p>Special Cases: > * <ul> > * <li> If the argument is NaN, then the result is NaN. > * <li> If the argument is positive zero or negative zero, then the > * result is the same as the argument. > * </ul> > * > * @param d the floating-point value whose signum is to be returned > * @return the signum function of the argument > * @author Joseph D. Darcy > * @since 1.5 > */ > public static double signum(double d) { > return sun.misc.FpUtils.signum(d); > } > > /** > * Returns the signum function of the argument; zero if the argument > * is zero, 1.0f if the argument is greater than zero, -1.0f if the > * argument is less than zero. > * > * <p>Special Cases: > * <ul> > * <li> If the argument is NaN, then the result is NaN. > * <li> If the argument is positive zero or negative zero, then the > * result is the same as the argument. > * </ul> > * > * @param f the floating-point value whose signum is to be returned > * @return the signum function of the argument > * @author Joseph D. Darcy > * @since 1.5 > */ > public static float signum(float f) { > return sun.misc.FpUtils.signum(f); > } ------- StrictMath.java ------- 4c4 < * Copyright 2003 Sun Microsystems, Inc. All rights reserved. --- > * Copyright 2002 Sun Microsystems, Inc. All rights reserved. 16,18c16,18 < * <p> < * To help ensure portability of Java programs, the definitions of < * many of the numeric functions in this package require that they --- > * > * <p>To help ensure portability of Java programs, the definitions of > * some of the numeric functions in this package require that they 26,27c26,27 < * <p> < * The network library may be found on the World Wide Web at: --- > * > * <p>The network library may be found on the World Wide Web at: 31,37c31,42 < * <p> < * The Java math library is defined with respect to the version of < * <code>fdlibm</code> dated January 4, 1995. Where < * <code>fdlibm</code> provides more than one definition for a < * function (such as <code>acos</code>), use the "IEEE 754 core < * function" version (residing in a file whose name begins with < * the letter <code>e</code>). --- > * > * <p>The Java math library is defined with respect to the version of > * <code>fdlibm</code> dated January 4, 1995. Where > * <code>fdlibm</code> provides more than one definition for a > * function (such as <code>acos</code>), use the "IEEE 754 core > * function" version (residing in a file whose name begins with the > * letter <code>e</code>). The methods which require > * <code>fdlibm</code> semantics are <code>sin</code>, > * <code>cos</code>, <code>tan</code>, <code>asin</code>, > * <code>acos</code>, <code>atan</code>, <code>exp</code>, > * <code>log</code>, <code>log10</code>, <code>cbrt</code>, > * <code>atan2</code>, and <code>pow</code>. 44c49 < public final strictfp class StrictMath { --- > public final class StrictMath { 187c192 < * @param a a number greater than <code>0.0</code>. --- > * @param a a value 192a198 > 193a200,219 > * Returns the base 10 logarithm of a <code>double</code> value. > * Special cases: > * > * <ul><li>If the argument is NaN or less than zero, then the result > * is NaN. > * <li>If the argument is positive infinity, then the result is > * positive infinity. > * <li>If the argument is positive zero or negative zero, then the > * result is negative infinity. > * <li> If the argument is equal to 10<sup><i>n</i></sup> for > * integer <i>n</i>, then the result is <i>n</i>. > * </ul> > * > * @param a a value > * @return the base 10 logarithm of <code>a</code>. > * @since 1.5 > */ > public static native double log10(double a); > > /** 207d232 < * <!--@return the value of &radic;&nbsp;<code>a</code>.--> 212a238,262 > * Returns the cube root of a <code>double</code> value. For > * positive finite <code>x</code>, <code>cbrt(-x) == > * -cbrt(x)</code>; that is, the cube root of a negative value is > * the ne
11-06-2004

EVALUATION This is a useful method that should be included in Java's math library. A true cube root method will return somewhat different answers than pow(x, 1.0/3.0) since 1/3 is not exactly representable as a floating-point value. joe.darcy@eng 2001-06-25
25-06-2001