This is an automated email from the ASF dual-hosted git repository.

kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 567f9c596e GH-44588: [GLib] Add GArrowDecimal64 Class (#44591)
567f9c596e is described below

commit 567f9c596ed8e5b9c4435172442997874a4764e0
Author: Hiroyuki Sato <[email protected]>
AuthorDate: Thu Oct 31 15:53:39 2024 +0900

    GH-44588: [GLib] Add GArrowDecimal64 Class (#44591)
    
    
    
    ### Rationale for this change
    
    `Decimal64` class has been introeduced. It is necessary to support in GLib.
    
    ### What changes are included in this PR?
    
    Implement `GArrowDecimal64` class.
    
    ### Are these changes tested?
    
    YES
    
    ### Are there any user-facing changes?
    
    NO
    
    * GitHub Issue: #44588
    
    Lead-authored-by: Hiroyuki Sato <[email protected]>
    Co-authored-by: Sutou Kouhei <[email protected]>
    Signed-off-by: Sutou Kouhei <[email protected]>
---
 c_glib/arrow-glib/decimal.cpp | 435 +++++++++++++++++++++++++++++++++++++++++-
 c_glib/arrow-glib/decimal.h   |  79 ++++++++
 c_glib/arrow-glib/decimal.hpp |   5 +
 c_glib/test/test-decimal64.rb | 222 +++++++++++++++++++++
 4 files changed, 740 insertions(+), 1 deletion(-)

diff --git a/c_glib/arrow-glib/decimal.cpp b/c_glib/arrow-glib/decimal.cpp
index 5947868edd..edc2af7a7e 100644
--- a/c_glib/arrow-glib/decimal.cpp
+++ b/c_glib/arrow-glib/decimal.cpp
@@ -24,6 +24,24 @@ template <typename Decimal> struct DecimalConverter
 {
 };
 
+template <> struct DecimalConverter<arrow::Decimal64>
+{
+  using ArrowType = arrow::Decimal64;
+  using GArrowType = GArrowDecimal64;
+
+  GArrowType *
+  new_raw(std::shared_ptr<ArrowType> *arrow_decimal64)
+  {
+    return garrow_decimal64_new_raw(arrow_decimal64);
+  }
+
+  std::shared_ptr<ArrowType>
+  get_raw(GArrowType *decimal64)
+  {
+    return garrow_decimal64_get_raw(decimal64);
+  }
+};
+
 template <> struct DecimalConverter<arrow::Decimal128>
 {
   using ArrowType = arrow::Decimal128;
@@ -301,9 +319,11 @@ G_BEGIN_DECLS
 /**
  * SECTION: decimal
  * @section_id: decimal
- * @title: 128-bit and 256-bit decimal classes
+ * @title: 64-bit, 128-bit and 256-bit decimal classes
  * @include: arrow-glib/arrow-glib.h
  *
+ * #GArrowDecimal64 is a 64-bit decimal class.
+ *
  * #GArrowDecimal128 is a 128-bit decimal class.
  *
  * #GArrowDecimal256 is a 256-bit decimal class.
@@ -311,6 +331,404 @@ G_BEGIN_DECLS
  * Since: 0.10.0
  */
 
+typedef struct GArrowDecimal64Private_
+{
+  std::shared_ptr<arrow::Decimal64> decimal64;
+} GArrowDecimal64Private;
+
+enum {
+  PROP_DECIMAL64 = 1
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(GArrowDecimal64, garrow_decimal64, G_TYPE_OBJECT)
+
+#define GARROW_DECIMAL64_GET_PRIVATE(obj)                                      
          \
+  static_cast<GArrowDecimal64Private *>(                                       
          \
+    garrow_decimal64_get_instance_private(GARROW_DECIMAL64(obj)))
+
+static void
+garrow_decimal64_finalize(GObject *object)
+{
+  auto priv = GARROW_DECIMAL64_GET_PRIVATE(object);
+
+  priv->decimal64.~shared_ptr();
+
+  G_OBJECT_CLASS(garrow_decimal64_parent_class)->finalize(object);
+}
+
+static void
+garrow_decimal64_set_property(GObject *object,
+                              guint prop_id,
+                              const GValue *value,
+                              GParamSpec *pspec)
+{
+  auto priv = GARROW_DECIMAL64_GET_PRIVATE(object);
+
+  switch (prop_id) {
+  case PROP_DECIMAL64:
+    priv->decimal64 =
+      *static_cast<std::shared_ptr<arrow::Decimal64> 
*>(g_value_get_pointer(value));
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+garrow_decimal64_init(GArrowDecimal64 *object)
+{
+  auto priv = GARROW_DECIMAL64_GET_PRIVATE(object);
+  new (&priv->decimal64) std::shared_ptr<arrow::Decimal64>;
+}
+
+static void
+garrow_decimal64_class_init(GArrowDecimal64Class *klass)
+{
+  auto gobject_class = G_OBJECT_CLASS(klass);
+
+  gobject_class->finalize = garrow_decimal64_finalize;
+  gobject_class->set_property = garrow_decimal64_set_property;
+
+  GParamSpec *spec;
+  spec = g_param_spec_pointer(
+    "decimal64",
+    "Decimal64",
+    "The raw std::shared<arrow::Decimal64> *",
+    static_cast<GParamFlags>(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property(gobject_class, PROP_DECIMAL64, spec);
+}
+
+/**
+ * garrow_decimal64_new_string:
+ * @data: The data of the decimal.
+ * @error: (nullable): Return location for a #GError or %NULL.
+ *
+ * Returns: (nullable):
+ *   A newly created #GArrowDecimal64 on success, %NULL on error.
+ *
+ * Since: 19.0.0
+ */
+GArrowDecimal64 *
+garrow_decimal64_new_string(const gchar *data, GError **error)
+{
+  return garrow_decimal_new_string<arrow::Decimal64>(data,
+                                                     error,
+                                                     
"[decimal64][new][string]");
+}
+
+/**
+ * garrow_decimal64_new_integer:
+ * @data: The data of the decimal.
+ *
+ * Returns: A newly created #GArrowDecimal64.
+ *
+ * Since: 19.0.0
+ */
+GArrowDecimal64 *
+garrow_decimal64_new_integer(const gint64 data)
+{
+  return garrow_decimal_new_integer<arrow::Decimal64>(data);
+}
+
+/**
+ * garrow_decimal64_copy:
+ * @decimal: The decimal to be copied.
+ *
+ * Returns: (transfer full): A copied #GArrowDecimal64.
+ *
+ * Since: 19.0.0
+ */
+GArrowDecimal64 *
+garrow_decimal64_copy(GArrowDecimal64 *decimal)
+{
+  return garrow_decimal_copy<arrow::Decimal64>(decimal);
+}
+
+/**
+ * garrow_decimal64_equal:
+ * @decimal: A #GArrowDecimal64.
+ * @other_decimal: A #GArrowDecimal64 to be compared.
+ *
+ * Returns: %TRUE if the decimal is equal to the other decimal, %FALSE
+ *   otherwise.
+ *
+ * Since: 19.0.0
+ */
+gboolean
+garrow_decimal64_equal(GArrowDecimal64 *decimal, GArrowDecimal64 
*other_decimal)
+{
+  return garrow_decimal_equal<arrow::Decimal64>(decimal, other_decimal);
+}
+
+/**
+ * garrow_decimal64_not_equal:
+ * @decimal: A #GArrowDecimal64.
+ * @other_decimal: A #GArrowDecimal64 to be compared.
+ *
+ * Returns: %TRUE if the decimal isn't equal to the other decimal,
+ *   %FALSE otherwise.
+ *
+ * Since: 19.0.0
+ */
+gboolean
+garrow_decimal64_not_equal(GArrowDecimal64 *decimal, GArrowDecimal64 
*other_decimal)
+{
+  return garrow_decimal_not_equal<arrow::Decimal64>(decimal, other_decimal);
+}
+
+/**
+ * garrow_decimal64_less_than:
+ * @decimal: A #GArrowDecimal64.
+ * @other_decimal: A #GArrowDecimal64 to be compared.
+ *
+ * Returns: %TRUE if the decimal is less than the other decimal,
+ *   %FALSE otherwise.
+ *
+ * Since: 19.0.0
+ */
+gboolean
+garrow_decimal64_less_than(GArrowDecimal64 *decimal, GArrowDecimal64 
*other_decimal)
+{
+  return garrow_decimal_less_than<arrow::Decimal64>(decimal, other_decimal);
+}
+
+/**
+ * garrow_decimal64_less_than_or_equal:
+ * @decimal: A #GArrowDecimal64.
+ * @other_decimal: A #GArrowDecimal64 to be compared.
+ *
+ * Returns: %TRUE if the decimal is less than the other decimal
+ *   or equal to the other decimal, %FALSE otherwise.
+ *
+ * Since: 19.0.0
+ */
+gboolean
+garrow_decimal64_less_than_or_equal(GArrowDecimal64 *decimal,
+                                    GArrowDecimal64 *other_decimal)
+{
+  return garrow_decimal_less_than_or_equal<arrow::Decimal64>(decimal, 
other_decimal);
+}
+
+/**
+ * garrow_decimal64_greater_than:
+ * @decimal: A #GArrowDecimal64.
+ * @other_decimal: A #GArrowDecimal64 to be compared.
+ *
+ * Returns: %TRUE if the decimal is greater than the other decimal,
+ *   %FALSE otherwise.
+ *
+ * Since: 19.0.0
+ */
+gboolean
+garrow_decimal64_greater_than(GArrowDecimal64 *decimal, GArrowDecimal64 
*other_decimal)
+{
+  return garrow_decimal_greater_than<arrow::Decimal64>(decimal, other_decimal);
+}
+
+/**
+ * garrow_decimal64_greater_than_or_equal:
+ * @decimal: A #GArrowDecimal64.
+ * @other_decimal: A #GArrowDecimal64 to be compared.
+ *
+ * Returns: %TRUE if the decimal is greater than the other decimal
+ *   or equal to the other decimal, %FALSE otherwise.
+ *
+ * Since: 19.0.0
+ */
+gboolean
+garrow_decimal64_greater_than_or_equal(GArrowDecimal64 *decimal,
+                                       GArrowDecimal64 *other_decimal)
+{
+  return garrow_decimal_greater_than_or_equal<arrow::Decimal64>(decimal, 
other_decimal);
+}
+
+/**
+ * garrow_decimal64_to_string_scale:
+ * @decimal: A #GArrowDecimal64.
+ * @scale: The scale of the decimal.
+ *
+ * Returns: The string representation of the decimal.
+ *
+ *   It should be freed with g_free() when no longer needed.
+ *
+ * Since: 19.0.0
+ */
+gchar *
+garrow_decimal64_to_string_scale(GArrowDecimal64 *decimal, gint32 scale)
+{
+  return garrow_decimal_to_string_scale<arrow::Decimal64>(decimal, scale);
+}
+
+/**
+ * garrow_decimal64_to_string:
+ * @decimal: A #GArrowDecimal64.
+ *
+ * Returns: The string representation of the decimal.
+ *
+ *   It should be freed with g_free() when no longer needed.
+ *
+ * Since: 19.0.0
+ */
+gchar *
+garrow_decimal64_to_string(GArrowDecimal64 *decimal)
+{
+  return garrow_decimal_to_string<arrow::Decimal64>(decimal);
+}
+
+/**
+ * garrow_decimal64_to_bytes:
+ * @decimal: A #GArrowDecimal64.
+ *
+ * Returns: (transfer full): The binary representation of the decimal.
+ *
+ * Since: 19.0.0
+ */
+GBytes *
+garrow_decimal64_to_bytes(GArrowDecimal64 *decimal)
+{
+  return garrow_decimal_to_bytes<arrow::Decimal64>(decimal);
+}
+
+/**
+ * garrow_decimal64_abs:
+ * @decimal: A #GArrowDecimal64.
+ *
+ * Computes the absolute value of the @decimal destructively.
+ *
+ * Since: 19.0.0
+ */
+void
+garrow_decimal64_abs(GArrowDecimal64 *decimal)
+{
+  garrow_decimal_abs<arrow::Decimal64>(decimal);
+}
+
+/**
+ * garrow_decimal64_negate:
+ * @decimal: A #GArrowDecimal64.
+ *
+ * Negate the current value of the @decimal destructively.
+ *
+ * Since: 19.0.0
+ */
+void
+garrow_decimal64_negate(GArrowDecimal64 *decimal)
+{
+  garrow_decimal_negate<arrow::Decimal64>(decimal);
+}
+
+/**
+ * garrow_decimal64_to_integer:
+ * @decimal: A #GArrowDecimal64.
+ *
+ * Returns: The 64-bit integer representation of the decimal.
+ *
+ * Since: 19.0.0
+ */
+gint64
+garrow_decimal64_to_integer(GArrowDecimal64 *decimal)
+{
+  auto arrow_decimal = garrow_decimal64_get_raw(decimal);
+  return static_cast<int64_t>(*arrow_decimal);
+}
+
+/**
+ * garrow_decimal64_plus:
+ * @left: A #GArrowDecimal64.
+ * @right: A #GArrowDecimal64.
+ *
+ * Returns: (transfer full): The added value of these decimals.
+ *
+ * Since: 19.0.0
+ */
+GArrowDecimal64 *
+garrow_decimal64_plus(GArrowDecimal64 *left, GArrowDecimal64 *right)
+{
+  return garrow_decimal_plus<arrow::Decimal64>(left, right);
+}
+
+/**
+ * garrow_decimal64_minus:
+ * @left: A #GArrowDecimal64.
+ * @right: A #GArrowDecimal64.
+ *
+ * Returns: (transfer full): The subtracted value of these decimals.
+ *
+ * Since: 19.0.0
+ */
+GArrowDecimal64 *
+garrow_decimal64_minus(GArrowDecimal64 *left, GArrowDecimal64 *right)
+{
+  return garrow_decimal_minus<arrow::Decimal64>(left, right);
+}
+
+/**
+ * garrow_decimal64_multiply:
+ * @left: A #GArrowDecimal64.
+ * @right: A #GArrowDecimal64.
+ *
+ * Returns: (transfer full): The multiplied value of these decimals.
+ *
+ * Since: 19.0.0
+ */
+GArrowDecimal64 *
+garrow_decimal64_multiply(GArrowDecimal64 *left, GArrowDecimal64 *right)
+{
+  return garrow_decimal_multiply<arrow::Decimal64>(left, right);
+}
+
+/**
+ * garrow_decimal64_divide:
+ * @left: A #GArrowDecimal64.
+ * @right: A #GArrowDecimal64.
+ * @remainder: (out) (nullable): A return location for the remainder
+ *   value of these decimals. The returned #GArrowDecimal64 be
+ *   unreferred with g_object_unref() when no longer needed.
+ * @error: (nullable): Return location for a #GError or %NULL.
+ *
+ * Returns: (nullable) (transfer full): The divided value of
+ *   these decimals or %NULL on error.
+ *
+ * Since: 19.0.0
+ */
+GArrowDecimal64 *
+garrow_decimal64_divide(GArrowDecimal64 *left,
+                        GArrowDecimal64 *right,
+                        GArrowDecimal64 **remainder,
+                        GError **error)
+{
+  return garrow_decimal_divide<arrow::Decimal64>(left,
+                                                 right,
+                                                 remainder,
+                                                 error,
+                                                 "[decimal64][divide]");
+}
+
+/**
+ * garrow_decimal64_rescale:
+ * @decimal: A #GArrowDecimal64.
+ * @original_scale: A scale to be converted from.
+ * @new_scale: A scale to be converted to.
+ * @error: (nullable): Return location for a #GError or %NULL.
+ *
+ * Returns: (nullable) (transfer full): The rescaled decimal or %NULL on error.
+ *
+ * Since: 19.0.0
+ */
+GArrowDecimal64 *
+garrow_decimal64_rescale(GArrowDecimal64 *decimal,
+                         gint32 original_scale,
+                         gint32 new_scale,
+                         GError **error)
+{
+  return garrow_decimal_rescale<arrow::Decimal64>(decimal,
+                                                  original_scale,
+                                                  new_scale,
+                                                  error,
+                                                  "[decimal64][rescale]");
+}
+
 typedef struct GArrowDecimal128Private_
 {
   std::shared_ptr<arrow::Decimal128> decimal128;
@@ -1081,6 +1499,21 @@ garrow_decimal256_rescale(GArrowDecimal256 *decimal,
 
 G_END_DECLS
 
+GArrowDecimal64 *
+garrow_decimal64_new_raw(std::shared_ptr<arrow::Decimal64> *arrow_decimal64)
+{
+  auto decimal64 =
+    g_object_new(garrow_decimal64_get_type(), "decimal64", arrow_decimal64, 
NULL);
+  return GARROW_DECIMAL64(decimal64);
+}
+
+std::shared_ptr<arrow::Decimal64>
+garrow_decimal64_get_raw(GArrowDecimal64 *decimal64)
+{
+  auto priv = GARROW_DECIMAL64_GET_PRIVATE(decimal64);
+  return priv->decimal64;
+}
+
 GArrowDecimal128 *
 garrow_decimal128_new_raw(std::shared_ptr<arrow::Decimal128> *arrow_decimal128)
 {
diff --git a/c_glib/arrow-glib/decimal.h b/c_glib/arrow-glib/decimal.h
index f64afa800a..bb266424b4 100644
--- a/c_glib/arrow-glib/decimal.h
+++ b/c_glib/arrow-glib/decimal.h
@@ -25,6 +25,85 @@
 
 G_BEGIN_DECLS
 
+/* Disabled because it conflicts with GARROW_TYPE_DECIMAL64 in GArrowType. */
+/* #define GARROW_TYPE_DECIMAL64 (garrow_decimal64_get_type()) */
+GARROW_AVAILABLE_IN_ALL
+G_DECLARE_DERIVABLE_TYPE(GArrowDecimal64, garrow_decimal64, GARROW, DECIMAL64, 
GObject)
+
+struct _GArrowDecimal64Class
+{
+  GObjectClass parent_class;
+};
+
+GARROW_AVAILABLE_IN_19_0
+GArrowDecimal64 *
+garrow_decimal64_new_string(const gchar *data, GError **error);
+GARROW_AVAILABLE_IN_19_0
+GArrowDecimal64 *
+garrow_decimal64_new_integer(const gint64 data);
+GARROW_AVAILABLE_IN_19_0
+GArrowDecimal64 *
+garrow_decimal64_copy(GArrowDecimal64 *decimal);
+GARROW_AVAILABLE_IN_19_0
+gboolean
+garrow_decimal64_equal(GArrowDecimal64 *decimal, GArrowDecimal64 
*other_decimal);
+GARROW_AVAILABLE_IN_19_0
+gboolean
+garrow_decimal64_not_equal(GArrowDecimal64 *decimal, GArrowDecimal64 
*other_decimal);
+GARROW_AVAILABLE_IN_19_0
+gboolean
+garrow_decimal64_less_than(GArrowDecimal64 *decimal, GArrowDecimal64 
*other_decimal);
+GARROW_AVAILABLE_IN_19_0
+gboolean
+garrow_decimal64_less_than_or_equal(GArrowDecimal64 *decimal,
+                                    GArrowDecimal64 *other_decimal);
+GARROW_AVAILABLE_IN_19_0
+gboolean
+garrow_decimal64_greater_than(GArrowDecimal64 *decimal, GArrowDecimal64 
*other_decimal);
+GARROW_AVAILABLE_IN_19_0
+gboolean
+garrow_decimal64_greater_than_or_equal(GArrowDecimal64 *decimal,
+                                       GArrowDecimal64 *other_decimal);
+GARROW_AVAILABLE_IN_19_0
+gchar *
+garrow_decimal64_to_string_scale(GArrowDecimal64 *decimal, gint32 scale);
+GARROW_AVAILABLE_IN_19_0
+gchar *
+garrow_decimal64_to_string(GArrowDecimal64 *decimal);
+GARROW_AVAILABLE_IN_19_0
+GBytes *
+garrow_decimal64_to_bytes(GArrowDecimal64 *decimal);
+GARROW_AVAILABLE_IN_19_0
+void
+garrow_decimal64_abs(GArrowDecimal64 *decimal);
+GARROW_AVAILABLE_IN_19_0
+void
+garrow_decimal64_negate(GArrowDecimal64 *decimal);
+GARROW_AVAILABLE_IN_19_0
+gint64
+garrow_decimal64_to_integer(GArrowDecimal64 *decimal);
+GARROW_AVAILABLE_IN_19_0
+GArrowDecimal64 *
+garrow_decimal64_plus(GArrowDecimal64 *left, GArrowDecimal64 *right);
+GARROW_AVAILABLE_IN_19_0
+GArrowDecimal64 *
+garrow_decimal64_minus(GArrowDecimal64 *left, GArrowDecimal64 *right);
+GARROW_AVAILABLE_IN_19_0
+GArrowDecimal64 *
+garrow_decimal64_multiply(GArrowDecimal64 *left, GArrowDecimal64 *right);
+GARROW_AVAILABLE_IN_19_0
+GArrowDecimal64 *
+garrow_decimal64_divide(GArrowDecimal64 *left,
+                        GArrowDecimal64 *right,
+                        GArrowDecimal64 **remainder,
+                        GError **error);
+GARROW_AVAILABLE_IN_19_0
+GArrowDecimal64 *
+garrow_decimal64_rescale(GArrowDecimal64 *decimal,
+                         gint32 original_scale,
+                         gint32 new_scale,
+                         GError **error);
+
 /* Disabled because it conflicts with GARROW_TYPE_DECIMAL128 in GArrowType. */
 /* #define GARROW_TYPE_DECIMAL128 (garrow_decimal128_get_type()) */
 GARROW_AVAILABLE_IN_ALL
diff --git a/c_glib/arrow-glib/decimal.hpp b/c_glib/arrow-glib/decimal.hpp
index 054a91b836..dbfb7f30c6 100644
--- a/c_glib/arrow-glib/decimal.hpp
+++ b/c_glib/arrow-glib/decimal.hpp
@@ -25,6 +25,11 @@
 
 #include <arrow-glib/decimal.h>
 
+GArrowDecimal64 *
+garrow_decimal64_new_raw(std::shared_ptr<arrow::Decimal64> *arrow_decimal64);
+std::shared_ptr<arrow::Decimal64>
+garrow_decimal64_get_raw(GArrowDecimal64 *decimal);
+
 GArrowDecimal128 *
 garrow_decimal128_new_raw(std::shared_ptr<arrow::Decimal128> 
*arrow_decimal128);
 std::shared_ptr<arrow::Decimal128>
diff --git a/c_glib/test/test-decimal64.rb b/c_glib/test/test-decimal64.rb
new file mode 100644
index 0000000000..add4f3e0b4
--- /dev/null
+++ b/c_glib/test/test-decimal64.rb
@@ -0,0 +1,222 @@
+# 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.
+
+class TestDecimal64 < Test::Unit::TestCase
+  def test_new_string_invalid
+    message =
+      "[decimal64][new][string]: Invalid: " +
+      "The string '1,1' is not a valid decimal64 number"
+    error = assert_raise(Arrow::Error::Invalid) do
+      Arrow::Decimal64.new("1,1")
+    end
+    assert_equal(message,
+                 error.message.lines.first.chomp)
+  end
+
+  def test_copy
+    decimal = Arrow::Decimal64.new("234.23445")
+    assert_equal(decimal, decimal.copy)
+  end
+
+  def test_to_string_scale
+    integer_data = 23423445
+    string_data = "234.23445"
+    decimal = Arrow::Decimal64.new(integer_data)
+    assert_equal(string_data, decimal.to_string_scale(5))
+  end
+
+  def test_to_string
+    string_data = "999999999999999999"
+    decimal = Arrow::Decimal64.new(string_data)
+    assert_equal(string_data, decimal.to_s)
+  end
+
+  def test_to_bytes
+    decimal = Arrow::Decimal64.new("12.3")
+    assert_equal([123].pack("q*"),
+                 decimal.to_bytes.to_s)
+  end
+
+  def test_abs
+    absolute_value = "230492239423435324"
+    negative_value = "-230492239423435324"
+    decimal = Arrow::Decimal64.new(negative_value)
+    decimal.abs
+    assert_equal(absolute_value, decimal.to_s)
+  end
+
+  def test_negate
+    positive_value = "230492239423435324"
+    negative_value = "-230492239423435324"
+    decimal = Arrow::Decimal64.new(positive_value)
+    decimal.negate
+    assert_equal(negative_value, decimal.to_s)
+    decimal.negate
+    assert_equal(positive_value, decimal.to_s)
+  end
+
+  def test_plus
+    integer_data1 = 23423445
+    integer_data2 = 5443
+    decimal1 = Arrow::Decimal64.new(integer_data1)
+    decimal2 = Arrow::Decimal64.new(integer_data2)
+    decimal3 = decimal1.plus(decimal2)
+    assert_equal((integer_data1 + integer_data2).to_s,
+                 decimal3.to_s)
+  end
+
+  def test_multiply
+    integer_data1 = 23423445
+    integer_data2 = 5443
+    decimal1 = Arrow::Decimal64.new(integer_data1)
+    decimal2 = Arrow::Decimal64.new(integer_data2)
+    decimal3 = decimal1.multiply(decimal2)
+    assert_equal((integer_data1 * integer_data2).to_s,
+                 decimal3.to_s)
+  end
+
+  def test_divide
+    integer_data1 = 23423445
+    integer_data2 = -5443
+    decimal1 = Arrow::Decimal64.new(integer_data1)
+    decimal2 = Arrow::Decimal64.new(integer_data2)
+    result, remainder = decimal1.divide(decimal2)
+    assert_equal([
+                   integer_data1.quo(integer_data2).truncate.to_s,
+                   integer_data1.remainder(integer_data2).to_s,
+                 ],
+                 [result.to_s, remainder.to_s])
+  end
+
+  def test_divide_zero
+    decimal1 = Arrow::Decimal64.new(23423445)
+    decimal2 = Arrow::Decimal64.new(0)
+    message =
+      "[decimal64][divide]: Invalid: Division by 0 in Decimal64"
+    assert_raise(Arrow::Error::Invalid.new(message)) do
+      decimal1.divide(decimal2)
+    end
+  end
+
+  def test_equal
+    decimal = Arrow::Decimal64.new(10)
+    other_decimal1 = Arrow::Decimal64.new(10)
+    other_decimal2 = Arrow::Decimal64.new(11)
+    assert_equal([
+                   true,
+                   false,
+                 ],
+                 [
+                   decimal == other_decimal1,
+                   decimal == other_decimal2,
+                 ])
+  end
+
+  def test_not_equal
+    decimal = Arrow::Decimal64.new(10)
+    other_decimal1 = Arrow::Decimal64.new(10)
+    other_decimal2 = Arrow::Decimal64.new(11)
+    assert_equal([
+                   false,
+                   true,
+                 ],
+                 [
+                   decimal != other_decimal1,
+                   decimal != other_decimal2,
+                 ])
+  end
+
+  def test_less_than
+    decimal = Arrow::Decimal64.new(10)
+    other_decimal1 = Arrow::Decimal64.new(11)
+    other_decimal2 = Arrow::Decimal64.new(9)
+    assert_equal([
+                   true,
+                   false,
+                   false
+                 ],
+                 [
+                   decimal < other_decimal1,
+                   decimal < other_decimal2,
+                   decimal < decimal,
+                 ])
+  end
+
+  def test_less_than_or_equal
+    decimal = Arrow::Decimal64.new(10)
+    other_decimal1 = Arrow::Decimal64.new(11)
+    other_decimal2 = Arrow::Decimal64.new(9)
+    assert_equal([
+                   true,
+                   false,
+                   true
+                 ],
+                 [
+                   decimal <= other_decimal1,
+                   decimal <= other_decimal2,
+                   decimal <= decimal
+                 ])
+  end
+
+  def test_greater_than
+    decimal = Arrow::Decimal64.new(10)
+    other_decimal1 = Arrow::Decimal64.new(11)
+    other_decimal2 = Arrow::Decimal64.new(9)
+    assert_equal([
+                   false,
+                   true,
+                   false
+                 ],
+                 [
+                   decimal > other_decimal1,
+                   decimal > other_decimal2,
+                   decimal > decimal
+                 ])
+  end
+
+  def test_greater_than_or_equal
+    decimal = Arrow::Decimal64.new(10)
+    other_decimal1 = Arrow::Decimal64.new(11)
+    other_decimal2 = Arrow::Decimal64.new(9)
+    assert_equal([
+                   false,
+                   true,
+                   true
+                 ],
+                 [
+                   decimal >= other_decimal1,
+                   decimal >= other_decimal2,
+                   decimal >= decimal
+                 ])
+  end
+
+  def test_rescale
+    decimal = Arrow::Decimal64.new(10)
+    assert_equal(Arrow::Decimal64.new(1000),
+                 decimal.rescale(1, 3))
+  end
+
+  def test_rescale_fail
+    decimal = Arrow::Decimal64.new(10)
+    message =
+      "[decimal64][rescale]: Invalid: " +
+      "Rescaling Decimal64 value would cause data loss"
+    assert_raise(Arrow::Error::Invalid.new(message)) do
+      decimal.rescale(1, -1)
+    end
+  end
+end

Reply via email to