/************************************************************************** * Parts copyright (c) 2001 by Punch Telematix. All rights reserved. * * Parts copyright (c) 2009 by Chris Gray, /k/ Embedded Java Solutions. * * All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1. Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * 3. Neither the name of Punch Telematix or of /k/ Embedded Java Solutions* * nor the names of other contributors may be used to endorse or promote* * products derived from this software without specific prior written * * permission. * * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * * IN NO EVENT SHALL PUNCH TELEMATIX, /K/ EMBEDDED JAVA SOLUTIONS OR OTHER * * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ package java.lang; /** ** Class <b>java.lang.Math</b> is a little odd. It is a utility class which ** implements basic mathematical functions similar to those found in ** the standard libraries of many languages. The printed documentation ** for the class (<i>The Java Class Libraries</i>) refers the reader to the ** <i>Java Language Specification</i> (1st Ed.!) for the semantics of the ** various methods. Curiously, the JLS in turn refers to a C library ** (<tt>fdlibm</tt>), with a remark to the effect that the C code is to ** be interpreted with Java semantics. Curious, because ** <ul> ** <li>the semantics of C are less well-defined than those of Java, ** particularly in the area of floating-point arithmetic. It is ** a strange idea to define the semantics of a relatively well-defined ** language in terms of a less well-defined language. ** <li>in the name of WORA (write once, run anywhere), the semantics ** are defined in terms of a reference implementation (the C library ** already mentioned). This seems to imply that it is more important ** that the results of a calculation be consistent across implementations ** than that they be correct: arguably this is taking WORA a little too ** far. ** </ul> ** ** <p>The implementations which follow are believed by the authors to be ** roughly as correct, mathematically speaking, as the <tt>fdlibm</tt> ** code (sometimes more so, sometimes less), based on our own tests; ** we do not however claim that they are bit-compatible with <tt>fdlibm</tt> ** or any other library, and here as elsewhere ANY EXPRESS OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** <p>We have also tried to avoid including here any material on which ** copyright or patent rights might be claimed by any third party: ** <ul> ** <li>The algorithms for sqrt, sin, cos, tan, and exp are based on ** Newton's approximation and Taylor series from way back when, coded ** from scratch. The string<->number conversions are also straight off ** the top of [CG]'s head. ** <li>Other algorithms draw on work performed for the United ** States Air Force by Col. William A. Whitaker and Lt. Tim Eicholz, ** and stated by them to be released into the public domain. ** We therefore believe these algorithms (and their expression ** here) to be unencumbered. ** </ul> ** ** <p>It follows that the Copyright notice above should be read not ** as claiming proprietary rights in the expression of these ideas, ** but rather as affirming our belief that these ideas are there for ** everybody to use. ** ** <p>Finally, a riddle and its answer: ** <blockquote> ** Q: When is a number not equal to itself? <br> ** A: When it's Not a Number. ** </blockquote> ** <p><author>Chris Gray, ACUNIA VM Architect, August 21 2001</author> */ public final class Math { static { init(); } private static native void init(); /** ** this constructor is added to prevent the compiler from adding a default constructor. ** Since the default constructor is public, it would be possible todo: Math m = new Math(); ** Such an Object would be useless ... */ private Math(){} public static final double E = 2.7182818284590452354; public static final double PI = 3.14159265358979323846; /** ** A double-precision IEE754 number looks like this: ** Bit 64 63 .. 52 (implied) 51 .. 0 ** sign exp+3ff 0.1 rest of mantissa ** Bitmask <tt>d_signbit</tt> isolates the sign bit. */ private static final long d_signbit = 0x8000000000000000L; /** ** Bitmask <tt>d_expbits</tt> isolates the exponent field. */ private static final long d_expbits = 0x7ff0000000000000L; /** ** The exponent is offset by 1023 (0x3ff). */ private static final long d_offsetbits = 0x3ff0000000000000L; /** ** Bitmask <tt>d_mantbits</tt> isolates the mantissa field. */ private static final long d_mantbits = 0x000fffffffffffffL; /** ** A single-precision IEE754 number looks like this: ** Bit 32 31 .. 23 (implied) 22 .. 0 ** sign exp+3ff 0.1 rest of mantissa ** Bitmask <tt>f_signbit</tt> isolates the sign bit. */ private static final int f_signbit = 0x80000000; /** ** Bitmask <tt>f_expbits</tt> isolates the exponent field. */ private static final int f_expbits = 0x7f800000; /** ** One revolution. */ private static final double twopi = Math.PI * 2.0; /** ** One right angle. */ private static final double halfpi = Math.PI * 0.5; /** ** Half a right angle (45 degrees). */ private static final double quarterpi = Math.PI * 0.25; /** ** The square root of the smallest double-precision number distinguishable ** from zero (more or less). Within this distance of zero all functions ** can be treated as linear, 'coz a quadratic term would be negligible. */ private static final double tiny = Double.longBitsToDouble(0x1ff0000000000000L); /** ** Trying to calculate the exponent of anything bigger than this would be foolish. */ private static final double logbignum = 709.782712893384; // log(Double.MAX_VALUE) /** ** The (pseudo-)random number generator used by random(). */ private static java.util.Random RNG = null; /** ** The square root algorithm is a pretty dumb Newton-Raphson thang. ** Blame this on no one but me [CG]. */ public static double sqrt(double arg) { /* ** Eliminate tiresome cases. */ if ((arg < 0) || (arg != arg)) { return Double.NaN; } if (arg == Double.POSITIVE_INFINITY){ return arg; } /* ** Eliminate nice easy case. */ if (arg < tiny) { return arg * 0.5; } long bits = Double.doubleToLongBits(arg); /* ** Extract the exponent. We don't bother to mask out the sign bit, ** 'coz we already eliminated negative numbers. ** Then make sure the exponent is even (after allowing for the offset ** of 0x3ff, which is why the test looks wrong), and define fraction ** to be the fractional part and multiplier to be 2 raised to the power ** of half the exponent (geddit?). */ long magbits = bits & d_expbits; double multiplier = Double.longBitsToDouble(magbits); double fraction = Double.longBitsToDouble((bits & d_mantbits) | d_offsetbits); if ((magbits & 0x0010000000000000L) == 0) { multiplier = multiplier * 0.5; fraction = fraction * 2; } multiplier = Double.longBitsToDouble((((magbits - d_offsetbits) >> 1) + d_offsetbits) & d_expbits); /* ** Now comes Sir Isaac's contribution. The number of iterations may be ** shown to be sufficient, using ``proof by vigorous assertion''. */ double root = fraction * 0.5; root = (root + fraction/root) * 0.5; root = (root + fraction/root) * 0.5; root = (root + fraction/root) * 0.5; root = (root + fraction/root) * 0.5; root = (root + fraction/root) * 0.5; root = (root + fraction/root) * 0.5; return root * multiplier; } /** ** Evaluate sin() using a truncated Taylor series. ** Only use this in the range -quarterpi..quarterpi ! */ private static final double sine(double theta) { double temp; temp = theta * theta; temp = theta * theta * (1.0 - (temp / 156.0)); temp = theta * theta * (1.0 - (temp / 110.0)); temp = theta * theta * (1.0 - (temp / 72.0)); temp = theta * theta * (1.0 - (temp / 42.0)); temp = theta * theta * (1.0 - (temp / 20.0)); temp = theta * (1.0 - (temp / 6.0)); return temp; } /** ** Now for the real sin() function. ** ** For small x, sin(x) = x (this also takes care of -0.0 and 0.0). ** Otherwise we reduce the argument to the range -pi..pi, and then ** subdivide this range into eight octants (half-quadrants). ** Within each quadrant, we use either our truncated Taylor series ** directly or sqrt(1-y*y), where y is the complementary angle to x ** (opposite corner of a right-angled triangle). ** ** Here also, only [CG] is to blame. */ public static double sin(double arg) { if (arg > -tiny && arg < tiny || arg != arg) { return arg; } double theta = arg % twopi; int phase; if (theta <= - Math.PI) { theta += twopi; } else if (theta > Math.PI) { theta -= twopi; } phase = (int)(theta / quarterpi); double temp; switch(phase) { case 0: case -1: return sine(theta); case 1: temp = sine(halfpi - theta); return sqrt(1.0 - temp * temp); case -3: case -2: temp = sine(-halfpi - theta); return -sqrt(1.0 - temp * temp); case 2: temp = sine(theta - halfpi); return sqrt(1.0 - temp * temp); default: return sine(Math.PI - theta); } } /** ** The cos() function works the same way as sin(), mutatis mutandis. */ public static double cos(double arg) { if (arg > -tiny && arg < tiny) { return 1.0; } if (arg != arg) { return arg; } double theta = arg % twopi; int phase; if (theta <= - Math.PI) { theta += twopi; } else if (theta > Math.PI) { theta -= twopi; } phase = (int)(theta / quarterpi); double temp; switch(phase) { case 0: case -1: temp = sine(theta); return sqrt(1.0 - temp * temp); case 1: case 2: return -sine(theta - halfpi); case -2: case -3: return sine(halfpi + theta); default: temp = sine(Math.PI - theta); return -sqrt(1.0 - temp * temp); } } /** ** This is what they tort me at skule, anyway. */ public static double tan(double arg) { if (arg > -tiny && arg < tiny) { return arg; } return sin(arg) / cos(arg); } /** ** Implementation of asin uses a rational polynomial. ** This and asin() itself are based on Whitaker and Eicholz's work. */ private static double arcrat(double x) { double denom; double numer; numer = - 0.69674573447350646411e+0 * x; numer = (numer + 0.10152522233806463645e+2) * x; numer = (numer - 0.39688862997504877339e+2) * x; numer = (numer + 0.57208227877891731407e+2) * x; numer = (numer - 0.27368494524164255994e+2) * x; denom = x; denom = (denom - 0.23823859153670238830e+2) * x; denom = (denom + 0.15095270841030604719e+3) * x; denom = (denom - 0.38186303361750149284e+3) * x; denom = (denom + 0.41714430248260412556e+3) * x ; denom = denom - 0.16421096714498560795e+3; return numer/denom; } /** ** The asin() method proper first eliminates trivial or awkward cases, ** then finds a way to apply arcrat() to a value in [0.0,0.5]. ** If the absolute value of the argument is in [0.5,1.0] then ** we use recursion, which is lazy: someone should take the time ** to eliniate this (e.g., the compiler 9->). */ public static double asin(double arg) { double absval; double sign; if (arg > -tiny && arg < tiny || arg != arg) { return arg; } if (arg > 0) { if (arg > 1) { return Double.NaN; } if (arg > 0.5) { return halfpi - 2.0 * asin(sqrt((1.0 - arg) * 0.5)); } absval = arg; sign = 1.0; } else { if (arg < -1) { return Double.NaN; } if (arg < -0.5) { return 2.0 * asin(sqrt((1.0 + arg) * 0.5)) - halfpi; } absval = -arg; sign = -1.0; } return sign * (absval + (absval * arcrat(arg * arg))); } /** ** Lazy version. */ public static double acos(double arg) { return halfpi - asin(arg); } /** ** Implementation of atan uses a rational polynomial. ** This and arctan() itself are based on Whitaker and Eicholz's work. */ private static double tancrat(double x) { double denom; double numer; numer = - 0.83758299368150059274e+0 * x; numer = (numer - 0.84946240351320683534e+1) * x; numer = (numer - 0.20505855195861651981e+2) * x; numer = (numer - 0.13688768894191926929e+2) * x; denom = x; denom = (denom + 0.15024001160028576121e+2) * x; denom = (denom + 0.59578436142597344465e+2) * x; denom = (denom + 0.86157349597130242515e+2) * x; denom = denom + 0.41066306682575781263e+2; return numer/denom; } /** ** Similarly to asin(), atan() first narrows the range (to [0.0,1.0]) ** and then invokes tancrat(). */ public static double atan(double arg) { double x = arg; boolean flipped = false; double sign = 1.0; double temp; if (arg == 0.0){ return arg; } if (arg != arg) { return arg; } if (arg < 0.0) { x = -arg; sign = -1.0; } if (x > 1.0) { x = 1.0/x; flipped = true; } if (x < tiny) { temp = x; } else { temp = x + x * tancrat(x * x); } if (flipped) { temp = halfpi - temp; } return sign * temp; } /** ** The atan2() method is basically a wrapper around atan(), except ** that for negative arguments it sometimes returns a result in a ** different quadrant. */ public static double atan2(double y, double x) { if (x != x || y != y) { return Double.NaN; } if (x == 0.0) { return y == 0.0 ? Double.NaN : y > 0 ? halfpi : -halfpi; } if (y == 0.0){ if (x > 0){ return y; } long l = Double.doubleToLongBits(PI) | Double.doubleToLongBits(y); return Double.longBitsToDouble(l); } if (Double.isInfinite(y)) { if (Double.isInfinite(x)) { return (y > 0 ? 1.0 : -1.0) * (x > 0 ? quarterpi : Math.PI - quarterpi); } else { return y > 0 ? halfpi : -halfpi; } } double temp = atan(y/x); if (x < 0.0) { if (y < 0.0) { temp = temp - Math.PI; } else { temp = temp + Math.PI; } } return temp; } /** ** Our log is based on a simple Taylor series -- couldn't get ** the rational polynomial jazz to work on this one. */ public static double log(double arg) { if (arg < 0.0 || arg != arg) { return Double.NaN; } if (arg < Double.longBitsToDouble(1L)) { return Double.NEGATIVE_INFINITY; } if (arg == Double.POSITIVE_INFINITY) { return arg; } /* ** Extract the exponent and fractional part. */ long bits = Double.doubleToLongBits(arg); int exponent = (int)((bits - d_offsetbits) >> 52); double fraction = Double.longBitsToDouble((bits & d_mantbits) | d_offsetbits); /* ** Now we use the Taylor series for ln((x+1)/(x-1)): ** <pre> ** / x+1 \ / 1 1 1 \ ** ln |-----| = 2*| --- + ----- + ----- + ... | x >= 1 ** \ x-1 / \ x 3*x^3 5*x^5 / ** </pre> */ double temp = 0.0; if (fraction > 1.0) { double x = (1 + fraction) / (fraction - 1); double square = 1.0 / (x * x); temp = 1.0/21.0; temp = (temp * square) + 1.0/19.0; temp = (temp * square) + 1.0/17.0; temp = (temp * square) + 1.0/15.0; temp = (temp * square) + 1.0/13.0; temp = (temp * square) + 1.0/11.0; temp = (temp * square) + 1.0/9.0; temp = (temp * square) + 1.0/7.0; temp = (temp * square) + 1.0/5.0; temp = (temp * square) + 1.0/3.0; temp = (temp * square) + 1.0; temp = 2.0 * temp / x; } /* ** Finally, add in ln(2) times the exponent. */ return temp + 0.6931471805599453 * exponent; } /** ** For the exp() method we just use a schoolbook Taylor series. ** I'm sure there are faster ways to do this ... */ public static double exp(double arg) { if (arg != arg) { return arg; } if (arg > logbignum) { return Double.POSITIVE_INFINITY; } if (arg == Double.NEGATIVE_INFINITY) { return 0.0; } if (arg > -tiny && arg < tiny) { return 1.0; } int exponent = (int)((arg / 0.6931471805599453) + (arg > 0 ? + 0.5 : -0.5)); double difference = arg - (exponent * 0.6931471805599453); double temp = 1.0 + (difference / 12.0); temp = 1.0 + (difference / 11.0) * temp; temp = 1.0 + (difference / 10.0) * temp; temp = 1.0 + (difference / 9.0) * temp; temp = 1.0 + (difference / 8.0) * temp; temp = 1.0 + (difference / 7.0) * temp; temp = 1.0 + (difference / 6.0) * temp; temp = 1.0 + (difference / 5.0) * temp; temp = 1.0 + (difference / 4.0) * temp; temp = 1.0 + (difference / 3.0) * temp; temp = 1.0 + (difference / 2.0) * temp; temp = 1.0 + difference * temp; return Double.longBitsToDouble(((long)exponent + 0x3ff) << 52) * temp; } /** ** This looks more complicated than it is because of a lot of special-casing. ** Once all that is out of the way, we either use a multiply-and-square ** algorithm if b is an integer, or exp(log(a)*b) otherwise. */ public static double pow(double a, double b) { if (b > -tiny && b < tiny) { return 1.0; } if (b == 1.0) { return a; } if (b != b || a != a) { return Double.NaN; } if (Double.isInfinite(b)) { if (abs(a) == 1.0) { return Double.NaN; } else { return ((abs(a) > 1.0 && b > 0.0) || (abs(a) < 1.0 && b < 0.0)) ? Double.POSITIVE_INFINITY : 0.0; } } if (Double.isInfinite(a)) { if (b > 0.0) { return a; } else { return 0.0; } } long ib = (long)floor(b); if (ib == b) { double temp = 1.0; long j = ib < 0 ? -ib : ib; long k; for (k = 1; k <= j; k <<= 1); for (;;) { if ((k & j) != 0) { temp = temp * a; } k >>= 1; if (k > 0) { temp = temp * temp; } else { break; } } if (ib < 0) { temp = 1.0 / temp; } return temp; } else { /* ** Note that if b is non-integer and a is negative then log(a) will ** return NaN, so we don't have to test for that case. */ return exp(log(a) * b); } } /** ** Create an instance of Random and use this for all subsequent calls. */ public static synchronized double random() { if (RNG == null) { RNG = new java.util.Random(); } return RNG.nextDouble(); } public static double toDegrees(double d) { if ( d == -0.0 || d == 0.0 || d != d || Double.isInfinite(d)) { return d; } d = d * 180.0 / Math.PI; return d; } public static double toRadians(double d) { if ( d == -0.0 || d == 0.0 || d != d || Double.isInfinite(d)) { return d; } d = d * Math.PI / 180.0; return d; } /** ** A very simple abs(). */ public static int abs(int arg) { return (arg < 0) ? -arg : arg; } /** ** Another very simple abs(). */ public static long abs(long arg) { return (arg < 0L) ? -arg : arg; } /** ** A not-so-simple abs() (we need to return 0.0 for abs(-0.0)). */ public static float abs(float arg) { return Float.intBitsToFloat(Float.floatToIntBits(arg) & ~f_signbit); } /** ** Another not-so-simple abs(). */ public static double abs(double arg) { return Double.longBitsToDouble(Double.doubleToLongBits(arg) & ~d_signbit); } /** ** A very simple max(). */ public static int max(int a, int b) { return (a > b) ? a : b; } /** ** Another very simple max(). */ public static long max(long a, long b) { return (a > b) ? a : b; } /** ** This max() is not so simple, because we have to ensure that ** max(0.0,-0.0) is 0.0. */ public static float max(float a, float b) { int abits = Float.floatToIntBits(a); int bbits = Float.floatToIntBits(a); if (abits == 0 && b <= 0.0f) { return a; } if (bbits == 0 && a <= 0.0f) { return b; } return (a > b || a != a) ? a : b; } /** ** Another not-so-simple max(). */ public static double max(double a, double b) { long abits = Double.doubleToLongBits(a); long bbits = Double.doubleToLongBits(a); if (abits == 0L && b <= 0.0f) { return a; } if (bbits == 0L && a <= 0.0f) { return b; } return (a > b || a != a) ? a : b; } /** ** A very simple min(). */ public static int min(int a, int b) { return (a < b || a != a) ? a : b; } /** ** Another very simple min(). */ public static long min(long a, long b) { return (a < b || a != a) ? a : b; } /** ** A not-so-simple min(). */ public static float min(float a, float b) { int abits = Float.floatToIntBits(a); int bbits = Float.floatToIntBits(a); if (abits == f_signbit && b >= 0.0f) { return a; } if (bbits == f_signbit && a >= 0.0f) { return b; } return (a < b || a != a) ? a : b; } /** ** Another not-so-simple min(). */ public static double min(double a, double b) { long abits = Double.doubleToLongBits(a); long bbits = Double.doubleToLongBits(a); if (abits == d_signbit && b >= 0.0f) { return a; } if (bbits == d_signbit && a >= 0.0f) { return b; } return (a < b || a!= a) ? a : b; } /** ** If arg is already an integer, floor(arg) == arg. ** All numbers bigger than 2^52 are considered to be integers ** (how would we know if they weren't?). For smaller numbers ** we can cast to a long and back to truncate towards zero, ** and then adjust as necessary. */ public static double floor(double arg) { if ((abs(arg) > 0x0010000000000000L) || arg != arg || (arg == ((long)arg))) { return arg; } if (arg < 0.0) { return ((long)arg) - 1.0; } return ((long)arg); } /** ** See floor() above. ** Ha, floor above and ceiling below. This is good stuff. */ public static double ceil(double arg) { if ((abs(arg) > 0x0010000000000000L) || arg != arg || arg == ((long)arg)) { return arg; } if (arg < 0.0) { arg = ((long)(arg)); return (arg == 0.0 ? -0.0 : arg); } return ((long)arg) + 1.0; } /** ** Simple enough, but look out for the case of infinite y, finite x. */ public static double IEEEremainder(double x, double y) { if (Double.isInfinite(y) && ! Double.isInfinite(x)) { return x; } return x - y * rint(x / y); } /** ** The integer closest to arg (if two are equally close, take the even one). */ public static double rint(double arg) { double f = floor(arg); double c = ceil(arg); double n; if (arg == f) { n = arg; } else if (arg - f > c - arg) { n = c; } else if (arg - f < c - arg) { n = f; } else if ((f % 2.0) == 0.0) { n = f; } else { n = c; } return n; } /** ** Defined to be (int)floor(arg + 0.5f). */ public static int round(float arg) { return (int)floor(arg + 0.5f); } /** ** Same story. */ public static long round(double arg) { return (long)floor(arg + 0.5d); } /** ** Implementation of Float.valueOf() and Float.parseFloat(). ** Package access, so can only be seen within java.lang . */ static float floatValue(String s) throws NumberFormatException { s = s.trim(); int length = s.length(); if(length == 0){ throw new NumberFormatException(); } double result = 0.0f; boolean negative = false; boolean expnegative = false; int index = 0; String wholepart; String fractpart; String exppart; try { if (s.charAt(index) == '-') { negative = true; ++index; } else if (s.charAt(index) == '+') { ++index; } if((3 + index == length) &&s.regionMatches(true, index, "NaN", 0, 3)) { return Float.NaN; } if((8 + index == length) &&s.regionMatches(true, index, "Infinity", 0, 8)) { return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; } if("dDfF".indexOf(s.charAt(length-1)) != -1){ --length; } int point = s.indexOf('.', index); int e; if (point >= 0) { e = s.indexOf('e', point+1); if (e < 0) { e = s.indexOf('E', point+1); } wholepart = s.substring(index, point); if (e < 0) { fractpart = s.substring(point+1, length); exppart = "0"; expnegative = false; } else { fractpart = s.substring(point+1, e); exppart = s.substring(e+1, length); if (exppart.charAt(0) == '-') { expnegative = true; exppart = exppart.substring(1); } else if (exppart.charAt(0) == '+') { exppart = exppart.substring(1); } } } else { e = s.indexOf('e', index); if (e < 0) { e = s.indexOf('E', index); } if (e < 0) { wholepart = s.substring(index, length); fractpart = ""; exppart = "0"; expnegative = false; } else { wholepart = s.substring(index, e); fractpart = ""; exppart = s.substring(e+1, length); if (exppart.charAt(0) == '-') { expnegative = true; exppart = exppart.substring(1); } else if (exppart.charAt(0) == '+') { exppart = exppart.substring(1); } } } if (fractpart.length() > 18) { fractpart = fractpart.substring(0, 18); } } catch (IndexOutOfBoundsException ioobe) { // System.out.println("floatValue: got "+ioobe+", throwing NumberFormatException"); throw new NumberFormatException(); } if (wholepart.length() == 0 && fractpart.length() == 0) { // System.out.println("floatValue: no chars either side of point, throwing NumberFormatException"); throw new NumberFormatException(); } if (wholepart.length() == 0) { wholepart = "0"; } if (fractpart.length() == 0) { fractpart = "0"; } if (negative && wholepart.equals("0") && fractpart.equals("0")) { // System.out.println("floatValue: special case, returning -0.0"); return -0.0f; } result = (Long.parseLong(fractpart) / pow(10.0, fractpart.length())); result += Long.parseLong(wholepart); int exponent = Integer.parseInt(exppart); if (exponent != 0) { result *= pow(10.0, expnegative ? -exponent : exponent); } return (float)(negative ? -result : result); } /** ** Implementation of Double.valueOf() and Double.parseDouble(). ** Package access, so can only be seen within java.lang . */ static double doubleValue(String s) throws NumberFormatException { s = s.trim(); int length = s.length(); if(length == 0){ throw new NumberFormatException(); } double result = 0.0d; boolean negative = false; boolean expnegative = false; int index = 0; String wholepart; String fractpart; String exppart; // System.out.println("doubleValue: input is \""+s+"\""); try { if (s.charAt(index) == '-') { negative = true; ++index; } else if (s.charAt(index) == '+') { ++index; } if((3 + index == length) &&s.regionMatches(true, index, "NaN", 0, 3)) { return Float.NaN; } if((8 + index == length) &&s.regionMatches(true, index, "Infinity", 0, 8)) { return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; } if("dDfF".indexOf(s.charAt(length-1)) != -1){ --length; } int point = s.indexOf('.', index); int e; if (point >= 0) { e = s.indexOf('e', point+1); if (e < 0) { e = s.indexOf('E', point+1); } wholepart = s.substring(index,point); if (e < 0) { fractpart = s.substring(point+1, length); exppart = "0"; expnegative = false; } else { fractpart = s.substring(point+1, e); exppart = s.substring(e+1, length); if (exppart.charAt(0) == '-') { expnegative = true; exppart = exppart.substring(1); } else if (exppart.charAt(0) == '+') { exppart = exppart.substring(1); } } } else { e = s.indexOf('e', index); if (e < 0) { e = s.indexOf('E', index); } if (e < 0) { wholepart = s.substring(index, length); fractpart = ""; exppart = "0"; expnegative = false; } else { wholepart = s.substring(index, e); fractpart = ""; exppart = s.substring(e+1, length); if (exppart.charAt(0) == '-') { expnegative = true; exppart = exppart.substring(1); } else if (exppart.charAt(0) == '+') { exppart = exppart.substring(1); } } } if (fractpart.length() > 18) { fractpart = fractpart.substring(0, 18); } } catch (IndexOutOfBoundsException ioobe) { // System.out.println("floatValue: got "+ioobe+", throwing NumberFormatException"); throw new NumberFormatException(); } // System.out.println("doubleValue: wholepart = "+wholepart); // System.out.println("doubleValue: fractpart = "+fractpart); // System.out.println("doubleValue: exppart = "+exppart); // System.out.println("doubleValue: expnegative = "+expnegative); if (wholepart.length() == 0 && fractpart.length() == 0) { // System.out.println("doubleValue: no chars either side of point, throwing NumberFormatException"); throw new NumberFormatException(); } if (wholepart.length() == 0) { wholepart = "0"; } if (fractpart.length() == 0) { fractpart = "0"; } if (negative && wholepart.equals("0") && fractpart.equals("0")) { // System.out.println("floatValue: special case, returning -0.0"); return -0.0d; } result = Long.parseLong(wholepart); result += Long.parseLong(fractpart) / pow(10.0, fractpart.length()); int exponent = Integer.parseInt(exppart); if (exponent != 0) { result *= pow(10.0, expnegative ? -exponent : exponent); } // System.out.println("doubleValue: returning "+(negative ? -result : result)); return negative ? -result : result; } /** ** Package-private method to convert a long to a string. */ static String toString(long arg, int radix) { if (arg == 0) { return "0"; } if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) { radix = 10; } char[] buffer = new char[65]; boolean negative = true; int length = 0; if (arg > 0) { negative = false; arg = -arg; } while (arg < 0) { buffer[64 - length] = Character.forDigit((int)(-(arg % radix)), radix); arg /= radix; ++length; } if (negative) { buffer[64 - length] = '-'; ++length; } return new String(buffer, 65 - length, length); } /** ** Package-private method to convert an int to a string, unsigned. ** Only works for radix = 2, 8 or 16. */ static String toStringUnsigned(int arg, int radix) { if (arg >= 0) { return toString(arg, radix); } char[] buffer = new char[32]; int shift; int mask; int length = 0; switch(radix) { case 2: shift = 1; mask = 1; break; case 8: shift = 3; mask = 7; break; default: /* 16 */ shift = 4; mask = 15; } while (arg != 0) { buffer[31 - length] = Character.forDigit((arg & mask), radix); arg >>>= shift; ++length; } return new String(buffer, 32 - length, length); } /** ** Package-private method to convert a long to a string, unsigned. ** Only works for radix = 2, 8 or 16. */ static String toStringUnsigned(long arg, int radix) { if (arg >= 0) { return toString(arg, radix); } char[] buffer = new char[64]; int shift; int mask; int length = 0; switch(radix) { case 2: shift = 1; mask = 1; break; case 8: shift = 3; mask = 7; break; default: /* 16 */ shift = 4; mask = 15; } while (arg != 0) { buffer[63 - length] = Character.forDigit((int)(arg & mask), radix); arg >>>= shift; ++length; } return new String(buffer, 64 - length, length); } /** ** Package-private method to convert a float to a string. */ static String toString(float arg) { if (arg != arg) { return "NaN"; } int bits = Float.floatToIntBits(arg); int signbit = bits & f_signbit; if (bits == signbit) { return (signbit == 0) ? "0.0" : "-0.0"; } if (Double.isInfinite(arg)) { return (signbit == 0) ? "Infinity" : "-Infinity"; } float absvalue = abs(arg); if (absvalue >= 0.001 && absvalue < 10000000.0) { return ((signbit == 0) ? "" : "-") + MathHelper.toString_internal(absvalue); } else { long exponent = (((bits & f_expbits) >> 23) - 0x7f) * 30103L / 100000L; float scaled = absvalue / (float)pow(10.0f, exponent); while (scaled < 1.0f) { exponent -= 1; scaled *= 10.0f; } while (scaled >= 10.0f) { exponent += 1; scaled *= 0.1f; } return ((signbit == 0L) ? "" : "-") + MathHelper.toString_internal(scaled) + "E" + exponent; } } /** ** Package-private method to convert a double to a string. */ static String toString(double arg) { if (arg != arg) { return "NaN"; } long bits = Double.doubleToLongBits(arg); long signbit = bits & d_signbit; if (bits == signbit) { return (signbit == 0L) ? "0.0" : "-0.0"; } if (Double.isInfinite(arg)) { return (signbit == 0L) ? "Infinity" : "-Infinity"; } double absvalue = abs(arg); if (absvalue >= 0.001 && absvalue < 10000000.0) { return ((signbit == 0L) ? "" : "-") + MathHelper.toString_internal(absvalue); } else { long exponent = (((bits & d_expbits) >> 52) - 0x3ff) * 30103L / 100000L; double scaled = absvalue / pow(10.0d, exponent); while (scaled < 1.0) { exponent -= 1; scaled *= 10.0; } while (scaled >= 10.0) { exponent += 1; scaled *= 0.1; } return ((signbit == 0L) ? "" : "-") + MathHelper.toString_internal(scaled) + "E" + exponent; } } }