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 
  58 package 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).
  65 class 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 }