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 62d3db662f GH-48364: [GLib][Ruby] Add CumulativeOptions (#48371)
62d3db662f is described below

commit 62d3db662fc8d5fac7742b00d3bf3c7ce680468e
Author: Sten Larsson <[email protected]>
AuthorDate: Sat Dec 6 02:09:28 2025 +0100

    GH-48364: [GLib][Ruby] Add CumulativeOptions (#48371)
    
    ### Rationale for this change
    
    The `CumulativeOptions` class is not available in GLib/Ruby, and it is used 
together with the `cumulative_sum`, `cumulative_prod`, etc compute functions.
    
    ### What changes are included in this PR?
    
    This adds the `CumulativeOptions` to GLib.
    
    ### Are these changes tested?
    
    Yes, with Ruby unit tests.
    
    ### Are there any user-facing changes?
    
    Yes, a new class.
    * GitHub Issue: #48364
    
    Authored-by: Sten Larsson <[email protected]>
    Signed-off-by: Sutou Kouhei <[email protected]>
---
 c_glib/arrow-glib/compute.cpp          | 203 +++++++++++++++++++++++++++++++++
 c_glib/arrow-glib/compute.h            |  16 +++
 c_glib/arrow-glib/compute.hpp          |   5 +
 c_glib/test/test-cumulative-options.rb |  64 +++++++++++
 4 files changed, 288 insertions(+)

diff --git a/c_glib/arrow-glib/compute.cpp b/c_glib/arrow-glib/compute.cpp
index db5be7a6f1..25eb50bab2 100644
--- a/c_glib/arrow-glib/compute.cpp
+++ b/c_glib/arrow-glib/compute.cpp
@@ -254,6 +254,10 @@ G_BEGIN_DECLS
  * #GArrowAssumeTimezoneOptions is a class to customize the `assume_timezone`
  * function.
  *
+ * #GArrowCumulativeOptions is a class to customize the cumulative functions
+ * such as `cumulative_sum`, `cumulative_prod`, `cumulative_max`, and
+ * `cumulative_min`.
+ *
  * There are many functions to compute data on an array.
  */
 
@@ -6491,6 +6495,173 @@ garrow_assume_timezone_options_new(void)
   return GARROW_ASSUME_TIMEZONE_OPTIONS(options);
 }
 
+typedef struct GArrowCumulativeOptionsPrivate_
+{
+  GArrowScalar *start;
+} GArrowCumulativeOptionsPrivate;
+
+enum {
+  PROP_CUMULATIVE_OPTIONS_START = 1,
+  PROP_CUMULATIVE_OPTIONS_SKIP_NULLS,
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(GArrowCumulativeOptions,
+                           garrow_cumulative_options,
+                           GARROW_TYPE_FUNCTION_OPTIONS)
+
+#define GARROW_CUMULATIVE_OPTIONS_GET_PRIVATE(object)                          
          \
+  static_cast<GArrowCumulativeOptionsPrivate *>(                               
          \
+    
garrow_cumulative_options_get_instance_private(GARROW_CUMULATIVE_OPTIONS(object)))
+
+static void
+garrow_cumulative_options_dispose(GObject *object)
+{
+  auto priv = GARROW_CUMULATIVE_OPTIONS_GET_PRIVATE(object);
+
+  if (priv->start) {
+    g_object_unref(priv->start);
+    priv->start = nullptr;
+  }
+
+  G_OBJECT_CLASS(garrow_cumulative_options_parent_class)->dispose(object);
+}
+
+static void
+garrow_cumulative_options_set_property(GObject *object,
+                                       guint prop_id,
+                                       const GValue *value,
+                                       GParamSpec *pspec)
+{
+  auto priv = GARROW_CUMULATIVE_OPTIONS_GET_PRIVATE(object);
+  auto options = 
garrow_cumulative_options_get_raw(GARROW_CUMULATIVE_OPTIONS(object));
+
+  switch (prop_id) {
+  case PROP_CUMULATIVE_OPTIONS_START:
+    {
+      auto scalar = GARROW_SCALAR(g_value_get_object(value));
+      if (priv->start == scalar) {
+        return;
+      }
+      if (priv->start) {
+        g_object_unref(priv->start);
+      }
+      priv->start = scalar;
+      if (priv->start) {
+        g_object_ref(priv->start);
+        options->start = garrow_scalar_get_raw(scalar);
+      } else {
+        options->start = std::nullopt;
+      }
+      break;
+    }
+  case PROP_CUMULATIVE_OPTIONS_SKIP_NULLS:
+    options->skip_nulls = g_value_get_boolean(value);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+garrow_cumulative_options_get_property(GObject *object,
+                                       guint prop_id,
+                                       GValue *value,
+                                       GParamSpec *pspec)
+{
+  auto priv = GARROW_CUMULATIVE_OPTIONS_GET_PRIVATE(object);
+  auto options = 
garrow_cumulative_options_get_raw(GARROW_CUMULATIVE_OPTIONS(object));
+
+  switch (prop_id) {
+  case PROP_CUMULATIVE_OPTIONS_START:
+    {
+      if (priv->start) {
+        g_value_set_object(value, G_OBJECT(priv->start));
+      } else {
+        g_value_set_object(value, NULL);
+      }
+      break;
+    }
+  case PROP_CUMULATIVE_OPTIONS_SKIP_NULLS:
+    g_value_set_boolean(value, options->skip_nulls);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+garrow_cumulative_options_init(GArrowCumulativeOptions *object)
+{
+  auto priv = GARROW_CUMULATIVE_OPTIONS_GET_PRIVATE(object);
+  priv->start = nullptr;
+  auto function_options_priv = GARROW_FUNCTION_OPTIONS_GET_PRIVATE(object);
+  function_options_priv->options = static_cast<arrow::compute::FunctionOptions 
*>(
+    new arrow::compute::CumulativeOptions());
+}
+
+static void
+garrow_cumulative_options_class_init(GArrowCumulativeOptionsClass *klass)
+{
+  auto gobject_class = G_OBJECT_CLASS(klass);
+
+  gobject_class->dispose = garrow_cumulative_options_dispose;
+  gobject_class->set_property = garrow_cumulative_options_set_property;
+  gobject_class->get_property = garrow_cumulative_options_get_property;
+
+  arrow::compute::CumulativeOptions options;
+
+  GParamSpec *spec;
+  /**
+   * GArrowCumulativeOptions:start:
+   *
+   * Optional starting value for cumulative operation computation.
+   *
+   * Since: 23.0.0
+   */
+  spec =
+    g_param_spec_object("start",
+                        "Start",
+                        "Optional starting value for cumulative operation 
computation",
+                        GARROW_TYPE_SCALAR,
+                        static_cast<GParamFlags>(G_PARAM_READWRITE));
+  g_object_class_install_property(gobject_class, 
PROP_CUMULATIVE_OPTIONS_START, spec);
+
+  /**
+   * GArrowCumulativeOptions:skip-nulls:
+   *
+   * If true, nulls in the input are ignored and produce a corresponding null 
output.
+   * When false, the first null encountered is propagated through the 
remaining output.
+   *
+   * Since: 23.0.0
+   */
+  spec = g_param_spec_boolean(
+    "skip-nulls",
+    "Skip nulls",
+    "If true, nulls in the input are ignored and produce a corresponding null 
output. "
+    "When false, the first null encountered is propagated through the 
remaining output",
+    options.skip_nulls,
+    static_cast<GParamFlags>(G_PARAM_READWRITE));
+  g_object_class_install_property(gobject_class,
+                                  PROP_CUMULATIVE_OPTIONS_SKIP_NULLS,
+                                  spec);
+}
+
+/**
+ * garrow_cumulative_options_new:
+ *
+ * Returns: A newly created #GArrowCumulativeOptions.
+ *
+ * Since: 23.0.0
+ */
+GArrowCumulativeOptions *
+garrow_cumulative_options_new(void)
+{
+  auto options = g_object_new(GARROW_TYPE_CUMULATIVE_OPTIONS, NULL);
+  return GARROW_CUMULATIVE_OPTIONS(options);
+}
+
 G_END_DECLS
 
 arrow::Result<arrow::FieldRef>
@@ -6627,6 +6798,11 @@ garrow_function_options_new_raw(const 
arrow::compute::FunctionOptions *arrow_opt
       static_cast<const arrow::compute::AssumeTimezoneOptions 
*>(arrow_options);
     auto options = 
garrow_assume_timezone_options_new_raw(arrow_assume_timezone_options);
     return GARROW_FUNCTION_OPTIONS(options);
+  } else if (arrow_type_name == "CumulativeOptions") {
+    const auto arrow_cumulative_options =
+      static_cast<const arrow::compute::CumulativeOptions *>(arrow_options);
+    auto options = garrow_cumulative_options_new_raw(arrow_cumulative_options);
+    return GARROW_FUNCTION_OPTIONS(options);
   } else {
     auto options = g_object_new(GARROW_TYPE_FUNCTION_OPTIONS, NULL);
     return GARROW_FUNCTION_OPTIONS(options);
@@ -7167,3 +7343,30 @@ 
garrow_assume_timezone_options_get_raw(GArrowAssumeTimezoneOptions *options)
   return static_cast<arrow::compute::AssumeTimezoneOptions *>(
     garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
 }
+
+GArrowCumulativeOptions *
+garrow_cumulative_options_new_raw(const arrow::compute::CumulativeOptions 
*arrow_options)
+{
+  GArrowScalar *start = nullptr;
+  if (arrow_options->start.has_value()) {
+    std::shared_ptr<arrow::Scalar> arrow_start = arrow_options->start.value();
+    start = garrow_scalar_new_raw(&arrow_start);
+  }
+  auto options = 
GARROW_CUMULATIVE_OPTIONS(g_object_new(GARROW_TYPE_CUMULATIVE_OPTIONS,
+                                                        "start",
+                                                        start,
+                                                        "skip-nulls",
+                                                        
arrow_options->skip_nulls,
+                                                        NULL));
+  if (start) {
+    g_object_unref(start);
+  }
+  return options;
+}
+
+arrow::compute::CumulativeOptions *
+garrow_cumulative_options_get_raw(GArrowCumulativeOptions *options)
+{
+  return static_cast<arrow::compute::CumulativeOptions *>(
+    garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
+}
diff --git a/c_glib/arrow-glib/compute.h b/c_glib/arrow-glib/compute.h
index eb3db5eeb3..92b5225798 100644
--- a/c_glib/arrow-glib/compute.h
+++ b/c_glib/arrow-glib/compute.h
@@ -1173,4 +1173,20 @@ GARROW_AVAILABLE_IN_23_0
 GArrowAssumeTimezoneOptions *
 garrow_assume_timezone_options_new(void);
 
+#define GARROW_TYPE_CUMULATIVE_OPTIONS (garrow_cumulative_options_get_type())
+GARROW_AVAILABLE_IN_23_0
+G_DECLARE_DERIVABLE_TYPE(GArrowCumulativeOptions,
+                         garrow_cumulative_options,
+                         GARROW,
+                         CUMULATIVE_OPTIONS,
+                         GArrowFunctionOptions)
+struct _GArrowCumulativeOptionsClass
+{
+  GArrowFunctionOptionsClass parent_class;
+};
+
+GARROW_AVAILABLE_IN_23_0
+GArrowCumulativeOptions *
+garrow_cumulative_options_new(void);
+
 G_END_DECLS
diff --git a/c_glib/arrow-glib/compute.hpp b/c_glib/arrow-glib/compute.hpp
index 55df617daf..ab5235b9cc 100644
--- a/c_glib/arrow-glib/compute.hpp
+++ b/c_glib/arrow-glib/compute.hpp
@@ -181,3 +181,8 @@ garrow_assume_timezone_options_new_raw(
   const arrow::compute::AssumeTimezoneOptions *arrow_options);
 arrow::compute::AssumeTimezoneOptions *
 garrow_assume_timezone_options_get_raw(GArrowAssumeTimezoneOptions *options);
+
+GArrowCumulativeOptions *
+garrow_cumulative_options_new_raw(const arrow::compute::CumulativeOptions 
*arrow_options);
+arrow::compute::CumulativeOptions *
+garrow_cumulative_options_get_raw(GArrowCumulativeOptions *options);
diff --git a/c_glib/test/test-cumulative-options.rb 
b/c_glib/test/test-cumulative-options.rb
new file mode 100644
index 0000000000..9b25efd55f
--- /dev/null
+++ b/c_glib/test/test-cumulative-options.rb
@@ -0,0 +1,64 @@
+# 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 TestCumulativeOptions < Test::Unit::TestCase
+  include Helper::Buildable
+
+  def setup
+    @options = Arrow::CumulativeOptions.new
+  end
+
+  def test_start_property
+    assert_nil(@options.start)
+    start_scalar = Arrow::Int64Scalar.new(10)
+    @options.start = start_scalar
+    assert_equal(start_scalar, @options.start)
+    @options.start = nil
+    assert_nil(@options.start)
+  end
+
+  def test_skip_nulls_property
+    assert do
+      [email protected]_nulls?
+    end
+    @options.skip_nulls = true
+    assert do
+      @options.skip_nulls?
+    end
+  end
+
+  def test_cumulative_sum_with_skip_nulls
+    args = [
+      Arrow::ArrayDatum.new(build_int64_array([1, 2, 3, nil, 4, 5])),
+    ]
+    @options.skip_nulls = true
+    cumulative_sum_function = Arrow::Function.find("cumulative_sum")
+    assert_equal(build_int64_array([1, 3, 6, nil, 10, 15]),
+                 cumulative_sum_function.execute(args, @options).value)
+  end
+
+  def test_cumulative_sum_with_start
+    args = [
+      Arrow::ArrayDatum.new(build_int64_array([1, 2, 3])),
+    ]
+    @options.start = Arrow::Int64Scalar.new(10)
+    cumulative_sum_function = Arrow::Function.find("cumulative_sum")
+    assert_equal(build_int64_array([11, 13, 16]),
+                 cumulative_sum_function.execute(args, @options).value)
+  end
+end
+

Reply via email to