1/* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26// This file is available under and governed by the GNU General Public 27// License version 2 only, as published by the Free Software Foundation. 28// However, the following notice accompanied the original version of this 29// file: 30// 31// Copyright 2010 the V8 project authors. All rights reserved. 32// Redistribution and use in source and binary forms, with or without 33// modification, are permitted provided that the following conditions are 34// met: 35// 36// * Redistributions of source code must retain the above copyright 37// notice, this list of conditions and the following disclaimer. 38// * Redistributions in binary form must reproduce the above 39// copyright notice, this list of conditions and the following 40// disclaimer in the documentation and/or other materials provided 41// with the distribution. 42// * Neither the name of Google Inc. nor the names of its 43// contributors may be used to endorse or promote products derived 44// from this software without specific prior written permission. 45// 46// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 47// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 48// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 49// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 50// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 51// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 52// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 53// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 54// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 55// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 56// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 58package jdk.nashorn.internal.runtime.doubleconv; 59 60// This "Do It Yourself Floating Point" class implements a floating-point number 61// with a uint64 significand and an int exponent. Normalized DiyFp numbers will 62// have the most significant bit of the significand set. 63// Multiplication and Subtraction do not normalize their results. 64// DiyFp are not designed to contain special doubles (NaN and Infinity). 65class DiyFp { 66 67 private long f_; 68 private int e_; 69 70 static final int kSignificandSize = 64; 71 static final long kUint64MSB = 0x8000000000000000L; 72 73 74 DiyFp() { 75 this.f_ = 0; 76 this.e_ = 0; 77 } 78 79 DiyFp(final long f, final int e) { 80 this.f_ = f; 81 this.e_ = e; 82 } 83 84 // this = this - other. 85 // The exponents of both numbers must be the same and the significand of this 86 // must be bigger than the significand of other. 87 // The result will not be normalized. 88 void subtract(final DiyFp other) { 89 assert (e_ == other.e_); 90 assert Long.compareUnsigned(f_, other.f_) >= 0; 91 f_ -= other.f_; 92 } 93 94 // Returns a - b. 95 // The exponents of both numbers must be the same and this must be bigger 96 // than other. The result will not be normalized. 97 static DiyFp minus(final DiyFp a, final DiyFp b) { 98 final DiyFp result = new DiyFp(a.f_, a.e_); 99 result.subtract(b); 100 return result; 101 } 102 103 104 // this = this * other. 105 final void multiply(final DiyFp other) { 106 // Simply "emulates" a 128 bit multiplication. 107 // However: the resulting number only contains 64 bits. The least 108 // significant 64 bits are only used for rounding the most significant 64 109 // bits. 110 final long kM32 = 0xFFFFFFFFL; 111 final long a = f_ >>> 32; 112 final long b = f_ & kM32; 113 final long c = other.f_ >>> 32; 114 final long d = other.f_ & kM32; 115 final long ac = a * c; 116 final long bc = b * c; 117 final long ad = a * d; 118 final long bd = b * d; 119 long tmp = (bd >>> 32) + (ad & kM32) + (bc & kM32); 120 // By adding 1U << 31 to tmp we round the final result. 121 // Halfway cases will be round up. 122 tmp += 1L << 31; 123 final long result_f = ac + (ad >>> 32) + (bc >>> 32) + (tmp >>> 32); 124 e_ += other.e_ + 64; 125 f_ = result_f; 126 } 127 128 // returns a * b; 129 static DiyFp times(final DiyFp a, final DiyFp b) { 130 final DiyFp result = new DiyFp(a.f_, a.e_); 131 result.multiply(b); 132 return result; 133 } 134 135 void normalize() { 136 assert(f_ != 0); 137 long significand = this.f_; 138 int exponent = this.e_; 139 140 // This method is mainly called for normalizing boundaries. In general 141 // boundaries need to be shifted by 10 bits. We thus optimize for this case. 142 final long k10MSBits = 0xFFC00000L << 32; 143 while ((significand & k10MSBits) == 0) { 144 significand <<= 10; 145 exponent -= 10; 146 } 147 while ((significand & kUint64MSB) == 0) { 148 significand <<= 1; 149 exponent--; 150 } 151 this.f_ = significand; 152 this.e_ = exponent; 153 } 154 155 static DiyFp normalize(final DiyFp a) { 156 final DiyFp result = new DiyFp(a.f_, a.e_); 157 result.normalize(); 158 return result; 159 } 160 161 long f() { return f_; } 162 int e() { return e_; } 163 164 void setF(final long new_value) { f_ = new_value; } 165 void setE(final int new_value) { e_ = new_value; } 166 167 @Override 168 public String toString() { 169 return "DiyFp[f=" + f_ + ", e=" + e_ + "]"; 170 } 171 172} 173