Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-08-28 08:27:02

0001 // Licensed to the Apache Software Foundation (ASF) under one
0002 // or more contributor license agreements.  See the NOTICE file
0003 // distributed with this work for additional information
0004 // regarding copyright ownership.  The ASF licenses this file
0005 // to you under the Apache License, Version 2.0 (the
0006 // "License"); you may not use this file except in compliance
0007 // with the License.  You may obtain a copy of the License at
0008 //
0009 //   http://www.apache.org/licenses/LICENSE-2.0
0010 //
0011 // Unless required by applicable law or agreed to in writing,
0012 // software distributed under the License is distributed on an
0013 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0014 // KIND, either express or implied.  See the License for the
0015 // specific language governing permissions and limitations
0016 // under the License.
0017 
0018 #pragma once
0019 
0020 #include <array>
0021 #include <climits>
0022 #include <cstdint>
0023 #include <cstring>
0024 #include <limits>
0025 #include <string>
0026 #include <type_traits>
0027 
0028 #include "arrow/util/endian.h"
0029 #include "arrow/util/macros.h"
0030 #include "arrow/util/type_traits.h"
0031 #include "arrow/util/visibility.h"
0032 
0033 namespace arrow {
0034 
0035 enum class DecimalStatus {
0036   kSuccess,
0037   kDivideByZero,
0038   kOverflow,
0039   kRescaleDataLoss,
0040 };
0041 
0042 template <typename Derived, int BIT_WIDTH, int NWORDS = BIT_WIDTH / 64>
0043 class GenericBasicDecimal {
0044  protected:
0045   struct LittleEndianArrayTag {};
0046 
0047 #if ARROW_LITTLE_ENDIAN
0048   static constexpr int kHighWordIndex = NWORDS - 1;
0049   static constexpr int kLowWordIndex = 0;
0050 #else
0051   static constexpr int kHighWordIndex = 0;
0052   static constexpr int kLowWordIndex = NWORDS - 1;
0053 #endif
0054 
0055  public:
0056   static constexpr int kBitWidth = BIT_WIDTH;
0057   static constexpr int kByteWidth = kBitWidth / 8;
0058   static constexpr int kNumWords = NWORDS;
0059 
0060   // A constructor tag to introduce a little-endian encoded array
0061   static constexpr LittleEndianArrayTag LittleEndianArray{};
0062 
0063   using WordArray = std::array<uint64_t, NWORDS>;
0064 
0065   /// \brief Empty constructor creates a decimal with a value of 0.
0066   constexpr GenericBasicDecimal() noexcept : array_({0}) {}
0067 
0068   /// \brief Create a decimal from the two's complement representation.
0069   ///
0070   /// Input array is assumed to be in native endianness.
0071   explicit constexpr GenericBasicDecimal(const WordArray& array) noexcept
0072       : array_(array) {}
0073 
0074   /// \brief Create a decimal from the two's complement representation.
0075   ///
0076   /// Input array is assumed to be in little endianness, with native endian elements.
0077   GenericBasicDecimal(LittleEndianArrayTag, const WordArray& array) noexcept
0078       : GenericBasicDecimal(bit_util::little_endian::ToNative(array)) {}
0079 
0080   /// \brief Create a decimal from any integer not wider than 64 bits.
0081   template <typename T,
0082             typename = typename std::enable_if<
0083                 std::is_integral<T>::value && (sizeof(T) <= sizeof(uint64_t)), T>::type>
0084   constexpr GenericBasicDecimal(T value) noexcept  // NOLINT(runtime/explicit)
0085       : array_(WordsFromLowBits(value)) {}
0086 
0087   /// \brief Create a decimal from an array of bytes.
0088   ///
0089   /// Bytes are assumed to be in native-endian byte order.
0090   explicit GenericBasicDecimal(const uint8_t* bytes) {
0091     memcpy(array_.data(), bytes, sizeof(array_));
0092   }
0093 
0094   /// \brief Get the bits of the two's complement representation of the number.
0095   ///
0096   /// The elements are in native endian order. The bits within each uint64_t element
0097   /// are in native endian order. For example, on a little endian machine,
0098   /// BasicDecimal128(123).native_endian_array() = {123, 0};
0099   /// but on a big endian machine,
0100   /// BasicDecimal128(123).native_endian_array() = {0, 123};
0101   constexpr const WordArray& native_endian_array() const { return array_; }
0102 
0103   /// \brief Get the bits of the two's complement representation of the number.
0104   ///
0105   /// The elements are in little endian order. However, the bits within each
0106   /// uint64_t element are in native endian order.
0107   /// For example, BasicDecimal128(123).little_endian_array() = {123, 0};
0108   WordArray little_endian_array() const {
0109     return bit_util::little_endian::FromNative(array_);
0110   }
0111 
0112   const uint8_t* native_endian_bytes() const {
0113     return reinterpret_cast<const uint8_t*>(array_.data());
0114   }
0115 
0116   uint8_t* mutable_native_endian_bytes() {
0117     return reinterpret_cast<uint8_t*>(array_.data());
0118   }
0119 
0120   /// \brief Return the raw bytes of the value in native-endian byte order.
0121   std::array<uint8_t, kByteWidth> ToBytes() const {
0122     std::array<uint8_t, kByteWidth> out{{0}};
0123     memcpy(out.data(), array_.data(), kByteWidth);
0124     return out;
0125   }
0126 
0127   /// \brief Copy the raw bytes of the value in native-endian byte order.
0128   void ToBytes(uint8_t* out) const { memcpy(out, array_.data(), kByteWidth); }
0129 
0130   /// Return 1 if positive or zero, -1 if strictly negative.
0131   int64_t Sign() const {
0132     return 1 | (static_cast<int64_t>(array_[kHighWordIndex]) >> 63);
0133   }
0134 
0135   bool IsNegative() const { return static_cast<int64_t>(array_[kHighWordIndex]) < 0; }
0136 
0137   explicit operator bool() const { return array_ != WordArray{}; }
0138 
0139   friend bool operator==(const GenericBasicDecimal& left,
0140                          const GenericBasicDecimal& right) {
0141     return left.array_ == right.array_;
0142   }
0143 
0144   friend bool operator!=(const GenericBasicDecimal& left,
0145                          const GenericBasicDecimal& right) {
0146     return left.array_ != right.array_;
0147   }
0148 
0149  protected:
0150   WordArray array_;
0151 
0152   template <typename T>
0153   static constexpr uint64_t SignExtend(T low_bits) noexcept {
0154     return low_bits >= T{} ? uint64_t{0} : ~uint64_t{0};
0155   }
0156 
0157   template <typename T>
0158   static constexpr WordArray WordsFromLowBits(T low_bits) {
0159     WordArray words{};
0160     if (low_bits < T{}) {
0161       for (auto& word : words) {
0162         word = ~uint64_t{0};
0163       }
0164     }
0165     words[kLowWordIndex] = static_cast<uint64_t>(low_bits);
0166     return words;
0167   }
0168 };
0169 
0170 template <typename DigitType>
0171 class ARROW_EXPORT SmallBasicDecimal {
0172  public:
0173   static_assert(
0174       std::is_same_v<DigitType, int32_t> || std::is_same_v<DigitType, int64_t>,
0175       "for bitwidths larger than 64 bits use BasicDecimal128 and BasicDecimal256");
0176 
0177   static constexpr int kMaxPrecision = std::numeric_limits<DigitType>::digits10;
0178   static constexpr int kMaxScale = kMaxPrecision;
0179   static constexpr int kBitWidth = sizeof(DigitType) * CHAR_BIT;
0180   static constexpr int kByteWidth = sizeof(DigitType);
0181 
0182   using WordArray = std::array<std::make_unsigned_t<DigitType>, 1>;
0183 
0184   /// \brief Empty constructor creates a decimal with a value of 0.
0185   constexpr SmallBasicDecimal() noexcept : value_(0) {}
0186 
0187   /// \brief Create a decimal from any integer not wider than 64 bits.
0188   template <typename T,
0189             typename = typename std::enable_if<
0190                 std::is_integral<T>::value && (sizeof(T) <= sizeof(int64_t)), T>::type>
0191   constexpr SmallBasicDecimal(T value) noexcept  // NOLINT(runtime/explicit)
0192       : value_(static_cast<DigitType>(value)) {}
0193 
0194   /// \brief Create a decimal from an array of bytes.
0195   ///
0196   /// Bytes are assumed to be in native-endian byte order.
0197   explicit SmallBasicDecimal(const uint8_t* bytes) {
0198     memcpy(&value_, bytes, sizeof(value_));
0199   }
0200 
0201   constexpr const WordArray native_endian_array() const {
0202     return WordArray{static_cast<typename WordArray::value_type>(value_)};
0203   }
0204 
0205   constexpr const WordArray little_endian_array() const {
0206     return bit_util::little_endian::FromNative(
0207         WordArray{static_cast<typename WordArray::value_type>(value_)});
0208   }
0209 
0210   const uint8_t* native_endian_bytes() const {
0211     return reinterpret_cast<const uint8_t*>(&value_);
0212   }
0213 
0214   uint8_t* mutable_native_endian_bytes() { return reinterpret_cast<uint8_t*>(&value_); }
0215 
0216   /// \brief Return the raw bytes of the value in native-endian byte order.
0217   std::array<uint8_t, kByteWidth> ToBytes() const {
0218     std::array<uint8_t, kByteWidth> out{{0}};
0219     memcpy(out.data(), &value_, kByteWidth);
0220     return out;
0221   }
0222 
0223   /// \brief Copy the raw bytes of the value in native-endian byte order
0224   void ToBytes(uint8_t* out) const { memcpy(out, &value_, kByteWidth); }
0225 
0226   /// \brief Return 1 if positive or 0, -1 if strictly negative
0227   int64_t Sign() const { return 1 | (value_ >> (kBitWidth - 1)); }
0228 
0229   bool IsNegative() const { return value_ < 0; }
0230 
0231   explicit operator bool() const { return value_ != 0; }
0232 
0233   friend bool operator==(const SmallBasicDecimal& left, const SmallBasicDecimal& right) {
0234     return left.value_ == right.value_;
0235   }
0236 
0237   friend bool operator!=(const SmallBasicDecimal& left, const SmallBasicDecimal& right) {
0238     return left.value_ != right.value_;
0239   }
0240 
0241   DigitType value() const { return value_; }
0242 
0243   /// \brief count the number of leading binary zeroes.
0244   int32_t CountLeadingBinaryZeros() const;
0245 
0246   constexpr uint64_t low_bits() const { return static_cast<uint64_t>(value_); }
0247 
0248  protected:
0249   DigitType value_;
0250 };
0251 
0252 class BasicDecimal32;
0253 class BasicDecimal64;
0254 
0255 ARROW_EXPORT bool operator<(const BasicDecimal32& left, const BasicDecimal32& right);
0256 ARROW_EXPORT bool operator<=(const BasicDecimal32& left, const BasicDecimal32& right);
0257 ARROW_EXPORT bool operator>(const BasicDecimal32& left, const BasicDecimal32& right);
0258 ARROW_EXPORT bool operator>=(const BasicDecimal32& left, const BasicDecimal32& right);
0259 
0260 ARROW_EXPORT BasicDecimal32 operator-(const BasicDecimal32& self);
0261 ARROW_EXPORT BasicDecimal32 operator~(const BasicDecimal32& self);
0262 ARROW_EXPORT BasicDecimal32 operator+(const BasicDecimal32& left,
0263                                       const BasicDecimal32& right);
0264 ARROW_EXPORT BasicDecimal32 operator-(const BasicDecimal32& left,
0265                                       const BasicDecimal32& right);
0266 ARROW_EXPORT BasicDecimal32 operator*(const BasicDecimal32& left,
0267                                       const BasicDecimal32& right);
0268 ARROW_EXPORT BasicDecimal32 operator/(const BasicDecimal32& left,
0269                                       const BasicDecimal32& right);
0270 ARROW_EXPORT BasicDecimal32 operator%(const BasicDecimal32& left,
0271                                       const BasicDecimal32& right);
0272 
0273 class ARROW_EXPORT BasicDecimal32 : public SmallBasicDecimal<int32_t> {
0274  public:
0275   using SmallBasicDecimal<int32_t>::SmallBasicDecimal;
0276   using ValueType = int32_t;
0277 
0278   /// \brief Negate the current value (in-place)
0279   BasicDecimal32& Negate();
0280 
0281   /// \brief Absolute value (in-place)
0282   BasicDecimal32& Abs() { return *this < 0 ? Negate() : *this; }
0283 
0284   /// \brief Absolute value
0285   static BasicDecimal32 Abs(const BasicDecimal32& in) {
0286     BasicDecimal32 result(in);
0287     return result.Abs();
0288   }
0289 
0290   /// \brief Add a number to this one. The result is truncated to 32 bits.
0291   BasicDecimal32& operator+=(const BasicDecimal32& right) {
0292     value_ += right.value_;
0293     return *this;
0294   }
0295 
0296   /// \brief Subtract a number from this one. The result is truncated to 32 bits.
0297   BasicDecimal32& operator-=(const BasicDecimal32& right) {
0298     value_ -= right.value_;
0299     return *this;
0300   }
0301 
0302   /// \brief Multiply this number by another. The result is truncated to 32 bits.
0303   BasicDecimal32& operator*=(const BasicDecimal32& right) {
0304     value_ *= static_cast<uint64_t>(right.value_);
0305     return *this;
0306   }
0307 
0308   /// \brief Divide this number by the divisor and return the result.
0309   ///
0310   /// This operation is not destructive.
0311   /// The answer rounds to zero. Signs work like:
0312   ///   21 /  5 ->  4,  1
0313   ///  -21 /  5 -> -4, -1
0314   ///   21 / -5 -> -4,  1
0315   ///  -21 / -5 ->  4, -1
0316   /// \param[in] divisor the number to divide by
0317   /// \param[out] result the quotient
0318   /// \param[out] remainder the remainder after the division
0319   DecimalStatus Divide(const BasicDecimal32& divisor, BasicDecimal32* result,
0320                        BasicDecimal32* remainder) const;
0321 
0322   /// \brief In-place division
0323   BasicDecimal32& operator/=(const BasicDecimal32& right) {
0324     value_ /= right.value_;
0325     return *this;
0326   }
0327 
0328   /// \brief Bitwise "or" between two BasicDecimal32s
0329   BasicDecimal32& operator|=(const BasicDecimal32& right) {
0330     value_ |= right.value_;
0331     return *this;
0332   }
0333 
0334   /// \brief Bitwise "and" between two BasicDecimal32s
0335   BasicDecimal32& operator&=(const BasicDecimal32& right) {
0336     value_ &= right.value_;
0337     return *this;
0338   }
0339   /// \brief Shift left by the given number of bits.
0340   BasicDecimal32& operator<<=(uint32_t bits);
0341 
0342   BasicDecimal32 operator<<(uint32_t bits) const {
0343     auto res = *this;
0344     res <<= bits;
0345     return res;
0346   }
0347 
0348   /// \brief Shift right by the given number of bits.
0349   ///
0350   /// Negative values will sign-extend
0351   BasicDecimal32& operator>>=(uint32_t bits);
0352 
0353   BasicDecimal32 operator>>(uint32_t bits) const {
0354     auto res = *this;
0355     res >>= bits;
0356     return res;
0357   }
0358 
0359   /// \brief Convert BasicDecimal32 from one scale to another
0360   DecimalStatus Rescale(int32_t original_scale, int32_t new_scale,
0361                         BasicDecimal32* out) const;
0362 
0363   void GetWholeAndFraction(int scale, BasicDecimal32* whole,
0364                            BasicDecimal32* fraction) const;
0365 
0366   /// \brief Scale up.
0367   BasicDecimal32 IncreaseScaleBy(int32_t increase_by) const;
0368 
0369   /// \brief Scale down.
0370   ///
0371   /// - If 'round' is true, the right-most digits are dropped and the result value is
0372   ///   rounded up (+1 for +ve, -1 for -ve) based on the value of the dropped digits
0373   ///   (>= 10^reduce_by / 2).
0374   /// - If 'round' is false, the right-most digits are simply dropped.
0375   BasicDecimal32 ReduceScaleBy(int32_t reduce_by, bool round = true) const;
0376 
0377   /// \brief Whether this number fits in the given precision
0378   ///
0379   /// Return true if the number of significant digits is less or equal to 'precision'.
0380   bool FitsInPrecision(int32_t precision) const;
0381 
0382   /// \brief Get the maximum valid unscaled decimal value.
0383   static const BasicDecimal32& GetMaxValue();
0384   /// \brief Get the maximum valid unscaled decimal value for the given precision.
0385   static BasicDecimal32 GetMaxValue(int32_t precision);
0386 
0387   /// \brief Get the maximum decimal value (is not a valid value).
0388   static constexpr BasicDecimal32 GetMaxSentinel() {
0389     return BasicDecimal32(std::numeric_limits<int32_t>::max());
0390   }
0391 
0392   /// \brief Get the minimum decimal value (is not a valid value).
0393   static constexpr BasicDecimal32 GetMinSentinel() {
0394     return BasicDecimal32(std::numeric_limits<int32_t>::min());
0395   }
0396 
0397   /// \brief Scale multiplier for a given scale value.
0398   static const BasicDecimal32& GetScaleMultiplier(int32_t scale);
0399   /// \brief Half-scale multiplier for a given scale value.
0400   static const BasicDecimal32& GetHalfScaleMultiplier(int32_t scale);
0401 
0402   explicit operator BasicDecimal64() const;
0403 };
0404 
0405 ARROW_EXPORT bool operator<(const BasicDecimal64& left, const BasicDecimal64& right);
0406 ARROW_EXPORT bool operator<=(const BasicDecimal64& left, const BasicDecimal64& right);
0407 ARROW_EXPORT bool operator>(const BasicDecimal64& left, const BasicDecimal64& right);
0408 ARROW_EXPORT bool operator>=(const BasicDecimal64& left, const BasicDecimal64& right);
0409 
0410 ARROW_EXPORT BasicDecimal64 operator-(const BasicDecimal64& self);
0411 ARROW_EXPORT BasicDecimal64 operator~(const BasicDecimal64& self);
0412 ARROW_EXPORT BasicDecimal64 operator+(const BasicDecimal64& left,
0413                                       const BasicDecimal64& right);
0414 ARROW_EXPORT BasicDecimal64 operator-(const BasicDecimal64& left,
0415                                       const BasicDecimal64& right);
0416 ARROW_EXPORT BasicDecimal64 operator*(const BasicDecimal64& left,
0417                                       const BasicDecimal64& right);
0418 ARROW_EXPORT BasicDecimal64 operator/(const BasicDecimal64& left,
0419                                       const BasicDecimal64& right);
0420 ARROW_EXPORT BasicDecimal64 operator%(const BasicDecimal64& left,
0421                                       const BasicDecimal64& right);
0422 
0423 class ARROW_EXPORT BasicDecimal64 : public SmallBasicDecimal<int64_t> {
0424  public:
0425   using SmallBasicDecimal<int64_t>::SmallBasicDecimal;
0426   using ValueType = int64_t;
0427 
0428   /// \brief Negate the current value (in-place)
0429   BasicDecimal64& Negate();
0430 
0431   /// \brief Absolute value (in-place)
0432   BasicDecimal64& Abs() { return *this < 0 ? Negate() : *this; }
0433 
0434   /// \brief Absolute value
0435   static BasicDecimal64 Abs(const BasicDecimal64& in) {
0436     BasicDecimal64 result(in);
0437     return result.Abs();
0438   }
0439 
0440   /// \brief Add a number to this one. The result is truncated to 32 bits.
0441   BasicDecimal64& operator+=(const BasicDecimal64& right) {
0442     value_ += right.value_;
0443     return *this;
0444   }
0445 
0446   /// \brief Subtract a number from this one. The result is truncated to 32 bits.
0447   BasicDecimal64& operator-=(const BasicDecimal64& right) {
0448     value_ -= right.value_;
0449     return *this;
0450   }
0451 
0452   /// \brief Multiply this number by another. The result is truncated to 32 bits.
0453   BasicDecimal64& operator*=(const BasicDecimal64& right) {
0454     value_ *= static_cast<uint64_t>(right.value_);
0455     return *this;
0456   }
0457 
0458   /// \brief Divide this number by the divisor and return the result.
0459   ///
0460   /// This operation is not destructive.
0461   /// The answer rounds to zero. Signs work like:
0462   ///   21 /  5 ->  4,  1
0463   ///  -21 /  5 -> -4, -1
0464   ///   21 / -5 -> -4,  1
0465   ///  -21 / -5 ->  4, -1
0466   /// \param[in] divisor the number to divide by
0467   /// \param[out] result the quotient
0468   /// \param[out] remainder the remainder after the division
0469   DecimalStatus Divide(const BasicDecimal64& divisor, BasicDecimal64* result,
0470                        BasicDecimal64* remainder) const;
0471 
0472   /// \brief In-place division
0473   BasicDecimal64& operator/=(const BasicDecimal64& right) {
0474     value_ /= right.value_;
0475     return *this;
0476   }
0477 
0478   /// \brief Bitwise "or" between two BasicDecimal64s
0479   BasicDecimal64& operator|=(const BasicDecimal64& right) {
0480     value_ |= right.value_;
0481     return *this;
0482   }
0483 
0484   /// \brief Bitwise "and" between two BasicDecimal64s
0485   BasicDecimal64& operator&=(const BasicDecimal64& right) {
0486     value_ &= right.value_;
0487     return *this;
0488   }
0489 
0490   /// \brief Shift left by the given number of bits.
0491   BasicDecimal64& operator<<=(uint32_t bits);
0492 
0493   BasicDecimal64 operator<<(uint32_t bits) const {
0494     auto res = *this;
0495     res <<= bits;
0496     return res;
0497   }
0498 
0499   /// \brief Shift right by the given number of bits.
0500   ///
0501   /// Negative values will sign-extend
0502   BasicDecimal64& operator>>=(uint32_t bits);
0503 
0504   BasicDecimal64 operator>>(uint32_t bits) const {
0505     auto res = *this;
0506     res >>= bits;
0507     return res;
0508   }
0509 
0510   /// \brief Convert BasicDecimal32 from one scale to another
0511   DecimalStatus Rescale(int32_t original_scale, int32_t new_scale,
0512                         BasicDecimal64* out) const;
0513 
0514   void GetWholeAndFraction(int scale, BasicDecimal64* whole,
0515                            BasicDecimal64* fraction) const;
0516 
0517   /// \brief Scale up.
0518   BasicDecimal64 IncreaseScaleBy(int32_t increase_by) const;
0519 
0520   /// \brief Scale down.
0521   ///
0522   /// - If 'round' is true, the right-most digits are dropped and the result value is
0523   ///   rounded up (+1 for +ve, -1 for -ve) based on the value of the dropped digits
0524   ///   (>= 10^reduce_by / 2).
0525   /// - If 'round' is false, the right-most digits are simply dropped.
0526   BasicDecimal64 ReduceScaleBy(int32_t reduce_by, bool round = true) const;
0527 
0528   /// \brief Whether this number fits in the given precision
0529   ///
0530   /// Return true if the number of significant digits is less or equal to 'precision'.
0531   bool FitsInPrecision(int32_t precision) const;
0532 
0533   /// \brief Get the maximum valid unscaled decimal value.
0534   static const BasicDecimal64& GetMaxValue();
0535   /// \brief Get the maximum valid unscaled decimal value for the given precision.
0536   static BasicDecimal64 GetMaxValue(int32_t precision);
0537 
0538   /// \brief Get the maximum decimal value (is not a valid value).
0539   static constexpr BasicDecimal64 GetMaxSentinel() {
0540     return BasicDecimal64(std::numeric_limits<int32_t>::max());
0541   }
0542 
0543   /// \brief Get the minimum decimal value (is not a valid value).
0544   static constexpr BasicDecimal64 GetMinSentinel() {
0545     return BasicDecimal64(std::numeric_limits<int32_t>::min());
0546   }
0547 
0548   /// \brief Scale multiplier for a given scale value.
0549   static const BasicDecimal64& GetScaleMultiplier(int32_t scale);
0550   /// \brief Half-scale multiplier for a given scale value.
0551   static const BasicDecimal64& GetHalfScaleMultiplier(int32_t scale);
0552 };
0553 
0554 /// Represents a signed 128-bit integer in two's complement.
0555 ///
0556 /// This class is also compiled into LLVM IR - so, it should not have cpp references like
0557 /// streams and boost.
0558 class ARROW_EXPORT BasicDecimal128 : public GenericBasicDecimal<BasicDecimal128, 128> {
0559  public:
0560   static constexpr int kMaxPrecision = 38;
0561   static constexpr int kMaxScale = 38;
0562 
0563   using GenericBasicDecimal::GenericBasicDecimal;
0564 
0565   constexpr BasicDecimal128() noexcept : GenericBasicDecimal() {}
0566 
0567   /// \brief Create a BasicDecimal128 from the two's complement representation.
0568 #if ARROW_LITTLE_ENDIAN
0569   constexpr BasicDecimal128(int64_t high, uint64_t low) noexcept
0570       : BasicDecimal128(WordArray{low, static_cast<uint64_t>(high)}) {}
0571 #else
0572   constexpr BasicDecimal128(int64_t high, uint64_t low) noexcept
0573       : BasicDecimal128(WordArray{static_cast<uint64_t>(high), low}) {}
0574 #endif
0575 
0576   /// \brief Negate the current value (in-place)
0577   BasicDecimal128& Negate();
0578 
0579   /// \brief Absolute value (in-place)
0580   BasicDecimal128& Abs();
0581 
0582   /// \brief Absolute value
0583   static BasicDecimal128 Abs(const BasicDecimal128& left);
0584 
0585   /// \brief Add a number to this one. The result is truncated to 128 bits.
0586   BasicDecimal128& operator+=(const BasicDecimal128& right);
0587 
0588   /// \brief Subtract a number from this one. The result is truncated to 128 bits.
0589   BasicDecimal128& operator-=(const BasicDecimal128& right);
0590 
0591   /// \brief Multiply this number by another number. The result is truncated to 128 bits.
0592   BasicDecimal128& operator*=(const BasicDecimal128& right);
0593 
0594   /// Divide this number by right and return the result.
0595   ///
0596   /// This operation is not destructive.
0597   /// The answer rounds to zero. Signs work like:
0598   ///   21 /  5 ->  4,  1
0599   ///  -21 /  5 -> -4, -1
0600   ///   21 / -5 -> -4,  1
0601   ///  -21 / -5 ->  4, -1
0602   /// \param[in] divisor the number to divide by
0603   /// \param[out] result the quotient
0604   /// \param[out] remainder the remainder after the division
0605   DecimalStatus Divide(const BasicDecimal128& divisor, BasicDecimal128* result,
0606                        BasicDecimal128* remainder) const;
0607 
0608   /// \brief In-place division.
0609   BasicDecimal128& operator/=(const BasicDecimal128& right);
0610 
0611   /// \brief Bitwise "or" between two BasicDecimal128.
0612   BasicDecimal128& operator|=(const BasicDecimal128& right);
0613 
0614   /// \brief Bitwise "and" between two BasicDecimal128.
0615   BasicDecimal128& operator&=(const BasicDecimal128& right);
0616 
0617   /// \brief Shift left by the given number of bits.
0618   BasicDecimal128& operator<<=(uint32_t bits);
0619 
0620   BasicDecimal128 operator<<(uint32_t bits) const {
0621     auto res = *this;
0622     res <<= bits;
0623     return res;
0624   }
0625 
0626   /// \brief Shift right by the given number of bits.
0627   ///
0628   /// Negative values will sign-extend.
0629   BasicDecimal128& operator>>=(uint32_t bits);
0630 
0631   BasicDecimal128 operator>>(uint32_t bits) const {
0632     auto res = *this;
0633     res >>= bits;
0634     return res;
0635   }
0636 
0637   /// \brief Get the high bits of the two's complement representation of the number.
0638   constexpr int64_t high_bits() const {
0639 #if ARROW_LITTLE_ENDIAN
0640     return static_cast<int64_t>(array_[1]);
0641 #else
0642     return static_cast<int64_t>(array_[0]);
0643 #endif
0644   }
0645 
0646   /// \brief Get the low bits of the two's complement representation of the number.
0647   constexpr uint64_t low_bits() const {
0648 #if ARROW_LITTLE_ENDIAN
0649     return array_[0];
0650 #else
0651     return array_[1];
0652 #endif
0653   }
0654 
0655   /// \brief separate the integer and fractional parts for the given scale.
0656   void GetWholeAndFraction(int32_t scale, BasicDecimal128* whole,
0657                            BasicDecimal128* fraction) const;
0658 
0659   /// \brief Scale multiplier for given scale value.
0660   static const BasicDecimal128& GetScaleMultiplier(int32_t scale);
0661   /// \brief Half-scale multiplier for given scale value.
0662   static const BasicDecimal128& GetHalfScaleMultiplier(int32_t scale);
0663 
0664   /// \brief Convert BasicDecimal128 from one scale to another
0665   DecimalStatus Rescale(int32_t original_scale, int32_t new_scale,
0666                         BasicDecimal128* out) const;
0667 
0668   /// \brief Scale up.
0669   BasicDecimal128 IncreaseScaleBy(int32_t increase_by) const;
0670 
0671   /// \brief Scale down.
0672   /// - If 'round' is true, the right-most digits are dropped and the result value is
0673   ///   rounded up (+1 for +ve, -1 for -ve) based on the value of the dropped digits
0674   ///   (>= 10^reduce_by / 2).
0675   /// - If 'round' is false, the right-most digits are simply dropped.
0676   BasicDecimal128 ReduceScaleBy(int32_t reduce_by, bool round = true) const;
0677 
0678   /// \brief Whether this number fits in the given precision
0679   ///
0680   /// Return true if the number of significant digits is less or equal to `precision`.
0681   bool FitsInPrecision(int32_t precision) const;
0682 
0683   /// \brief count the number of leading binary zeroes.
0684   int32_t CountLeadingBinaryZeros() const;
0685 
0686   /// \brief Get the maximum valid unscaled decimal value.
0687   static const BasicDecimal128& GetMaxValue();
0688 
0689   /// \brief Get the maximum valid unscaled decimal value for the given precision.
0690   static BasicDecimal128 GetMaxValue(int32_t precision);
0691 
0692   /// \brief Get the maximum decimal value (is not a valid value).
0693   static constexpr BasicDecimal128 GetMaxSentinel() {
0694     return BasicDecimal128(/*high=*/std::numeric_limits<int64_t>::max(),
0695                            /*low=*/std::numeric_limits<uint64_t>::max());
0696   }
0697   /// \brief Get the minimum decimal value (is not a valid value).
0698   static constexpr BasicDecimal128 GetMinSentinel() {
0699     return BasicDecimal128(/*high=*/std::numeric_limits<int64_t>::min(),
0700                            /*low=*/std::numeric_limits<uint64_t>::min());
0701   }
0702 };
0703 
0704 ARROW_EXPORT bool operator<(const BasicDecimal128& left, const BasicDecimal128& right);
0705 ARROW_EXPORT bool operator<=(const BasicDecimal128& left, const BasicDecimal128& right);
0706 ARROW_EXPORT bool operator>(const BasicDecimal128& left, const BasicDecimal128& right);
0707 ARROW_EXPORT bool operator>=(const BasicDecimal128& left, const BasicDecimal128& right);
0708 
0709 ARROW_EXPORT BasicDecimal128 operator-(const BasicDecimal128& operand);
0710 ARROW_EXPORT BasicDecimal128 operator~(const BasicDecimal128& operand);
0711 ARROW_EXPORT BasicDecimal128 operator+(const BasicDecimal128& left,
0712                                        const BasicDecimal128& right);
0713 ARROW_EXPORT BasicDecimal128 operator-(const BasicDecimal128& left,
0714                                        const BasicDecimal128& right);
0715 ARROW_EXPORT BasicDecimal128 operator*(const BasicDecimal128& left,
0716                                        const BasicDecimal128& right);
0717 ARROW_EXPORT BasicDecimal128 operator/(const BasicDecimal128& left,
0718                                        const BasicDecimal128& right);
0719 ARROW_EXPORT BasicDecimal128 operator%(const BasicDecimal128& left,
0720                                        const BasicDecimal128& right);
0721 
0722 class ARROW_EXPORT BasicDecimal256 : public GenericBasicDecimal<BasicDecimal256, 256> {
0723  public:
0724   using GenericBasicDecimal::GenericBasicDecimal;
0725 
0726   static constexpr int kMaxPrecision = 76;
0727   static constexpr int kMaxScale = 76;
0728 
0729   constexpr BasicDecimal256() noexcept : GenericBasicDecimal() {}
0730 
0731   explicit BasicDecimal256(const BasicDecimal128& value) noexcept
0732       : BasicDecimal256(bit_util::little_endian::ToNative<uint64_t, 4>(
0733             {value.low_bits(), static_cast<uint64_t>(value.high_bits()),
0734              SignExtend(value.high_bits()), SignExtend(value.high_bits())})) {}
0735 
0736   explicit BasicDecimal256(const BasicDecimal64& value) noexcept
0737       : BasicDecimal256(bit_util::little_endian::ToNative<uint64_t, 4>(
0738             {value.low_bits(), SignExtend(value.value()), SignExtend(value.value()),
0739              SignExtend(value.value())})) {}
0740 
0741   explicit BasicDecimal256(const BasicDecimal32& value) noexcept
0742       : BasicDecimal256(bit_util::little_endian::ToNative<uint64_t, 4>(
0743             {value.low_bits(), SignExtend(value.value()), SignExtend(value.value()),
0744              SignExtend(value.value())})) {}
0745 
0746   /// \brief Negate the current value (in-place)
0747   BasicDecimal256& Negate();
0748 
0749   /// \brief Absolute value (in-place)
0750   BasicDecimal256& Abs();
0751 
0752   /// \brief Absolute value
0753   static BasicDecimal256 Abs(const BasicDecimal256& left);
0754 
0755   /// \brief Add a number to this one. The result is truncated to 256 bits.
0756   BasicDecimal256& operator+=(const BasicDecimal256& right);
0757 
0758   /// \brief Subtract a number from this one. The result is truncated to 256 bits.
0759   BasicDecimal256& operator-=(const BasicDecimal256& right);
0760 
0761   /// \brief Get the lowest bits of the two's complement representation of the number.
0762   uint64_t low_bits() const { return bit_util::little_endian::Make(array_)[0]; }
0763 
0764   /// \brief separate the integer and fractional parts for the given scale.
0765   void GetWholeAndFraction(int32_t scale, BasicDecimal256* whole,
0766                            BasicDecimal256* fraction) const;
0767 
0768   /// \brief Scale multiplier for given scale value.
0769   static const BasicDecimal256& GetScaleMultiplier(int32_t scale);
0770   /// \brief Half-scale multiplier for given scale value.
0771   static const BasicDecimal256& GetHalfScaleMultiplier(int32_t scale);
0772 
0773   /// \brief Convert BasicDecimal256 from one scale to another
0774   DecimalStatus Rescale(int32_t original_scale, int32_t new_scale,
0775                         BasicDecimal256* out) const;
0776 
0777   /// \brief Scale up.
0778   BasicDecimal256 IncreaseScaleBy(int32_t increase_by) const;
0779 
0780   /// \brief Scale down.
0781   /// - If 'round' is true, the right-most digits are dropped and the result value is
0782   ///   rounded up (+1 for positive, -1 for negative) based on the value of the
0783   ///   dropped digits (>= 10^reduce_by / 2).
0784   /// - If 'round' is false, the right-most digits are simply dropped.
0785   BasicDecimal256 ReduceScaleBy(int32_t reduce_by, bool round = true) const;
0786 
0787   /// \brief Whether this number fits in the given precision
0788   ///
0789   /// Return true if the number of significant digits is less or equal to `precision`.
0790   bool FitsInPrecision(int32_t precision) const;
0791 
0792   /// \brief Multiply this number by another number. The result is truncated to 256 bits.
0793   BasicDecimal256& operator*=(const BasicDecimal256& right);
0794 
0795   /// Divide this number by right and return the result.
0796   ///
0797   /// This operation is not destructive.
0798   /// The answer rounds to zero. Signs work like:
0799   ///   21 /  5 ->  4,  1
0800   ///  -21 /  5 -> -4, -1
0801   ///   21 / -5 -> -4,  1
0802   ///  -21 / -5 ->  4, -1
0803   /// \param[in] divisor the number to divide by
0804   /// \param[out] result the quotient
0805   /// \param[out] remainder the remainder after the division
0806   DecimalStatus Divide(const BasicDecimal256& divisor, BasicDecimal256* result,
0807                        BasicDecimal256* remainder) const;
0808 
0809   /// \brief Shift left by the given number of bits.
0810   BasicDecimal256& operator<<=(uint32_t bits);
0811 
0812   BasicDecimal256 operator<<(uint32_t bits) const {
0813     auto res = *this;
0814     res <<= bits;
0815     return res;
0816   }
0817 
0818   /// \brief Shift right by the given number of bits.
0819   ///
0820   /// Negative values will sign-extend.
0821   BasicDecimal256& operator>>=(uint32_t bits);
0822 
0823   BasicDecimal256 operator>>(uint32_t bits) const {
0824     auto res = *this;
0825     res >>= bits;
0826     return res;
0827   }
0828 
0829   /// \brief In-place division.
0830   BasicDecimal256& operator/=(const BasicDecimal256& right);
0831 
0832   /// \brief Get the maximum valid unscaled decimal value for the given precision.
0833   static BasicDecimal256 GetMaxValue(int32_t precision);
0834 
0835   /// \brief Get the maximum decimal value (is not a valid value).
0836   static constexpr BasicDecimal256 GetMaxSentinel() {
0837 #if ARROW_LITTLE_ENDIAN
0838     return BasicDecimal256({std::numeric_limits<uint64_t>::max(),
0839                             std::numeric_limits<uint64_t>::max(),
0840                             std::numeric_limits<uint64_t>::max(),
0841                             static_cast<uint64_t>(std::numeric_limits<int64_t>::max())});
0842 #else
0843     return BasicDecimal256({static_cast<uint64_t>(std::numeric_limits<int64_t>::max()),
0844                             std::numeric_limits<uint64_t>::max(),
0845                             std::numeric_limits<uint64_t>::max(),
0846                             std::numeric_limits<uint64_t>::max()});
0847 #endif
0848   }
0849   /// \brief Get the minimum decimal value (is not a valid value).
0850   static constexpr BasicDecimal256 GetMinSentinel() {
0851 #if ARROW_LITTLE_ENDIAN
0852     return BasicDecimal256(
0853         {0, 0, 0, static_cast<uint64_t>(std::numeric_limits<int64_t>::min())});
0854 #else
0855     return BasicDecimal256(
0856         {static_cast<uint64_t>(std::numeric_limits<int64_t>::min()), 0, 0, 0});
0857 #endif
0858   }
0859 };
0860 
0861 ARROW_EXPORT bool operator<(const BasicDecimal256& left, const BasicDecimal256& right);
0862 
0863 ARROW_EXPORT inline bool operator<=(const BasicDecimal256& left,
0864                                     const BasicDecimal256& right) {
0865   return !operator<(right, left);
0866 }
0867 
0868 ARROW_EXPORT inline bool operator>(const BasicDecimal256& left,
0869                                    const BasicDecimal256& right) {
0870   return operator<(right, left);
0871 }
0872 
0873 ARROW_EXPORT inline bool operator>=(const BasicDecimal256& left,
0874                                     const BasicDecimal256& right) {
0875   return !operator<(left, right);
0876 }
0877 
0878 ARROW_EXPORT BasicDecimal256 operator-(const BasicDecimal256& operand);
0879 ARROW_EXPORT BasicDecimal256 operator~(const BasicDecimal256& operand);
0880 ARROW_EXPORT BasicDecimal256 operator+(const BasicDecimal256& left,
0881                                        const BasicDecimal256& right);
0882 ARROW_EXPORT BasicDecimal256 operator*(const BasicDecimal256& left,
0883                                        const BasicDecimal256& right);
0884 ARROW_EXPORT BasicDecimal256 operator/(const BasicDecimal256& left,
0885                                        const BasicDecimal256& right);
0886 
0887 }  // namespace arrow