1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_NUMBERS_DIY_FP_H_ 6 #define V8_NUMBERS_DIY_FP_H_ 7 8 #include <stdint.h> 9 10 #include "src/base/logging.h" 11 #include "src/base/macros.h" 12 13 namespace v8 { 14 namespace internal { 15 16 // This "Do It Yourself Floating Point" class implements a floating-point number 17 // with a uint64 significand and an int exponent. Normalized DiyFp numbers will 18 // have the most significant bit of the significand set. 19 // Multiplication and Subtraction do not normalize their results. 20 // DiyFp are not designed to contain special doubles (NaN and Infinity). 21 class DiyFp { 22 public: 23 static const int kSignificandSize = 64; 24 DiyFp()25 DiyFp() : f_(0), e_(0) {} DiyFp(uint64_t f,int e)26 DiyFp(uint64_t f, int e) : f_(f), e_(e) {} 27 28 // this = this - other. 29 // The exponents of both numbers must be the same and the significand of this 30 // must be bigger than the significand of other. 31 // The result will not be normalized. Subtract(const DiyFp & other)32 void Subtract(const DiyFp& other) { 33 DCHECK(e_ == other.e_); 34 DCHECK(f_ >= other.f_); 35 f_ -= other.f_; 36 } 37 38 // Returns a - b. 39 // The exponents of both numbers must be the same and this must be bigger 40 // than other. The result will not be normalized. Minus(const DiyFp & a,const DiyFp & b)41 static DiyFp Minus(const DiyFp& a, const DiyFp& b) { 42 DiyFp result = a; 43 result.Subtract(b); 44 return result; 45 } 46 47 // this = this * other. 48 V8_EXPORT_PRIVATE void Multiply(const DiyFp& other); 49 50 // returns a * b; Times(const DiyFp & a,const DiyFp & b)51 static DiyFp Times(const DiyFp& a, const DiyFp& b) { 52 DiyFp result = a; 53 result.Multiply(b); 54 return result; 55 } 56 Normalize()57 void Normalize() { 58 DCHECK_NE(f_, 0); 59 uint64_t f = f_; 60 int e = e_; 61 62 // This method is mainly called for normalizing boundaries. In general 63 // boundaries need to be shifted by 10 bits. We thus optimize for this case. 64 const uint64_t k10MSBits = static_cast<uint64_t>(0x3FF) << 54; 65 while ((f & k10MSBits) == 0) { 66 f <<= 10; 67 e -= 10; 68 } 69 while ((f & kUint64MSB) == 0) { 70 f <<= 1; 71 e--; 72 } 73 f_ = f; 74 e_ = e; 75 } 76 Normalize(const DiyFp & a)77 static DiyFp Normalize(const DiyFp& a) { 78 DiyFp result = a; 79 result.Normalize(); 80 return result; 81 } 82 f()83 uint64_t f() const { return f_; } e()84 int e() const { return e_; } 85 set_f(uint64_t new_value)86 void set_f(uint64_t new_value) { f_ = new_value; } set_e(int new_value)87 void set_e(int new_value) { e_ = new_value; } 88 89 private: 90 static const uint64_t kUint64MSB = static_cast<uint64_t>(1) << 63; 91 92 uint64_t f_; 93 int e_; 94 }; 95 96 } // namespace internal 97 } // namespace v8 98 99 #endif // V8_NUMBERS_DIY_FP_H_ 100