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_DIY_FP_H_
29 : #define V8_DIY_FP_H_
30 :
31 : namespace v8 {
32 : namespace internal {
33 :
34 : // This "Do It Yourself Floating Point" class implements a floating-point number
35 : // with a uint64 significand and an int exponent. Normalized DiyFp numbers will
36 : // have the most significant bit of the significand set.
37 : // Multiplication and Subtraction do not normalize their results.
38 : // DiyFp are not designed to contain special doubles (NaN and Infinity).
39 : class DiyFp {
40 : public:
41 : static const int kSignificandSize = 64;
42 :
43 852028 : DiyFp() : f_(0), e_(0) {}
44 1704056 : DiyFp(uint64_t f, int e) : f_(f), e_(e) {}
45 :
46 : // this = this - other.
47 : // The exponents of both numbers must be the same and the significand of this
48 : // must be bigger than the significand of other.
49 : // The result will not be normalized.
50 426014 : void Subtract(const DiyFp& other) {
51 426014 : ASSERT(e_ == other.e_);
52 426014 : ASSERT(f_ >= other.f_);
53 426014 : f_ -= other.f_;
54 426014 : }
55 :
56 : // Returns a - b.
57 : // The exponents of both numbers must be the same and this must be bigger
58 : // than other. The result will not be normalized.
59 426014 : static DiyFp Minus(const DiyFp& a, const DiyFp& b) {
60 426014 : DiyFp result = a;
61 426014 : result.Subtract(b);
62 : return result;
63 : }
64 :
65 :
66 : // this = this * other.
67 : void Multiply(const DiyFp& other);
68 :
69 : // returns a * b;
70 639021 : static DiyFp Times(const DiyFp& a, const DiyFp& b) {
71 639021 : DiyFp result = a;
72 639021 : result.Multiply(b);
73 : return result;
74 : }
75 :
76 213007 : void Normalize() {
77 213007 : ASSERT(f_ != 0);
78 213007 : uint64_t f = f_;
79 213007 : int e = e_;
80 :
81 : // This method is mainly called for normalizing boundaries. In general
82 : // boundaries need to be shifted by 10 bits. We thus optimize for this case.
83 213007 : const uint64_t k10MSBits = V8_2PART_UINT64_C(0xFFC00000, 00000000);
84 639021 : while ((f & k10MSBits) == 0) {
85 213007 : f <<= 10;
86 213007 : e -= 10;
87 : }
88 426014 : while ((f & kUint64MSB) == 0) {
89 0 : f <<= 1;
90 0 : e--;
91 : }
92 213007 : f_ = f;
93 213007 : e_ = e;
94 213007 : }
95 :
96 213007 : static DiyFp Normalize(const DiyFp& a) {
97 213007 : DiyFp result = a;
98 213007 : result.Normalize();
99 : return result;
100 : }
101 :
102 10398033 : uint64_t f() const { return f_; }
103 11978400 : int e() const { return e_; }
104 :
105 3513835 : void set_f(uint64_t new_value) { f_ = new_value; }
106 3513835 : void set_e(int new_value) { e_ = new_value; }
107 :
108 : private:
109 : static const uint64_t kUint64MSB = V8_2PART_UINT64_C(0x80000000, 00000000);
110 :
111 : uint64_t f_;
112 : int e_;
113 : };
114 :
115 : } } // namespace v8::internal
116 :
117 : #endif // V8_DIY_FP_H_
|