blob: 46ae7beec2675e3b9efd022bb4435986c1af2706 [file] [log] [blame]
/*
* 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.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <arrow-glib/buffer.hpp>
#include <arrow-glib/data-type.hpp>
#include <arrow-glib/tensor.hpp>
#include <arrow-glib/type.hpp>
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<arrow::Tensor> 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<GArrowTensorPrivate *>( \
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 = nullptr;
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<std::shared_ptr<arrow::Tensor> *>(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)
{
}
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<arrow::Tensor> *",
static_cast<GParamFlags>(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<GParamFlags>(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.
* @dimention_names: (array length=n_dimention_names) (nullable): A list of
* dimension names.
* @n_dimention_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<int64_t> arrow_shape;
for (gsize i = 0; i < n_dimensions; ++i) {
arrow_shape.push_back(shape[i]);
}
std::vector<int64_t> arrow_strides;
for (gsize i = 0; i < n_strides; ++i) {
arrow_strides.push_back(strides[i]);
}
std::vector<std::string> 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::Tensor>(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<gint64 *>(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<gint>(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<gint64 *>(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<gint>(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> *arrow_tensor)
{
return garrow_tensor_new_raw_buffer(arrow_tensor, nullptr);
}
GArrowTensor *
garrow_tensor_new_raw_buffer(std::shared_ptr<arrow::Tensor> *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<arrow::Tensor>
garrow_tensor_get_raw(GArrowTensor *tensor)
{
auto priv = GARROW_TENSOR_GET_PRIVATE(tensor);
return priv->tensor;
}