]>
git.saurik.com Git - apple/javascriptcore.git/blob - runtime/Uint16WithFraction.h
2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef Uint16WithFraction_h
27 #define Uint16WithFraction_h
29 #include <wtf/MathExtras.h>
33 // Would be nice if this was a static const member, but the OS X linker
34 // seems to want a symbol in the binary in that case...
35 #define oneGreaterThanMaxUInt16 0x10000
37 // A uint16_t with an infinite precision fraction. Upon overflowing
38 // the uint16_t range, this class will clamp to oneGreaterThanMaxUInt16.
39 // This is used in converting the fraction part of a number to a string.
40 class Uint16WithFraction
{
42 explicit Uint16WithFraction(double number
, uint16_t divideByExponent
= 0)
44 ASSERT(number
&& isfinite(number
) && !signbit(number
));
46 // Check for values out of uint16_t range.
47 if (number
>= oneGreaterThanMaxUInt16
) {
48 m_values
.append(oneGreaterThanMaxUInt16
);
53 // Append the units to m_values.
54 double integerPart
= floor(number
);
55 m_values
.append(static_cast<uint32_t>(integerPart
));
60 decomposeDouble(number
- integerPart
, sign
, exponent
, mantissa
);
61 ASSERT(!sign
&& exponent
< 0);
62 exponent
-= divideByExponent
;
64 int32_t zeroBits
= -exponent
;
67 // Append the append words for to m_values.
68 while (zeroBits
>= 32) {
73 // Left align the 53 bits of the mantissa within 96 bits.
75 values
[0] = static_cast<uint32_t>(mantissa
>> 21);
76 values
[1] = static_cast<uint32_t>(mantissa
<< 11);
78 // Shift based on the remainder of the exponent.
80 values
[2] = values
[1] << (32 - zeroBits
);
81 values
[1] = (values
[1] >> zeroBits
) | (values
[0] << (32 - zeroBits
));
82 values
[0] = (values
[0] >> zeroBits
);
84 m_values
.append(values
[0]);
85 m_values
.append(values
[1]);
86 m_values
.append(values
[2]);
88 // Canonicalize; remove any trailing zeros.
89 while (m_values
.size() > 1 && !m_values
.last())
90 m_values
.removeLast();
92 // Count the number of leading zero, this is useful in optimizing multiplies.
94 while (m_leadingZeros
< m_values
.size() && !m_values
[m_leadingZeros
])
98 Uint16WithFraction
& operator*=(uint16_t multiplier
)
100 ASSERT(checkConsistency());
102 // iteratate backwards over the fraction until we reach the leading zeros,
103 // passing the carry from one calculation into the next.
104 uint64_t accumulator
= 0;
105 for (size_t i
= m_values
.size(); i
> m_leadingZeros
; ) {
107 accumulator
+= static_cast<uint64_t>(m_values
[i
]) * static_cast<uint64_t>(multiplier
);
108 m_values
[i
] = static_cast<uint32_t>(accumulator
);
112 if (!m_leadingZeros
) {
113 // With a multiplicand and multiplier in the uint16_t range, this cannot carry
114 // (even allowing for the infinity value).
115 ASSERT(!accumulator
);
116 // Check for overflow & clamp to 'infinity'.
117 if (m_values
[0] >= oneGreaterThanMaxUInt16
) {
119 m_values
[0] = oneGreaterThanMaxUInt16
;
123 } else if (accumulator
) {
124 // Check for carry from the last multiply, if so overwrite last leading zero.
125 m_values
[--m_leadingZeros
] = static_cast<uint32_t>(accumulator
);
126 // The limited range of the multiplier should mean that even if we carry into
127 // the units, we don't need to check for overflow of the uint16_t range.
128 ASSERT(m_values
[0] < oneGreaterThanMaxUInt16
);
131 // Multiplication by an even value may introduce trailing zeros; if so, clean them
132 // up. (Keeping the value in a normalized form makes some of the comparison operations
134 while (m_values
.size() > 1 && !m_values
.last())
135 m_values
.removeLast();
136 ASSERT(checkConsistency());
140 bool operator<(const Uint16WithFraction
& other
)
142 ASSERT(checkConsistency());
143 ASSERT(other
.checkConsistency());
145 // Iterate over the common lengths of arrays.
146 size_t minSize
= std::min(m_values
.size(), other
.m_values
.size());
147 for (size_t index
= 0; index
< minSize
; ++index
) {
148 // If we find a value that is not equal, compare and return.
149 uint32_t fromThis
= m_values
[index
];
150 uint32_t fromOther
= other
.m_values
[index
];
151 if (fromThis
!= fromOther
)
152 return fromThis
< fromOther
;
154 // If these numbers have the same lengths, they are equal,
155 // otherwise which ever number has a longer fraction in larger.
156 return other
.m_values
.size() > minSize
;
159 // Return the floor (non-fractional portion) of the number, clearing this to zero,
160 // leaving the fractional part unchanged.
161 uint32_t floorAndSubtract()
163 // 'floor' is simple the integer portion of the value.
164 uint32_t floor
= m_values
[0];
166 // If floor is non-zero,
170 while (m_leadingZeros
< m_values
.size() && !m_values
[m_leadingZeros
])
177 // Compare this value to 0.5, returns -1 for less than, 0 for equal, 1 for greater.
180 ASSERT(checkConsistency());
181 // If units != 0, this is greater than 0.5.
184 // If size == 1 this value is 0, hence < 0.5.
185 if (m_values
.size() == 1)
188 if (m_values
[1] > 0x80000000ul
)
190 if (m_values
[1] < 0x80000000ul
)
192 // Check for more words - since normalized numbers have no trailing zeros, if
193 // there are more that two digits we can assume at least one more is non-zero,
194 // and hence the value is > 0.5.
195 return m_values
.size() > 2 ? 1 : 0;
198 // Return true if the sum of this plus addend would be greater than 1.
199 bool sumGreaterThanOne(const Uint16WithFraction
& addend
)
201 ASSERT(checkConsistency());
202 ASSERT(addend
.checkConsistency());
204 // First, sum the units. If the result is greater than one, return true.
205 // If equal to one, return true if either number has a fractional part.
206 uint32_t sum
= m_values
[0] + addend
.m_values
[0];
208 return sum
> 1 || std::max(m_values
.size(), addend
.m_values
.size()) > 1;
210 // We could still produce a result greater than zero if addition of the next
211 // word from the fraction were to carry, leaving a result > 0.
213 // Iterate over the common lengths of arrays.
214 size_t minSize
= std::min(m_values
.size(), addend
.m_values
.size());
215 for (size_t index
= 1; index
< minSize
; ++index
) {
216 // Sum the next word from this & the addend.
217 uint32_t fromThis
= m_values
[index
];
218 uint32_t fromAddend
= addend
.m_values
[index
];
219 sum
= fromThis
+ fromAddend
;
221 // Check for overflow. If so, check whether the remaining result is non-zero,
222 // or if there are any further words in the fraction.
224 return sum
|| (index
+ 1) < std::max(m_values
.size(), addend
.m_values
.size());
226 // If the sum is uint32_t max, then we would carry a 1 if addition of the next
227 // digits in the number were to overflow.
228 if (sum
!= 0xFFFFFFFF)
235 bool checkConsistency() const
237 // All values should have at least one value.
238 return (m_values
.size())
239 // The units value must be a uint16_t, or the value is the overflow value.
240 && (m_values
[0] < oneGreaterThanMaxUInt16
|| (m_values
[0] == oneGreaterThanMaxUInt16
&& m_values
.size() == 1))
241 // There should be no trailing zeros (unless this value is zero!).
242 && (m_values
.last() || m_values
.size() == 1);
245 // The internal storage of the number. This vector is always at least one entry in size,
246 // with the first entry holding the portion of the number greater than zero. The first
247 // value always hold a value in the uint16_t range, or holds the value oneGreaterThanMaxUInt16 to
248 // indicate the value has overflowed to >= 0x10000. If the units value is oneGreaterThanMaxUInt16,
249 // there can be no fraction (size must be 1).
251 // Subsequent values in the array represent portions of the fractional part of this number.
252 // The total value of the number is the sum of (m_values[i] / pow(2^32, i)), for each i
253 // in the array. The vector should contain no trailing zeros, except for the value '0',
254 // represented by a vector contianing a single zero value. These constraints are checked
255 // by 'checkConsistency()', above.
257 // The inline capacity of the vector is set to be able to contain any IEEE double (1 for
258 // the units column, 32 for zeros introduced due to an exponent up to -3FE, and 2 for
259 // bits taken from the mantissa).
260 Vector
<uint32_t, 36> m_values
;
262 // Cache a count of the number of leading zeros in m_values. We can use this to optimize
263 // methods that would otherwise need visit all words in the vector, e.g. multiplication.
264 size_t m_leadingZeros
;