/* * 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. */ #include #include #include #include G_BEGIN_DECLS /** * SECTION: tensor * @short_description: Tensor class * @include: arrow-glib/arrow-glib.h * * #GArrowTensor is a tensor class. * * Since: 0.3.0 */ typedef struct GArrowTensorPrivate_ { std::shared_ptr tensor; GArrowBuffer *buffer; } GArrowTensorPrivate; enum { PROP_0, PROP_TENSOR, PROP_BUFFER }; G_DEFINE_TYPE_WITH_PRIVATE(GArrowTensor, garrow_tensor, G_TYPE_OBJECT) #define GARROW_TENSOR_GET_PRIVATE(obj) \ static_cast( \ garrow_tensor_get_instance_private( \ GARROW_TENSOR(obj))) static void garrow_tensor_dispose(GObject *object) { auto priv = GARROW_TENSOR_GET_PRIVATE(object); if (priv->buffer) { g_object_unref(priv->buffer); priv->buffer = nullptr; } G_OBJECT_CLASS(garrow_tensor_parent_class)->dispose(object); } static void garrow_tensor_finalize(GObject *object) { auto priv = GARROW_TENSOR_GET_PRIVATE(object); priv->tensor.~shared_ptr(); G_OBJECT_CLASS(garrow_tensor_parent_class)->finalize(object); } static void garrow_tensor_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { auto priv = GARROW_TENSOR_GET_PRIVATE(object); switch (prop_id) { case PROP_TENSOR: priv->tensor = *static_cast *>(g_value_get_pointer(value)); break; case PROP_BUFFER: priv->buffer = GARROW_BUFFER(g_value_dup_object(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void garrow_tensor_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { auto priv = GARROW_TENSOR_GET_PRIVATE(object); switch (prop_id) { case PROP_BUFFER: g_value_set_object(value, priv->buffer); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void garrow_tensor_init(GArrowTensor *object) { auto priv = GARROW_TENSOR_GET_PRIVATE(object); new(&priv->tensor) std::shared_ptr; } static void garrow_tensor_class_init(GArrowTensorClass *klass) { GParamSpec *spec; auto gobject_class = G_OBJECT_CLASS(klass); gobject_class->dispose = garrow_tensor_dispose; gobject_class->finalize = garrow_tensor_finalize; gobject_class->set_property = garrow_tensor_set_property; gobject_class->get_property = garrow_tensor_get_property; spec = g_param_spec_pointer("tensor", "Tensor", "The raw std::shared *", static_cast(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property(gobject_class, PROP_TENSOR, spec); spec = g_param_spec_object("buffer", "Buffer", "The data", GARROW_TYPE_BUFFER, static_cast(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property(gobject_class, PROP_BUFFER, spec); } /** * garrow_tensor_new: * @data_type: A #GArrowDataType that indicates each element type * in the tensor. * @data: A #GArrowBuffer that contains tensor data. * @shape: (array length=n_dimensions): A list of dimension sizes. * @n_dimensions: The number of dimensions. * @strides: (array length=n_strides) (nullable): A list of the number of * bytes in each dimension. * @n_strides: The number of strides. * @dimension_names: (array length=n_dimension_names) (nullable): A list of * dimension names. * @n_dimension_names: The number of dimension names * * Returns: The newly created #GArrowTensor. * * Since: 0.3.0 */ GArrowTensor * garrow_tensor_new(GArrowDataType *data_type, GArrowBuffer *data, gint64 *shape, gsize n_dimensions, gint64 *strides, gsize n_strides, gchar **dimension_names, gsize n_dimension_names) { auto arrow_data_type = garrow_data_type_get_raw(data_type); auto arrow_data = garrow_buffer_get_raw(data); std::vector arrow_shape; for (gsize i = 0; i < n_dimensions; ++i) { arrow_shape.push_back(shape[i]); } std::vector arrow_strides; for (gsize i = 0; i < n_strides; ++i) { arrow_strides.push_back(strides[i]); } std::vector arrow_dimension_names; for (gsize i = 0; i < n_dimension_names; ++i) { arrow_dimension_names.push_back(dimension_names[i]); } auto arrow_tensor = std::make_shared(arrow_data_type, arrow_data, arrow_shape, arrow_strides, arrow_dimension_names); auto tensor = garrow_tensor_new_raw_buffer(&arrow_tensor, data); return tensor; } /** * garrow_tensor_equal: * @tensor: A #GArrowTensor. * @other_tensor: A #GArrowTensor to be compared. * * Returns: %TRUE if both of them have the same data, %FALSE * otherwise. * * Since: 0.4.0 */ gboolean garrow_tensor_equal(GArrowTensor *tensor, GArrowTensor *other_tensor) { const auto arrow_tensor = garrow_tensor_get_raw(tensor); const auto arrow_other_tensor = garrow_tensor_get_raw(other_tensor); return arrow_tensor->Equals(*arrow_other_tensor); } /** * garrow_tensor_get_value_data_type: * @tensor: A #GArrowTensor. * * Returns: (transfer full): The data type of each value in the tensor. * * Since: 0.3.0 */ GArrowDataType * garrow_tensor_get_value_data_type(GArrowTensor *tensor) { auto arrow_tensor = garrow_tensor_get_raw(tensor); auto arrow_data_type = arrow_tensor->type(); return garrow_data_type_new_raw(&arrow_data_type); } /** * garrow_tensor_get_value_type: * @tensor: A #GArrowTensor. * * Returns: The type of each value in the tensor. * * Since: 0.3.0 */ GArrowType garrow_tensor_get_value_type(GArrowTensor *tensor) { auto arrow_tensor = garrow_tensor_get_raw(tensor); auto arrow_type = arrow_tensor->type_id(); return garrow_type_from_raw(arrow_type); } /** * garrow_tensor_get_buffer: * @tensor: A #GArrowTensor. * * Returns: (transfer full): The data of the tensor. * * Since: 0.3.0 */ GArrowBuffer * garrow_tensor_get_buffer(GArrowTensor *tensor) { auto priv = GARROW_TENSOR_GET_PRIVATE(tensor); if (priv->buffer) { g_object_ref(priv->buffer); return priv->buffer; } auto arrow_tensor = garrow_tensor_get_raw(tensor); auto arrow_buffer = arrow_tensor->data(); return garrow_buffer_new_raw(&arrow_buffer); } /** * garrow_tensor_get_shape: * @tensor: A #GArrowTensor. * @n_dimensions: (out): The number of dimensions. * * Returns: (array length=n_dimensions) (transfer full): * The shape of the tensor. * * It should be freed with g_free() when no longer needed. * * Since: 0.3.0 */ gint64 * garrow_tensor_get_shape(GArrowTensor *tensor, gint *n_dimensions) { auto arrow_tensor = garrow_tensor_get_raw(tensor); auto arrow_shape = arrow_tensor->shape(); auto n_dimensions_raw = arrow_shape.size(); auto shape = static_cast(g_malloc_n(sizeof(gint64), n_dimensions_raw)); for (gsize i = 0; i < n_dimensions_raw; ++i) { shape[i] = arrow_shape[i]; } *n_dimensions = static_cast(n_dimensions_raw); return shape; } /** * garrow_tensor_get_strides: * @tensor: A #GArrowTensor. * @n_strides: (out): The number of strides. * * Returns: (array length=n_strides) (transfer full): * The strides of the tensor. * * It should be freed with g_free() when no longer needed. * * Since: 0.3.0 */ gint64 * garrow_tensor_get_strides(GArrowTensor *tensor, gint *n_strides) { auto arrow_tensor = garrow_tensor_get_raw(tensor); auto arrow_strides = arrow_tensor->strides(); auto n_strides_raw = arrow_strides.size(); auto strides = static_cast(g_malloc_n(sizeof(gint64), n_strides_raw)); for (gsize i = 0; i < n_strides_raw; ++i) { strides[i] = arrow_strides[i]; } *n_strides = static_cast(n_strides_raw); return strides; } /** * garrow_tensor_get_n_dimensions: * @tensor: A #GArrowTensor. * * Returns: The number of dimensions of the tensor. * * Since: 0.3.0 */ gint garrow_tensor_get_n_dimensions(GArrowTensor *tensor) { auto arrow_tensor = garrow_tensor_get_raw(tensor); return arrow_tensor->ndim(); } /** * garrow_tensor_get_dimension_name: * @tensor: A #GArrowTensor. * @i: The index of the target dimension. * * Returns: The i-th dimension name of the tensor. * * Since: 0.3.0 */ const gchar * garrow_tensor_get_dimension_name(GArrowTensor *tensor, gint i) { auto arrow_tensor = garrow_tensor_get_raw(tensor); auto arrow_dimension_name = &(arrow_tensor->dim_name(i)); return arrow_dimension_name->c_str(); } /** * garrow_tensor_get_size: * @tensor: A #GArrowTensor. * * Returns: The number of value cells in the tensor. * * Since: 0.3.0 */ gint64 garrow_tensor_get_size(GArrowTensor *tensor) { auto arrow_tensor = garrow_tensor_get_raw(tensor); return arrow_tensor->size(); } /** * garrow_tensor_is_mutable: * @tensor: A #GArrowTensor. * * Returns: %TRUE if the tensor is mutable, %FALSE otherwise. * * Since: 0.3.0 */ gboolean garrow_tensor_is_mutable(GArrowTensor *tensor) { auto arrow_tensor = garrow_tensor_get_raw(tensor); return arrow_tensor->is_mutable(); } /** * garrow_tensor_is_contiguous: * @tensor: A #GArrowTensor. * * Returns: %TRUE if the tensor is contiguous, %FALSE otherwise. * * Since: 0.3.0 */ gboolean garrow_tensor_is_contiguous(GArrowTensor *tensor) { auto arrow_tensor = garrow_tensor_get_raw(tensor); return arrow_tensor->is_contiguous(); } /** * garrow_tensor_is_row_major: * @tensor: A #GArrowTensor. * * Returns: %TRUE if the tensor is row major a.k.a. C order, * %FALSE otherwise. * * Since: 0.3.0 */ gboolean garrow_tensor_is_row_major(GArrowTensor *tensor) { auto arrow_tensor = garrow_tensor_get_raw(tensor); return arrow_tensor->is_row_major(); } /** * garrow_tensor_is_column_major: * @tensor: A #GArrowTensor. * * Returns: %TRUE if the tensor is column major a.k.a. Fortran order, * %FALSE otherwise. * * Since: 0.3.0 */ gboolean garrow_tensor_is_column_major(GArrowTensor *tensor) { auto arrow_tensor = garrow_tensor_get_raw(tensor); return arrow_tensor->is_column_major(); } G_END_DECLS GArrowTensor * garrow_tensor_new_raw(std::shared_ptr *arrow_tensor) { return garrow_tensor_new_raw_buffer(arrow_tensor, nullptr); } GArrowTensor * garrow_tensor_new_raw_buffer(std::shared_ptr *arrow_tensor, GArrowBuffer *buffer) { auto tensor = GARROW_TENSOR(g_object_new(GARROW_TYPE_TENSOR, "tensor", arrow_tensor, "buffer", buffer, NULL)); return tensor; } std::shared_ptr garrow_tensor_get_raw(GArrowTensor *tensor) { auto priv = GARROW_TENSOR_GET_PRIVATE(tensor); return priv->tensor; }