]>
Commit | Line | Data |
---|---|---|
1d09f67e TL |
1 | // Licensed to the Apache Software Foundation (ASF) under one |
2 | // or more contributor license agreements. See the NOTICE file | |
3 | // distributed with this work for additional information | |
4 | // regarding copyright ownership. The ASF licenses this file | |
5 | // to you under the Apache License, Version 2.0 (the | |
6 | // "License"); you may not use this file except in compliance | |
7 | // with the License. You may obtain a copy of the License at | |
8 | // | |
9 | // http://www.apache.org/licenses/LICENSE-2.0 | |
10 | // | |
11 | // Unless required by applicable law or agreed to in writing, | |
12 | // software distributed under the License is distributed on an | |
13 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
14 | // KIND, either express or implied. See the License for the | |
15 | // specific language governing permissions and limitations | |
16 | // under the License. | |
17 | ||
18 | #pragma once | |
19 | ||
20 | #include <array> | |
21 | #include <cstdint> | |
22 | #include <limits> | |
23 | #include <string> | |
24 | #include <type_traits> | |
25 | ||
26 | #include "arrow/util/endian.h" | |
27 | #include "arrow/util/macros.h" | |
28 | #include "arrow/util/type_traits.h" | |
29 | #include "arrow/util/visibility.h" | |
30 | ||
31 | namespace arrow { | |
32 | ||
33 | enum class DecimalStatus { | |
34 | kSuccess, | |
35 | kDivideByZero, | |
36 | kOverflow, | |
37 | kRescaleDataLoss, | |
38 | }; | |
39 | ||
40 | /// Represents a signed 128-bit integer in two's complement. | |
41 | /// | |
42 | /// This class is also compiled into LLVM IR - so, it should not have cpp references like | |
43 | /// streams and boost. | |
44 | class ARROW_EXPORT BasicDecimal128 { | |
45 | struct LittleEndianArrayTag {}; | |
46 | ||
47 | public: | |
48 | static constexpr int kBitWidth = 128; | |
49 | static constexpr int kMaxPrecision = 38; | |
50 | static constexpr int kMaxScale = 38; | |
51 | ||
52 | // A constructor tag to introduce a little-endian encoded array | |
53 | static constexpr LittleEndianArrayTag LittleEndianArray{}; | |
54 | ||
55 | /// \brief Create a BasicDecimal128 from the two's complement representation. | |
56 | #if ARROW_LITTLE_ENDIAN | |
57 | constexpr BasicDecimal128(int64_t high, uint64_t low) noexcept | |
58 | : low_bits_(low), high_bits_(high) {} | |
59 | #else | |
60 | constexpr BasicDecimal128(int64_t high, uint64_t low) noexcept | |
61 | : high_bits_(high), low_bits_(low) {} | |
62 | #endif | |
63 | ||
64 | /// \brief Create a BasicDecimal256 from the two's complement representation. | |
65 | /// | |
66 | /// Input array is assumed to be in native endianness. | |
67 | #if ARROW_LITTLE_ENDIAN | |
68 | constexpr BasicDecimal128(const std::array<uint64_t, 2>& array) noexcept | |
69 | : low_bits_(array[0]), high_bits_(static_cast<int64_t>(array[1])) {} | |
70 | #else | |
71 | constexpr BasicDecimal128(const std::array<uint64_t, 2>& array) noexcept | |
72 | : high_bits_(static_cast<int64_t>(array[0])), low_bits_(array[1]) {} | |
73 | #endif | |
74 | ||
75 | /// \brief Create a BasicDecimal128 from the two's complement representation. | |
76 | /// | |
77 | /// Input array is assumed to be in little endianness, with native endian elements. | |
78 | BasicDecimal128(LittleEndianArrayTag, const std::array<uint64_t, 2>& array) noexcept | |
79 | : BasicDecimal128(BitUtil::LittleEndianArray::ToNative(array)) {} | |
80 | ||
81 | /// \brief Empty constructor creates a BasicDecimal128 with a value of 0. | |
82 | constexpr BasicDecimal128() noexcept : BasicDecimal128(0, 0) {} | |
83 | ||
84 | /// \brief Convert any integer value into a BasicDecimal128. | |
85 | template <typename T, | |
86 | typename = typename std::enable_if< | |
87 | std::is_integral<T>::value && (sizeof(T) <= sizeof(uint64_t)), T>::type> | |
88 | constexpr BasicDecimal128(T value) noexcept | |
89 | : BasicDecimal128(value >= T{0} ? 0 : -1, static_cast<uint64_t>(value)) { // NOLINT | |
90 | } | |
91 | ||
92 | /// \brief Create a BasicDecimal128 from an array of bytes. Bytes are assumed to be in | |
93 | /// native-endian byte order. | |
94 | explicit BasicDecimal128(const uint8_t* bytes); | |
95 | ||
96 | /// \brief Negate the current value (in-place) | |
97 | BasicDecimal128& Negate(); | |
98 | ||
99 | /// \brief Absolute value (in-place) | |
100 | BasicDecimal128& Abs(); | |
101 | ||
102 | /// \brief Absolute value | |
103 | static BasicDecimal128 Abs(const BasicDecimal128& left); | |
104 | ||
105 | /// \brief Add a number to this one. The result is truncated to 128 bits. | |
106 | BasicDecimal128& operator+=(const BasicDecimal128& right); | |
107 | ||
108 | /// \brief Subtract a number from this one. The result is truncated to 128 bits. | |
109 | BasicDecimal128& operator-=(const BasicDecimal128& right); | |
110 | ||
111 | /// \brief Multiply this number by another number. The result is truncated to 128 bits. | |
112 | BasicDecimal128& operator*=(const BasicDecimal128& right); | |
113 | ||
114 | /// Divide this number by right and return the result. | |
115 | /// | |
116 | /// This operation is not destructive. | |
117 | /// The answer rounds to zero. Signs work like: | |
118 | /// 21 / 5 -> 4, 1 | |
119 | /// -21 / 5 -> -4, -1 | |
120 | /// 21 / -5 -> -4, 1 | |
121 | /// -21 / -5 -> 4, -1 | |
122 | /// \param[in] divisor the number to divide by | |
123 | /// \param[out] result the quotient | |
124 | /// \param[out] remainder the remainder after the division | |
125 | DecimalStatus Divide(const BasicDecimal128& divisor, BasicDecimal128* result, | |
126 | BasicDecimal128* remainder) const; | |
127 | ||
128 | /// \brief In-place division. | |
129 | BasicDecimal128& operator/=(const BasicDecimal128& right); | |
130 | ||
131 | /// \brief Bitwise "or" between two BasicDecimal128. | |
132 | BasicDecimal128& operator|=(const BasicDecimal128& right); | |
133 | ||
134 | /// \brief Bitwise "and" between two BasicDecimal128. | |
135 | BasicDecimal128& operator&=(const BasicDecimal128& right); | |
136 | ||
137 | /// \brief Shift left by the given number of bits. | |
138 | BasicDecimal128& operator<<=(uint32_t bits); | |
139 | ||
140 | /// \brief Shift right by the given number of bits. Negative values will | |
141 | BasicDecimal128& operator>>=(uint32_t bits); | |
142 | ||
143 | /// \brief Get the high bits of the two's complement representation of the number. | |
144 | inline constexpr int64_t high_bits() const { return high_bits_; } | |
145 | ||
146 | /// \brief Get the low bits of the two's complement representation of the number. | |
147 | inline constexpr uint64_t low_bits() const { return low_bits_; } | |
148 | ||
149 | /// \brief Get the bits of the two's complement representation of the number. | |
150 | /// | |
151 | /// The 2 elements are in native endian order. The bits within each uint64_t element | |
152 | /// are in native endian order. For example, on a little endian machine, | |
153 | /// BasicDecimal128(123).native_endian_array() = {123, 0}; | |
154 | /// but on a big endian machine, | |
155 | /// BasicDecimal128(123).native_endian_array() = {0, 123}; | |
156 | inline std::array<uint64_t, 2> native_endian_array() const { | |
157 | #if ARROW_LITTLE_ENDIAN | |
158 | return {low_bits_, static_cast<uint64_t>(high_bits_)}; | |
159 | #else | |
160 | return {static_cast<uint64_t>(high_bits_), low_bits_}; | |
161 | #endif | |
162 | } | |
163 | ||
164 | /// \brief Get the bits of the two's complement representation of the number. | |
165 | /// | |
166 | /// The 2 elements are in little endian order. However, the bits within each | |
167 | /// uint64_t element are in native endian order. | |
168 | /// For example, BasicDecimal128(123).little_endian_array() = {123, 0}; | |
169 | inline std::array<uint64_t, 2> little_endian_array() const { | |
170 | return {low_bits_, static_cast<uint64_t>(high_bits_)}; | |
171 | } | |
172 | ||
173 | inline const uint8_t* native_endian_bytes() const { | |
174 | #if ARROW_LITTLE_ENDIAN | |
175 | return reinterpret_cast<const uint8_t*>(&low_bits_); | |
176 | #else | |
177 | return reinterpret_cast<const uint8_t*>(&high_bits_); | |
178 | #endif | |
179 | } | |
180 | ||
181 | inline uint8_t* mutable_native_endian_bytes() { | |
182 | #if ARROW_LITTLE_ENDIAN | |
183 | return reinterpret_cast<uint8_t*>(&low_bits_); | |
184 | #else | |
185 | return reinterpret_cast<uint8_t*>(&high_bits_); | |
186 | #endif | |
187 | } | |
188 | ||
189 | /// \brief Return the raw bytes of the value in native-endian byte order. | |
190 | std::array<uint8_t, 16> ToBytes() const; | |
191 | void ToBytes(uint8_t* out) const; | |
192 | ||
193 | /// \brief separate the integer and fractional parts for the given scale. | |
194 | void GetWholeAndFraction(int32_t scale, BasicDecimal128* whole, | |
195 | BasicDecimal128* fraction) const; | |
196 | ||
197 | /// \brief Scale multiplier for given scale value. | |
198 | static const BasicDecimal128& GetScaleMultiplier(int32_t scale); | |
199 | /// \brief Half-scale multiplier for given scale value. | |
200 | static const BasicDecimal128& GetHalfScaleMultiplier(int32_t scale); | |
201 | ||
202 | /// \brief Convert BasicDecimal128 from one scale to another | |
203 | DecimalStatus Rescale(int32_t original_scale, int32_t new_scale, | |
204 | BasicDecimal128* out) const; | |
205 | ||
206 | /// \brief Scale up. | |
207 | BasicDecimal128 IncreaseScaleBy(int32_t increase_by) const; | |
208 | ||
209 | /// \brief Scale down. | |
210 | /// - If 'round' is true, the right-most digits are dropped and the result value is | |
211 | /// rounded up (+1 for +ve, -1 for -ve) based on the value of the dropped digits | |
212 | /// (>= 10^reduce_by / 2). | |
213 | /// - If 'round' is false, the right-most digits are simply dropped. | |
214 | BasicDecimal128 ReduceScaleBy(int32_t reduce_by, bool round = true) const; | |
215 | ||
216 | /// \brief Whether this number fits in the given precision | |
217 | /// | |
218 | /// Return true if the number of significant digits is less or equal to `precision`. | |
219 | bool FitsInPrecision(int32_t precision) const; | |
220 | ||
221 | // returns 1 for positive and zero decimal values, -1 for negative decimal values. | |
222 | inline int64_t Sign() const { return 1 | (high_bits_ >> 63); } | |
223 | ||
224 | /// \brief count the number of leading binary zeroes. | |
225 | int32_t CountLeadingBinaryZeros() const; | |
226 | ||
227 | /// \brief Get the maximum valid unscaled decimal value. | |
228 | static const BasicDecimal128& GetMaxValue(); | |
229 | ||
230 | /// \brief Get the maximum decimal value (is not a valid value). | |
231 | static inline constexpr BasicDecimal128 GetMaxSentinel() { | |
232 | return BasicDecimal128(/*high=*/std::numeric_limits<int64_t>::max(), | |
233 | /*low=*/std::numeric_limits<uint64_t>::max()); | |
234 | } | |
235 | /// \brief Get the minimum decimal value (is not a valid value). | |
236 | static inline constexpr BasicDecimal128 GetMinSentinel() { | |
237 | return BasicDecimal128(/*high=*/std::numeric_limits<int64_t>::min(), | |
238 | /*low=*/std::numeric_limits<uint64_t>::min()); | |
239 | } | |
240 | ||
241 | private: | |
242 | #if ARROW_LITTLE_ENDIAN | |
243 | uint64_t low_bits_; | |
244 | int64_t high_bits_; | |
245 | #else | |
246 | int64_t high_bits_; | |
247 | uint64_t low_bits_; | |
248 | #endif | |
249 | }; | |
250 | ||
251 | ARROW_EXPORT bool operator==(const BasicDecimal128& left, const BasicDecimal128& right); | |
252 | ARROW_EXPORT bool operator!=(const BasicDecimal128& left, const BasicDecimal128& right); | |
253 | ARROW_EXPORT bool operator<(const BasicDecimal128& left, const BasicDecimal128& right); | |
254 | ARROW_EXPORT bool operator<=(const BasicDecimal128& left, const BasicDecimal128& right); | |
255 | ARROW_EXPORT bool operator>(const BasicDecimal128& left, const BasicDecimal128& right); | |
256 | ARROW_EXPORT bool operator>=(const BasicDecimal128& left, const BasicDecimal128& right); | |
257 | ||
258 | ARROW_EXPORT BasicDecimal128 operator-(const BasicDecimal128& operand); | |
259 | ARROW_EXPORT BasicDecimal128 operator~(const BasicDecimal128& operand); | |
260 | ARROW_EXPORT BasicDecimal128 operator+(const BasicDecimal128& left, | |
261 | const BasicDecimal128& right); | |
262 | ARROW_EXPORT BasicDecimal128 operator-(const BasicDecimal128& left, | |
263 | const BasicDecimal128& right); | |
264 | ARROW_EXPORT BasicDecimal128 operator*(const BasicDecimal128& left, | |
265 | const BasicDecimal128& right); | |
266 | ARROW_EXPORT BasicDecimal128 operator/(const BasicDecimal128& left, | |
267 | const BasicDecimal128& right); | |
268 | ARROW_EXPORT BasicDecimal128 operator%(const BasicDecimal128& left, | |
269 | const BasicDecimal128& right); | |
270 | ||
271 | class ARROW_EXPORT BasicDecimal256 { | |
272 | private: | |
273 | // Due to a bug in clang, we have to declare the extend method prior to its | |
274 | // usage. | |
275 | template <typename T> | |
276 | inline static constexpr uint64_t extend(T low_bits) noexcept { | |
277 | return low_bits >= T() ? uint64_t{0} : ~uint64_t{0}; | |
278 | } | |
279 | ||
280 | struct LittleEndianArrayTag {}; | |
281 | ||
282 | public: | |
283 | static constexpr int kBitWidth = 256; | |
284 | static constexpr int kMaxPrecision = 76; | |
285 | static constexpr int kMaxScale = 76; | |
286 | ||
287 | // A constructor tag to denote a little-endian encoded array | |
288 | static constexpr LittleEndianArrayTag LittleEndianArray{}; | |
289 | ||
290 | /// \brief Create a BasicDecimal256 from the two's complement representation. | |
291 | /// | |
292 | /// Input array is assumed to be in native endianness. | |
293 | constexpr BasicDecimal256(const std::array<uint64_t, 4>& array) noexcept | |
294 | : array_(array) {} | |
295 | ||
296 | /// \brief Create a BasicDecimal256 from the two's complement representation. | |
297 | /// | |
298 | /// Input array is assumed to be in little endianness, with native endian elements. | |
299 | BasicDecimal256(LittleEndianArrayTag, const std::array<uint64_t, 4>& array) noexcept | |
300 | : BasicDecimal256(BitUtil::LittleEndianArray::ToNative(array)) {} | |
301 | ||
302 | /// \brief Empty constructor creates a BasicDecimal256 with a value of 0. | |
303 | constexpr BasicDecimal256() noexcept : array_({0, 0, 0, 0}) {} | |
304 | ||
305 | /// \brief Convert any integer value into a BasicDecimal256. | |
306 | template <typename T, | |
307 | typename = typename std::enable_if< | |
308 | std::is_integral<T>::value && (sizeof(T) <= sizeof(uint64_t)), T>::type> | |
309 | constexpr BasicDecimal256(T value) noexcept | |
310 | : array_(BitUtil::LittleEndianArray::ToNative<uint64_t, 4>( | |
311 | {static_cast<uint64_t>(value), extend(value), extend(value), | |
312 | extend(value)})) {} | |
313 | ||
314 | explicit BasicDecimal256(const BasicDecimal128& value) noexcept | |
315 | : array_(BitUtil::LittleEndianArray::ToNative<uint64_t, 4>( | |
316 | {value.low_bits(), static_cast<uint64_t>(value.high_bits()), | |
317 | extend(value.high_bits()), extend(value.high_bits())})) {} | |
318 | ||
319 | /// \brief Create a BasicDecimal256 from an array of bytes. Bytes are assumed to be in | |
320 | /// native-endian byte order. | |
321 | explicit BasicDecimal256(const uint8_t* bytes); | |
322 | ||
323 | /// \brief Negate the current value (in-place) | |
324 | BasicDecimal256& Negate(); | |
325 | ||
326 | /// \brief Absolute value (in-place) | |
327 | BasicDecimal256& Abs(); | |
328 | ||
329 | /// \brief Absolute value | |
330 | static BasicDecimal256 Abs(const BasicDecimal256& left); | |
331 | ||
332 | /// \brief Add a number to this one. The result is truncated to 256 bits. | |
333 | BasicDecimal256& operator+=(const BasicDecimal256& right); | |
334 | ||
335 | /// \brief Subtract a number from this one. The result is truncated to 256 bits. | |
336 | BasicDecimal256& operator-=(const BasicDecimal256& right); | |
337 | ||
338 | /// \brief Get the bits of the two's complement representation of the number. | |
339 | /// | |
340 | /// The 4 elements are in native endian order. The bits within each uint64_t element | |
341 | /// are in native endian order. For example, on a little endian machine, | |
342 | /// BasicDecimal256(123).native_endian_array() = {123, 0, 0, 0}; | |
343 | /// BasicDecimal256(-2).native_endian_array() = {0xFF...FE, 0xFF...FF, 0xFF...FF, | |
344 | /// 0xFF...FF}. | |
345 | /// while on a big endian machine, | |
346 | /// BasicDecimal256(123).native_endian_array() = {0, 0, 0, 123}; | |
347 | /// BasicDecimal256(-2).native_endian_array() = {0xFF...FF, 0xFF...FF, 0xFF...FF, | |
348 | /// 0xFF...FE}. | |
349 | inline const std::array<uint64_t, 4>& native_endian_array() const { return array_; } | |
350 | ||
351 | /// \brief Get the bits of the two's complement representation of the number. | |
352 | /// | |
353 | /// The 4 elements are in little endian order. However, the bits within each | |
354 | /// uint64_t element are in native endian order. | |
355 | /// For example, BasicDecimal256(123).little_endian_array() = {123, 0}; | |
356 | inline const std::array<uint64_t, 4> little_endian_array() const { | |
357 | return BitUtil::LittleEndianArray::FromNative(array_); | |
358 | } | |
359 | ||
360 | inline const uint8_t* native_endian_bytes() const { | |
361 | return reinterpret_cast<const uint8_t*>(array_.data()); | |
362 | } | |
363 | ||
364 | inline uint8_t* mutable_native_endian_bytes() { | |
365 | return reinterpret_cast<uint8_t*>(array_.data()); | |
366 | } | |
367 | ||
368 | /// \brief Get the lowest bits of the two's complement representation of the number. | |
369 | inline uint64_t low_bits() const { return BitUtil::LittleEndianArray::Make(array_)[0]; } | |
370 | ||
371 | /// \brief Return the raw bytes of the value in native-endian byte order. | |
372 | std::array<uint8_t, 32> ToBytes() const; | |
373 | void ToBytes(uint8_t* out) const; | |
374 | ||
375 | /// \brief Scale multiplier for given scale value. | |
376 | static const BasicDecimal256& GetScaleMultiplier(int32_t scale); | |
377 | /// \brief Half-scale multiplier for given scale value. | |
378 | static const BasicDecimal256& GetHalfScaleMultiplier(int32_t scale); | |
379 | ||
380 | /// \brief Convert BasicDecimal256 from one scale to another | |
381 | DecimalStatus Rescale(int32_t original_scale, int32_t new_scale, | |
382 | BasicDecimal256* out) const; | |
383 | ||
384 | /// \brief Scale up. | |
385 | BasicDecimal256 IncreaseScaleBy(int32_t increase_by) const; | |
386 | ||
387 | /// \brief Scale down. | |
388 | /// - If 'round' is true, the right-most digits are dropped and the result value is | |
389 | /// rounded up (+1 for positive, -1 for negative) based on the value of the | |
390 | /// dropped digits (>= 10^reduce_by / 2). | |
391 | /// - If 'round' is false, the right-most digits are simply dropped. | |
392 | BasicDecimal256 ReduceScaleBy(int32_t reduce_by, bool round = true) const; | |
393 | ||
394 | /// \brief Whether this number fits in the given precision | |
395 | /// | |
396 | /// Return true if the number of significant digits is less or equal to `precision`. | |
397 | bool FitsInPrecision(int32_t precision) const; | |
398 | ||
399 | inline int64_t Sign() const { | |
400 | return 1 | (static_cast<int64_t>(BitUtil::LittleEndianArray::Make(array_)[3]) >> 63); | |
401 | } | |
402 | ||
403 | inline int64_t IsNegative() const { | |
404 | return static_cast<int64_t>(BitUtil::LittleEndianArray::Make(array_)[3]) < 0; | |
405 | } | |
406 | ||
407 | /// \brief Multiply this number by another number. The result is truncated to 256 bits. | |
408 | BasicDecimal256& operator*=(const BasicDecimal256& right); | |
409 | ||
410 | /// Divide this number by right and return the result. | |
411 | /// | |
412 | /// This operation is not destructive. | |
413 | /// The answer rounds to zero. Signs work like: | |
414 | /// 21 / 5 -> 4, 1 | |
415 | /// -21 / 5 -> -4, -1 | |
416 | /// 21 / -5 -> -4, 1 | |
417 | /// -21 / -5 -> 4, -1 | |
418 | /// \param[in] divisor the number to divide by | |
419 | /// \param[out] result the quotient | |
420 | /// \param[out] remainder the remainder after the division | |
421 | DecimalStatus Divide(const BasicDecimal256& divisor, BasicDecimal256* result, | |
422 | BasicDecimal256* remainder) const; | |
423 | ||
424 | /// \brief Shift left by the given number of bits. | |
425 | BasicDecimal256& operator<<=(uint32_t bits); | |
426 | ||
427 | /// \brief In-place division. | |
428 | BasicDecimal256& operator/=(const BasicDecimal256& right); | |
429 | ||
430 | /// \brief Get the maximum decimal value (is not a valid value). | |
431 | static inline constexpr BasicDecimal256 GetMaxSentinel() { | |
432 | #if ARROW_LITTLE_ENDIAN | |
433 | return BasicDecimal256({std::numeric_limits<uint64_t>::max(), | |
434 | std::numeric_limits<uint64_t>::max(), | |
435 | std::numeric_limits<uint64_t>::max(), | |
436 | static_cast<uint64_t>(std::numeric_limits<int64_t>::max())}); | |
437 | #else | |
438 | return BasicDecimal256({static_cast<uint64_t>(std::numeric_limits<int64_t>::max()), | |
439 | std::numeric_limits<uint64_t>::max(), | |
440 | std::numeric_limits<uint64_t>::max(), | |
441 | std::numeric_limits<uint64_t>::max()}); | |
442 | #endif | |
443 | } | |
444 | /// \brief Get the minimum decimal value (is not a valid value). | |
445 | static inline constexpr BasicDecimal256 GetMinSentinel() { | |
446 | #if ARROW_LITTLE_ENDIAN | |
447 | return BasicDecimal256( | |
448 | {0, 0, 0, static_cast<uint64_t>(std::numeric_limits<int64_t>::min())}); | |
449 | #else | |
450 | return BasicDecimal256( | |
451 | {static_cast<uint64_t>(std::numeric_limits<int64_t>::min()), 0, 0, 0}); | |
452 | #endif | |
453 | } | |
454 | ||
455 | private: | |
456 | std::array<uint64_t, 4> array_; | |
457 | }; | |
458 | ||
459 | ARROW_EXPORT inline bool operator==(const BasicDecimal256& left, | |
460 | const BasicDecimal256& right) { | |
461 | return left.native_endian_array() == right.native_endian_array(); | |
462 | } | |
463 | ||
464 | ARROW_EXPORT inline bool operator!=(const BasicDecimal256& left, | |
465 | const BasicDecimal256& right) { | |
466 | return left.native_endian_array() != right.native_endian_array(); | |
467 | } | |
468 | ||
469 | ARROW_EXPORT bool operator<(const BasicDecimal256& left, const BasicDecimal256& right); | |
470 | ||
471 | ARROW_EXPORT inline bool operator<=(const BasicDecimal256& left, | |
472 | const BasicDecimal256& right) { | |
473 | return !operator<(right, left); | |
474 | } | |
475 | ||
476 | ARROW_EXPORT inline bool operator>(const BasicDecimal256& left, | |
477 | const BasicDecimal256& right) { | |
478 | return operator<(right, left); | |
479 | } | |
480 | ||
481 | ARROW_EXPORT inline bool operator>=(const BasicDecimal256& left, | |
482 | const BasicDecimal256& right) { | |
483 | return !operator<(left, right); | |
484 | } | |
485 | ||
486 | ARROW_EXPORT BasicDecimal256 operator-(const BasicDecimal256& operand); | |
487 | ARROW_EXPORT BasicDecimal256 operator~(const BasicDecimal256& operand); | |
488 | ARROW_EXPORT BasicDecimal256 operator+(const BasicDecimal256& left, | |
489 | const BasicDecimal256& right); | |
490 | ARROW_EXPORT BasicDecimal256 operator*(const BasicDecimal256& left, | |
491 | const BasicDecimal256& right); | |
492 | ARROW_EXPORT BasicDecimal256 operator/(const BasicDecimal256& left, | |
493 | const BasicDecimal256& right); | |
494 | } // namespace arrow |