package org.apache.commons.math3.util; import org.geogebra.common.util.DoubleConsts; /* * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ public class GWTMath { /** * Returns the size of an ulp of the argument. An ulp, unit in the last * place, of a {@code double} value is the positive distance between this * floating-point value and the {@code * double} 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}. * <li>If the argument is ±{@code Double.MAX_VALUE}, 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) { int exp = getExponent(d); switch (exp) { case DoubleConsts.MAX_EXPONENT + 1: // NaN or infinity return Math.abs(d); case DoubleConsts.MIN_EXPONENT - 1: // zero or subnormal return Double.MIN_VALUE; default: assert exp <= DoubleConsts.MAX_EXPONENT && exp >= DoubleConsts.MIN_EXPONENT; // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x)) exp = exp - (DoubleConsts.SIGNIFICAND_WIDTH - 1); if (exp >= DoubleConsts.MIN_EXPONENT) { return powerOfTwoD(exp); } else { // return a subnormal result; left shift integer // representation of Double.MIN_VALUE appropriate // number of positions return Double.longBitsToDouble( 1L << (exp - (DoubleConsts.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH - 1)))); } } } /** * Returns a floating-point power of two in the normal range. */ static double powerOfTwoD(int n) { assert (n >= DoubleConsts.MIN_EXPONENT && n <= DoubleConsts.MAX_EXPONENT); return Double.longBitsToDouble((((long) n + (long) DoubleConsts.EXP_BIAS) << (DoubleConsts.SIGNIFICAND_WIDTH - 1)) & DoubleConsts.EXP_BIT_MASK); } // http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Math.java#Math.getExponent%28double%29 /** * Returns the unbiased exponent used in the representation of a * {@code double}. Special cases: * * <ul> * <li>If the argument is NaN or infinite, then the result is * {@link Double#MAX_EXPONENT} + 1. * <li>If the argument is zero or subnormal, then the result is * {@link Double#MIN_EXPONENT} -1. * </ul> * * @param d * a {@code double} value * @return the unbiased exponent of the argument * @since 1.6 */ public static int getExponent(double d) { /* * Bitwise convert d to long, mask out exponent bits, shift to the right * and then subtract out double's bias adjust to get true exponent * value. */ // changed from doubleToRawLongBits() for GWT return (int) (((Double.doubleToLongBits(d) & DoubleConsts.EXP_BIT_MASK) >> (DoubleConsts.SIGNIFICAND_WIDTH - 1)) - DoubleConsts.EXP_BIAS); } // from // https://groups.google.com/forum/#!topic/google-web-toolkit-contributors/I50Ry-x8ur0 public static double IEEEremainder(double f1, double f2) { double r = Math.abs(f1 % f2); if (Double.isNaN(r) || r == f2 || r <= Math.abs(f2) / 2.0) { return r; } else { return Math.signum(f1) * (r - f2); } } }