zhjwpku commented on code in PR #182:
URL: https://github.com/apache/iceberg-cpp/pull/182#discussion_r2319247750


##########
src/iceberg/util/decimal.h:
##########
@@ -0,0 +1,265 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#pragma once
+
+/// \file iceberg/util/decimal.h
+/// \brief 128-bit fixed-point decimal numbers.
+/// Adapted from Apache Arrow with only Decimal128 support.
+/// https://github.com/apache/arrow/blob/main/cpp/src/arrow/util/decimal.h
+
+#include <array>
+#include <bit>
+#include <cstdint>
+#include <iosfwd>
+#include <string>
+#include <string_view>
+#include <type_traits>
+
+#include <iceberg/type.h>
+
+#include "iceberg/iceberg_export.h"
+#include "iceberg/result.h"
+#include "iceberg/util/int128.h"
+#include "iceberg/util/macros.h"
+
+namespace iceberg {
+
+/// \brief Represents 128-bit fixed-point decimal numbers.
+/// The max decimal precision that can be safely represented is
+/// 38 significant digits.
+class ICEBERG_EXPORT Decimal {
+ public:
+  static constexpr int32_t kBitWidth = 128;
+  static constexpr int32_t kByteWidth = kBitWidth / 8;
+  static constexpr int32_t kMaxPrecision = 38;
+  static constexpr int32_t kMaxScale = 38;
+
+  /// \brief Default constructor initializes to zero.
+  constexpr Decimal() noexcept = default;
+
+  /// \brief Create a Decimal from a 128-bit integer.
+  constexpr Decimal(int128_t value) noexcept  // NOLINT
+      : data_(value) {}
+
+  /// \brief Create a Decimal from any integer not wider than 64 bits.
+  template <typename T>
+    requires(std::is_integral_v<T> && (sizeof(T) <= sizeof(uint64_t)))
+  constexpr Decimal(T value) noexcept  // NOLINT
+  {
+    data_ = static_cast<int128_t>(value);
+  }
+
+  /// \brief Parse a Decimal from a string representation.
+  explicit Decimal(std::string_view str);
+
+  /// \brief Create a Decimal from two 64-bit integers.
+  constexpr Decimal(int64_t high, uint64_t low) noexcept {
+    data_ = (static_cast<int128_t>(high) << 64) | low;
+  }
+
+  /// \brief Negate the current Decimal value (in place)
+  Decimal& Negate();
+
+  /// \brief Absolute value of the current Decimal value (in place)
+  Decimal& Abs();
+
+  /// \brief Absolute value of the current Decimal value
+  static Decimal Abs(const Decimal& value);
+
+  /// \brief Add a number to this one. The result is truncated to 128 bits.
+  Decimal& operator+=(const Decimal& other);
+
+  /// \brief Subtract a number from this one. The result is truncated to 128 
bits.
+  Decimal& operator-=(const Decimal& other);
+
+  /// \brief Multiply this number by another. The result is truncated to 128 
bits.
+  Decimal& operator*=(const Decimal& other);
+
+  /// \brief Divide this number by another.
+  ///
+  /// The operation does not modify the current Decimal value.
+  /// The answer rounds towards zero. Signs work like:
+  ///   21 /  5 ->  4,  1
+  ///  -21 /  5 -> -4, -1
+  ///   21 / -5 -> -4,  1
+  ///  -21 / -5 ->  4, -1
+  /// \param[in] divisor the number to divide by
+  /// \return the pair of the quotient and the remainder
+  Result<std::pair<Decimal, Decimal>> Divide(const Decimal& divisor) const;
+
+  /// \brief In place division.
+  Decimal& operator/=(const Decimal& other);
+
+  /// \brief Bitwise OR operation.
+  Decimal& operator|=(const Decimal& other);
+
+  /// \brief Bitwise AND operation.
+  Decimal& operator&=(const Decimal& other);
+
+  /// \brief Shift left by the given number of bits (in place).
+  Decimal& operator<<=(uint32_t shift);
+
+  /// \brief Shift left by the given number of bits.
+  Decimal operator<<(uint32_t shift) const {
+    Decimal result(*this);
+    result <<= shift;
+    return result;
+  }
+
+  /// \brief Shift right by the given number of bits (in place).
+  Decimal& operator>>=(uint32_t shift);
+
+  /// \brief Shift right by the given number of bits.
+  Decimal operator>>(uint32_t shift) const {
+    Decimal result(*this);
+    result >>= shift;
+    return result;
+  }
+
+  /// \brief Get the underlying 128-bit integer representation of the number.
+  constexpr int128_t value() const { return data_; }
+
+  /// \brief Get the high bits of the two's complement representation of the 
number.
+  constexpr int64_t high() const { return static_cast<int64_t>(data_ >> 64); }
+
+  /// \brief Get the low bits of the two's complement representation of the 
number.
+  constexpr uint64_t low() const { return static_cast<uint64_t>(data_); }
+
+  /// \brief Convert the Decimal value to a base 10 decimal string with the 
given scale.
+  /// \param scale The scale to use for the string representation.
+  /// \return The string representation of the Decimal value.
+  Result<std::string> ToString(int32_t scale = 0) const;
+
+  /// \brief Convert the Decimal value to an integer string.
+  std::string ToIntegerString() const;
+
+  /// \brief Convert the decimal string to a Decimal value, optionally 
including precision
+  /// and scale if they are provided not null.
+  static Result<Decimal> FromString(std::string_view str, int32_t* precision = 
nullptr,
+                                    int32_t* scale = nullptr);
+
+  /// \brief Convert the floating-point value to a Decimal value with the given
+  /// precision and scale.
+  static Result<Decimal> FromReal(double real, int32_t precision, int32_t 
scale);

Review Comment:
   Ok, removing all these conversions can make the code cleaner. I will remove 
these and keep a branch in my repo in case someday we need them.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@iceberg.apache.org
For additional commands, e-mail: issues-h...@iceberg.apache.org

Reply via email to