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 1029340 : DiyFp() : f_(0), e_(0) {}
44 2058680 : 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 514670 : void Subtract(const DiyFp& other) {
51 514670 : ASSERT(e_ == other.e_);
52 514670 : ASSERT(f_ >= other.f_);
53 514670 : f_ -= other.f_;
54 514670 : }
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 514670 : static DiyFp Minus(const DiyFp& a, const DiyFp& b) {
60 514670 : DiyFp result = a;
61 514670 : 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 772005 : static DiyFp Times(const DiyFp& a, const DiyFp& b) {
71 772005 : DiyFp result = a;
72 772005 : result.Multiply(b);
73 : return result;
74 : }
75 :
76 257335 : void Normalize() {
77 257335 : ASSERT(f_ != 0);
78 257335 : uint64_t f = f_;
79 257335 : 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 257335 : const uint64_t k10MSBits = V8_2PART_UINT64_C(0xFFC00000, 00000000);
84 772005 : while ((f & k10MSBits) == 0) {
85 257335 : f <<= 10;
86 257335 : e -= 10;
87 : }
88 514670 : while ((f & kUint64MSB) == 0) {
89 0 : f <<= 1;
90 0 : e--;
91 : }
92 257335 : f_ = f;
93 257335 : e_ = e;
94 257335 : }
95 :
96 257335 : static DiyFp Normalize(const DiyFp& a) {
97 257335 : DiyFp result = a;
98 257335 : result.Normalize();
99 : return result;
100 : }
101 :
102 12188676 : uint64_t f() const { return f_; }
103 14232113 : int e() const { return e_; }
104 :
105 3963947 : void set_f(uint64_t new_value) { f_ = new_value; }
106 3963947 : 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_
|