LCOV - code coverage report
Current view: directory - js/src/v8-dtoa - double.h (source / functions) Found Hit Coverage
Test: app.info Lines: 51 47 92.2 %
Date: 2012-06-02 Functions: 12 11 91.7 %

       1                 : // Copyright 2010 the V8 project authors. All rights reserved.
       2                 : // Redistribution and use in source and binary forms, with or without
       3                 : // modification, are permitted provided that the following conditions are
       4                 : // met:
       5                 : //
       6                 : //     * Redistributions of source code must retain the above copyright
       7                 : //       notice, this list of conditions and the following disclaimer.
       8                 : //     * Redistributions in binary form must reproduce the above
       9                 : //       copyright notice, this list of conditions and the following
      10                 : //       disclaimer in the documentation and/or other materials provided
      11                 : //       with the distribution.
      12                 : //     * Neither the name of Google Inc. nor the names of its
      13                 : //       contributors may be used to endorse or promote products derived
      14                 : //       from this software without specific prior written permission.
      15                 : //
      16                 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      17                 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      18                 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      19                 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      20                 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      21                 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      22                 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23                 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24                 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25                 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      26                 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27                 : 
      28                 : #ifndef V8_DOUBLE_H_
      29                 : #define V8_DOUBLE_H_
      30                 : 
      31                 : #include "diy-fp.h"
      32                 : 
      33                 : namespace v8 {
      34                 : namespace internal {
      35                 : 
      36                 : // We assume that doubles and uint64_t have the same endianness.
      37         1286675 : static uint64_t double_to_uint64(double d) { return BitCast<uint64_t>(d); }
      38               0 : static double uint64_to_double(uint64_t d64) { return BitCast<double>(d64); }
      39                 : 
      40                 : // Helper functions for doubles.
      41                 : class Double {
      42                 :  public:
      43                 :   static const uint64_t kSignMask = V8_2PART_UINT64_C(0x80000000, 00000000);
      44                 :   static const uint64_t kExponentMask = V8_2PART_UINT64_C(0x7FF00000, 00000000);
      45                 :   static const uint64_t kSignificandMask =
      46                 :       V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF);
      47                 :   static const uint64_t kHiddenBit = V8_2PART_UINT64_C(0x00100000, 00000000);
      48                 : 
      49                 :   Double() : d64_(0) {}
      50         1286675 :   explicit Double(double d) : d64_(double_to_uint64(d)) {}
      51                 :   explicit Double(uint64_t d64) : d64_(d64) {}
      52                 : 
      53          257335 :   DiyFp AsDiyFp() const {
      54          257335 :     ASSERT(!IsSpecial());
      55          257335 :     return DiyFp(Significand(), Exponent());
      56                 :   }
      57                 : 
      58                 :   // this->Significand() must not be 0.
      59          257335 :   DiyFp AsNormalizedDiyFp() const {
      60          257335 :     uint64_t f = Significand();
      61          257335 :     int e = Exponent();
      62                 : 
      63          257335 :     ASSERT(f != 0);
      64                 : 
      65                 :     // The current double could be a denormal.
      66          514670 :     while ((f & kHiddenBit) == 0) {
      67               0 :       f <<= 1;
      68               0 :       e--;
      69                 :     }
      70                 :     // Do the final shifts in one go. Don't forget the hidden bit (the '-1').
      71          257335 :     f <<= DiyFp::kSignificandSize - kSignificandSize - 1;
      72          257335 :     e -= DiyFp::kSignificandSize - kSignificandSize - 1;
      73          257335 :     return DiyFp(f, e);
      74                 :   }
      75                 : 
      76                 :   // Returns the double's bit as uint64.
      77         3088020 :   uint64_t AsUint64() const {
      78         3088020 :     return d64_;
      79                 :   }
      80                 : 
      81          514670 :   int Exponent() const {
      82          514670 :     if (IsDenormal()) return kDenormalExponent;
      83                 : 
      84          514670 :     uint64_t d64 = AsUint64();
      85          514670 :     int biased_e = static_cast<int>((d64 & kExponentMask) >> kSignificandSize);
      86          514670 :     return biased_e - kExponentBias;
      87                 :   }
      88                 : 
      89          514670 :   uint64_t Significand() const {
      90          514670 :     uint64_t d64 = AsUint64();
      91          514670 :     uint64_t significand = d64 & kSignificandMask;
      92          514670 :     if (!IsDenormal()) {
      93          514670 :       return significand + kHiddenBit;
      94                 :     } else {
      95               0 :       return significand;
      96                 :     }
      97                 :   }
      98                 : 
      99                 :   // Returns true if the double is a denormal.
     100         1029340 :   bool IsDenormal() const {
     101         1029340 :     uint64_t d64 = AsUint64();
     102         1029340 :     return (d64 & kExponentMask) == 0;
     103                 :   }
     104                 : 
     105                 :   // We consider denormals not to be special.
     106                 :   // Hence only Infinity and NaN are special.
     107          772005 :   bool IsSpecial() const {
     108          772005 :     uint64_t d64 = AsUint64();
     109          772005 :     return (d64 & kExponentMask) == kExponentMask;
     110                 :   }
     111                 : 
     112                 :   bool IsNan() const {
     113                 :     uint64_t d64 = AsUint64();
     114                 :     return ((d64 & kExponentMask) == kExponentMask) &&
     115                 :         ((d64 & kSignificandMask) != 0);
     116                 :   }
     117                 : 
     118                 : 
     119                 :   bool IsInfinite() const {
     120                 :     uint64_t d64 = AsUint64();
     121                 :     return ((d64 & kExponentMask) == kExponentMask) &&
     122                 :         ((d64 & kSignificandMask) == 0);
     123                 :   }
     124                 : 
     125                 : 
     126          257335 :   int Sign() const {
     127          257335 :     uint64_t d64 = AsUint64();
     128          257335 :     return (d64 & kSignMask) == 0? 1: -1;
     129                 :   }
     130                 : 
     131                 : 
     132                 :   // Returns the two boundaries of this.
     133                 :   // The bigger boundary (m_plus) is normalized. The lower boundary has the same
     134                 :   // exponent as m_plus.
     135          257335 :   void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
     136          257335 :     DiyFp v = this->AsDiyFp();
     137          257335 :     bool significand_is_zero = (v.f() == kHiddenBit);
     138          257335 :     DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
     139          257335 :     DiyFp m_minus;
     140          257335 :     if (significand_is_zero && v.e() != kDenormalExponent) {
     141                 :       // The boundary is closer. Think of v = 1000e10 and v- = 9999e9.
     142                 :       // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
     143                 :       // at a distance of 1e8.
     144                 :       // The only exception is for the smallest normal: the largest denormal is
     145                 :       // at the same distance as its successor.
     146                 :       // Note: denormals have the same exponent as the smallest normals.
     147            2980 :       m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
     148                 :     } else {
     149          254355 :       m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
     150                 :     }
     151          257335 :     m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
     152          257335 :     m_minus.set_e(m_plus.e());
     153          257335 :     *out_m_plus = m_plus;
     154          257335 :     *out_m_minus = m_minus;
     155          257335 :   }
     156                 : 
     157                 :   double value() const { return uint64_to_double(d64_); }
     158                 : 
     159                 :  private:
     160                 :   static const int kSignificandSize = 52;  // Excludes the hidden bit.
     161                 :   static const int kExponentBias = 0x3FF + kSignificandSize;
     162                 :   static const int kDenormalExponent = -kExponentBias + 1;
     163                 : 
     164                 :   uint64_t d64_;
     165                 : };
     166                 : 
     167                 : } }  // namespace v8::internal
     168                 : 
     169                 : #endif  // V8_DOUBLE_H_

Generated by: LCOV version 1.7