Java tutorial
//package com.java2s; /* * 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. */ import sun.misc.FloatConsts; import sun.misc.DoubleConsts; public class Main { static double twoToTheDoubleScaleUp = powerOfTwoD(512); static double twoToTheDoubleScaleDown = powerOfTwoD(-512); /** * Return <code>d</code> × * 2<sup><code>scale_factor</code></sup> rounded as if performed * by a single correctly rounded floating-point multiply to a * member of the double value set. See <a * href="http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html#9208">§4.2.3</a> * of the <a href="http://java.sun.com/docs/books/jls/html/">Java * Language Specification</a> for a discussion of floating-point * value sets. If the exponent of the result is between the * <code>double</code>'s minimum exponent and maximum exponent, * the answer is calculated exactly. If the exponent of the * result would be larger than <code>doubles</code>'s maximum * exponent, an infinity is returned. Note that if the result is * subnormal, precision may be lost; that is, when <code>scalb(x, * n)</code> is subnormal, <code>scalb(scalb(x, n), -n)</code> may * not equal <i>x</i>. When the result is non-NaN, the result has * the same sign as <code>d</code>. * *<p> * Special cases: * <ul> * <li> If the first argument is NaN, NaN is returned. * <li> If the first argument is infinite, then an infinity of the * same sign is returned. * <li> If the first argument is zero, then a zero of the same * sign is returned. * </ul> * * @param d number to be scaled by a power of two. * @param scale_factor power of 2 used to scale <code>d</code> * @return <code>d * </code>2<sup><code>scale_factor</code></sup> * @author Joseph D. Darcy */ public static double scalb(double d, int scale_factor) { /* * This method does not need to be declared strictfp to * compute the same correct result on all platforms. When * scaling up, it does not matter what order the * multiply-store operations are done; the result will be * finite or overflow regardless of the operation ordering. * However, to get the correct result when scaling down, a * particular ordering must be used. * * When scaling down, the multiply-store operations are * sequenced so that it is not possible for two consecutive * multiply-stores to return subnormal results. If one * multiply-store result is subnormal, the next multiply will * round it away to zero. This is done by first multiplying * by 2 ^ (scale_factor % n) and then multiplying several * times by by 2^n as needed where n is the exponent of number * that is a covenient power of two. In this way, at most one * real rounding error occurs. If the double value set is * being used exclusively, the rounding will occur on a * multiply. If the double-extended-exponent value set is * being used, the products will (perhaps) be exact but the * stores to d are guaranteed to round to the double value * set. * * It is _not_ a valid implementation to first multiply d by * 2^MIN_EXPONENT and then by 2 ^ (scale_factor % * MIN_EXPONENT) since even in a strictfp program double * rounding on underflow could occur; e.g. if the scale_factor * argument was (MIN_EXPONENT - n) and the exponent of d was a * little less than -(MIN_EXPONENT - n), meaning the final * result would be subnormal. * * Since exact reproducibility of this method can be achieved * without any undue performance burden, there is no * compelling reason to allow double rounding on underflow in * scalb. */ // magnitude of a power of two so large that scaling a finite // nonzero value by it would be guaranteed to over or // underflow; due to rounding, scaling down takes takes an // additional power of two which is reflected here final int MAX_SCALE = DoubleConsts.MAX_EXPONENT + -DoubleConsts.MIN_EXPONENT + DoubleConsts.SIGNIFICAND_WIDTH + 1; int exp_adjust = 0; int scale_increment = 0; double exp_delta = Double.NaN; // Make sure scaling factor is in a reasonable range if (scale_factor < 0) { scale_factor = Math.max(scale_factor, -MAX_SCALE); scale_increment = -512; exp_delta = twoToTheDoubleScaleDown; } else { scale_factor = Math.min(scale_factor, MAX_SCALE); scale_increment = 512; exp_delta = twoToTheDoubleScaleUp; } // Calculate (scale_factor % +/-512), 512 = 2^9, using // technique from "Hacker's Delight" section 10-2. int t = (scale_factor >> 9 - 1) >>> 32 - 9; exp_adjust = ((scale_factor + t) & (512 - 1)) - t; d *= powerOfTwoD(exp_adjust); scale_factor -= exp_adjust; while (scale_factor != 0) { d *= exp_delta; scale_factor -= scale_increment; } return d; } /** * Return <code>f </code>× * 2<sup><code>scale_factor</code></sup> rounded as if performed * by a single correctly rounded floating-point multiply to a * member of the float value set. See <a * href="http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html#9208">§4.2.3</a> * of the <a href="http://java.sun.com/docs/books/jls/html/">Java * Language Specification</a> for a discussion of floating-point * value set. If the exponent of the result is between the * <code>float</code>'s minimum exponent and maximum exponent, the * answer is calculated exactly. If the exponent of the result * would be larger than <code>float</code>'s maximum exponent, an * infinity is returned. Note that if the result is subnormal, * precision may be lost; that is, when <code>scalb(x, n)</code> * is subnormal, <code>scalb(scalb(x, n), -n)</code> may not equal * <i>x</i>. When the result is non-NaN, the result has the same * sign as <code>f</code>. * *<p> * Special cases: * <ul> * <li> If the first argument is NaN, NaN is returned. * <li> If the first argument is infinite, then an infinity of the * same sign is returned. * <li> If the first argument is zero, then a zero of the same * sign is returned. * </ul> * * @param f number to be scaled by a power of two. * @param scale_factor power of 2 used to scale <code>f</code> * @return <code>f * </code>2<sup><code>scale_factor</code></sup> * @author Joseph D. Darcy */ public static float scalb(float f, int scale_factor) { // magnitude of a power of two so large that scaling a finite // nonzero value by it would be guaranteed to over or // underflow; due to rounding, scaling down takes takes an // additional power of two which is reflected here final int MAX_SCALE = FloatConsts.MAX_EXPONENT + -FloatConsts.MIN_EXPONENT + FloatConsts.SIGNIFICAND_WIDTH + 1; // Make sure scaling factor is in a reasonable range scale_factor = Math.max(Math.min(scale_factor, MAX_SCALE), -MAX_SCALE); /* * Since + MAX_SCALE for float fits well within the double * exponent range and + float -> double conversion is exact * the multiplication below will be exact. Therefore, the * rounding that occurs when the double product is cast to * float will be the correctly rounded float result. Since * all operations other than the final multiply will be exact, * it is not necessary to declare this method strictfp. */ return (float) ((double) f * powerOfTwoD(scale_factor)); } /** * 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); } }