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_DIY_FP_H_ 6 #define V8_DIY_FP_H_ 7 8 #include <stdint.h> 9 10 #include "src/base/logging.h" 11 12 namespace v8 { 13 namespace internal { 14 15 // This "Do It Yourself Floating Point" class implements a floating-point number 16 // with a uint64 significand and an int exponent. Normalized DiyFp numbers will 17 // have the most significant bit of the significand set. 18 // Multiplication and Subtraction do not normalize their results. 19 // DiyFp are not designed to contain special doubles (NaN and Infinity). 20 class DiyFp { 21 public: 22 static const int kSignificandSize = 64; 23 DiyFp()24 DiyFp() : f_(0), e_(0) {} DiyFp(uint64_t f,int e)25 DiyFp(uint64_t f, int e) : f_(f), e_(e) {} 26 27 // this = this - other. 28 // The exponents of both numbers must be the same and the significand of this 29 // must be bigger than the significand of other. 30 // The result will not be normalized. Subtract(const DiyFp & other)31 void Subtract(const DiyFp& other) { 32 DCHECK(e_ == other.e_); 33 DCHECK(f_ >= other.f_); 34 f_ -= other.f_; 35 } 36 37 // Returns a - b. 38 // The exponents of both numbers must be the same and this must be bigger 39 // than other. The result will not be normalized. Minus(const DiyFp & a,const DiyFp & b)40 static DiyFp Minus(const DiyFp& a, const DiyFp& b) { 41 DiyFp result = a; 42 result.Subtract(b); 43 return result; 44 } 45 46 47 // this = this * other. 48 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_DIY_FP_H_ 100