blob: 32bdf5fcae6e49108b9ecb4b4d0fa767819d270a [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/decimal128.hpp>
#include <arrow-glib/error.hpp>
G_BEGIN_DECLS
/**
* SECTION: decimal128
* @title: 128-bit decimal class
* @include: arrow-glib/arrow-glib.h
*
* #GArrowDecimal128 is a 128-bit decimal class.
*
* Since: 0.10.0
*/
typedef struct GArrowDecimal128Private_ {
std::shared_ptr<arrow::Decimal128> decimal128;
} GArrowDecimal128Private;
enum {
PROP_0,
PROP_DECIMAL128
};
G_DEFINE_TYPE_WITH_PRIVATE(GArrowDecimal128,
garrow_decimal128,
G_TYPE_OBJECT)
#define GARROW_DECIMAL128_GET_PRIVATE(obj) \
static_cast<GArrowDecimal128Private *>( \
garrow_decimal128_get_instance_private( \
GARROW_DECIMAL128(obj)))
static void
garrow_decimal128_finalize(GObject *object)
{
auto priv = GARROW_DECIMAL128_GET_PRIVATE(object);
priv->decimal128 = nullptr;
G_OBJECT_CLASS(garrow_decimal128_parent_class)->finalize(object);
}
static void
garrow_decimal128_set_property(GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
auto priv = GARROW_DECIMAL128_GET_PRIVATE(object);
switch (prop_id) {
case PROP_DECIMAL128:
priv->decimal128 =
*static_cast<std::shared_ptr<arrow::Decimal128> *>(g_value_get_pointer(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
garrow_decimal128_init(GArrowDecimal128 *object)
{
}
static void
garrow_decimal128_class_init(GArrowDecimal128Class *klass)
{
GParamSpec *spec;
auto gobject_class = G_OBJECT_CLASS(klass);
gobject_class->finalize = garrow_decimal128_finalize;
gobject_class->set_property = garrow_decimal128_set_property;
spec = g_param_spec_pointer("decimal128",
"Decimal128",
"The raw std::shared<arrow::Decimal128> *",
static_cast<GParamFlags>(G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property(gobject_class, PROP_DECIMAL128, spec);
}
/**
* garrow_decimal128_new_string:
* @data: The data of the decimal.
*
* Returns: A newly created #GArrowDecimal128.
*
* Since: 0.10.0
*/
GArrowDecimal128 *
garrow_decimal128_new_string(const gchar *data)
{
auto arrow_decimal = std::make_shared<arrow::Decimal128>(data);
return garrow_decimal128_new_raw(&arrow_decimal);
}
/**
* garrow_decimal128_new_integer:
* @data: The data of the decimal.
*
* Returns: A newly created #GArrowDecimal128.
*
* Since: 0.10.0
*/
GArrowDecimal128 *
garrow_decimal128_new_integer(const gint64 data)
{
auto arrow_decimal = std::make_shared<arrow::Decimal128>(data);
return garrow_decimal128_new_raw(&arrow_decimal);
}
/**
* garrow_decimal128_equal:
* @decimal: A #GArrowDecimal128.
* @other_decimal: A #GArrowDecimal128 to be compared.
*
* Returns: %TRUE if the decimal is equal to the other decimal, %FALSE
* otherwise.
*
* Since: 0.12.0
*/
gboolean
garrow_decimal128_equal(GArrowDecimal128 *decimal,
GArrowDecimal128 *other_decimal)
{
const auto arrow_decimal = garrow_decimal128_get_raw(decimal);
const auto arrow_other_decimal = garrow_decimal128_get_raw(other_decimal);
return *arrow_decimal == *arrow_other_decimal;
}
/**
* garrow_decimal128_not_equal:
* @decimal: A #GArrowDecimal128.
* @other_decimal: A #GArrowDecimal128 to be compared.
*
* Returns: %TRUE if the decimal isn't equal to the other decimal,
* %FALSE otherwise.
*
* Since: 0.12.0
*/
gboolean
garrow_decimal128_not_equal(GArrowDecimal128 *decimal,
GArrowDecimal128 *other_decimal)
{
const auto arrow_decimal = garrow_decimal128_get_raw(decimal);
const auto arrow_other_decimal = garrow_decimal128_get_raw(other_decimal);
return *arrow_decimal != *arrow_other_decimal;
}
/**
* garrow_decimal128_less_than:
* @decimal: A #GArrowDecimal128.
* @other_decimal: A #GArrowDecimal128 to be compared.
*
* Returns: %TRUE if the decimal is less than the other decimal,
* %FALSE otherwise.
*
* Since: 0.12.0
*/
gboolean
garrow_decimal128_less_than(GArrowDecimal128 *decimal,
GArrowDecimal128 *other_decimal)
{
const auto arrow_decimal = garrow_decimal128_get_raw(decimal);
const auto arrow_other_decimal = garrow_decimal128_get_raw(other_decimal);
return *arrow_decimal < *arrow_other_decimal;
}
/**
* garrow_decimal128_less_than_or_equal:
* @decimal: A #GArrowDecimal128.
* @other_decimal: A #GArrowDecimal128 to be compared.
*
* Returns: %TRUE if the decimal is less than the other decimal
* or equal to the other decimal, %FALSE otherwise.
*
* Since: 0.12.0
*/
gboolean
garrow_decimal128_less_than_or_equal(GArrowDecimal128 *decimal,
GArrowDecimal128 *other_decimal)
{
const auto arrow_decimal = garrow_decimal128_get_raw(decimal);
const auto arrow_other_decimal = garrow_decimal128_get_raw(other_decimal);
return *arrow_decimal <= *arrow_other_decimal;
}
/**
* garrow_decimal128_greater_than:
* @decimal: A #GArrowDecimal128.
* @other_decimal: A #GArrowDecimal128 to be compared.
*
* Returns: %TRUE if the decimal is greater than the other decimal,
* %FALSE otherwise.
*
* Since: 0.12.0
*/
gboolean
garrow_decimal128_greater_than(GArrowDecimal128 *decimal,
GArrowDecimal128 *other_decimal)
{
const auto arrow_decimal = garrow_decimal128_get_raw(decimal);
const auto arrow_other_decimal = garrow_decimal128_get_raw(other_decimal);
return *arrow_decimal > *arrow_other_decimal;
}
/**
* garrow_decimal128_greater_than_or_equal:
* @decimal: A #GArrowDecimal128.
* @other_decimal: A #GArrowDecimal128 to be compared.
*
* Returns: %TRUE if the decimal is greater than the other decimal
* or equal to the other decimal, %FALSE otherwise.
*
* Since: 0.12.0
*/
gboolean
garrow_decimal128_greater_than_or_equal(GArrowDecimal128 *decimal,
GArrowDecimal128 *other_decimal)
{
const auto arrow_decimal = garrow_decimal128_get_raw(decimal);
const auto arrow_other_decimal = garrow_decimal128_get_raw(other_decimal);
return *arrow_decimal >= *arrow_other_decimal;
}
/**
* garrow_decimal128_to_string_scale:
* @decimal: A #GArrowDecimal128.
* @scale: The scale of the decimal.
*
* Returns: (transfer full): The string representation of the decimal.
*
* It should be freed with g_free() when no longer needed.
*
* Since: 0.10.0
*/
gchar *
garrow_decimal128_to_string_scale(GArrowDecimal128 *decimal, gint32 scale)
{
auto arrow_decimal = garrow_decimal128_get_raw(decimal);
auto string = arrow_decimal->ToString(scale);
return g_strndup(string.data(), string.size());
}
/**
* garrow_decimal128_to_string:
* @decimal: A #GArrowDecimal128.
*
* Returns: (transfer full): The string representation of the decimal.
*
* It should be freed with g_free() when no longer needed.
*
* Since: 0.10.0
*/
gchar *
garrow_decimal128_to_string(GArrowDecimal128 *decimal)
{
auto arrow_decimal = garrow_decimal128_get_raw(decimal);
auto string = arrow_decimal->ToIntegerString();
return g_strndup(string.data(), string.size());
}
/**
* garrow_decimal128_abs:
* @decimal: A #GArrowDecimal128.
*
* Computes the absolute value of the @decimal destructively.
*
* Since: 0.10.0
*/
void
garrow_decimal128_abs(GArrowDecimal128 *decimal)
{
auto arrow_decimal = garrow_decimal128_get_raw(decimal);
arrow_decimal->Abs();
}
/**
* garrow_decimal128_negate:
* @decimal: A #GArrowDecimal128.
*
* Negate the current value of the @decimal destructively.
*
* Since: 0.10.0
*/
void
garrow_decimal128_negate(GArrowDecimal128 *decimal)
{
auto arrow_decimal = garrow_decimal128_get_raw(decimal);
arrow_decimal->Negate();
}
/**
* garrow_decimal128_to_integer:
* @decimal: A #GArrowDecimal128.
*
* Returns: The 64-bit integer representation of the decimal.
*
* Since: 0.10.0
*/
gint64
garrow_decimal128_to_integer(GArrowDecimal128 *decimal)
{
auto arrow_decimal = garrow_decimal128_get_raw(decimal);
return static_cast<int64_t>(*arrow_decimal);
}
/**
* garrow_decimal128_plus:
* @left: A #GArrowDecimal128.
* @right: A #GArrowDecimal128.
*
* Returns: (transfer full): The added value of these decimals.
*
* Since: 0.11.0
*/
GArrowDecimal128 *
garrow_decimal128_plus(GArrowDecimal128 *left,
GArrowDecimal128 *right)
{
auto arrow_decimal_left = garrow_decimal128_get_raw(left);
auto arrow_decimal_right = garrow_decimal128_get_raw(right);
auto arrow_decimal =
std::make_shared<arrow::Decimal128>(*arrow_decimal_left + *arrow_decimal_right);
return garrow_decimal128_new_raw(&arrow_decimal);
}
/**
* garrow_decimal128_minus:
* @left: A #GArrowDecimal128.
* @right: A #GArrowDecimal128.
*
* Returns: (transfer full): The subtracted value of these decimals.
*
* Since: 0.11.0
*/
GArrowDecimal128 *
garrow_decimal128_minus(GArrowDecimal128 *left,
GArrowDecimal128 *right)
{
auto arrow_decimal_left = garrow_decimal128_get_raw(left);
auto arrow_decimal_right = garrow_decimal128_get_raw(right);
auto arrow_decimal =
std::make_shared<arrow::Decimal128>(*arrow_decimal_left - *arrow_decimal_right);
return garrow_decimal128_new_raw(&arrow_decimal);
}
/**
* garrow_decimal128_multiply:
* @left: A #GArrowDecimal128.
* @right: A #GArrowDecimal128.
*
* Returns: (transfer full): The multiplied value of these decimals.
*
* Since: 0.11.0
*/
GArrowDecimal128 *
garrow_decimal128_multiply(GArrowDecimal128 *left,
GArrowDecimal128 *right)
{
auto arrow_decimal_left = garrow_decimal128_get_raw(left);
auto arrow_decimal_right = garrow_decimal128_get_raw(right);
auto arrow_decimal =
std::make_shared<arrow::Decimal128>(*arrow_decimal_left * *arrow_decimal_right);
return garrow_decimal128_new_raw(&arrow_decimal);
}
/**
* garrow_decimal128_divide:
* @left: A #GArrowDecimal128.
* @right: A #GArrowDecimal128.
* @remainder: (out) (nullable): A return location for the remainder
* value of these decimals. The returned #GArrowDecimal128 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: 0.11.0
*/
GArrowDecimal128 *
garrow_decimal128_divide(GArrowDecimal128 *left,
GArrowDecimal128 *right,
GArrowDecimal128 **remainder,
GError **error)
{
auto arrow_decimal_left = garrow_decimal128_get_raw(left);
auto arrow_decimal_right = garrow_decimal128_get_raw(right);
arrow::Decimal128 arrow_result_raw;
arrow::Decimal128 arrow_remainder_raw;
auto status =
arrow_decimal_left->Divide(*arrow_decimal_right,
&arrow_result_raw,
&arrow_remainder_raw);
if (garrow_error_check(error, status, "[decimal][divide]")) {
if (remainder) {
auto arrow_remainder =
std::make_shared<arrow::Decimal128>(arrow_remainder_raw);
*remainder = garrow_decimal128_new_raw(&arrow_remainder);
}
auto arrow_result = std::make_shared<arrow::Decimal128>(arrow_result_raw);
return garrow_decimal128_new_raw(&arrow_result);
} else {
if (remainder) {
*remainder = NULL;
}
return NULL;
}
}
G_END_DECLS
GArrowDecimal128 *
garrow_decimal128_new_raw(std::shared_ptr<arrow::Decimal128> *arrow_decimal128)
{
auto decimal = g_object_new(GARROW_TYPE_DECIMAL128,
"decimal128", arrow_decimal128,
NULL);
return GARROW_DECIMAL128(decimal);
}
std::shared_ptr<arrow::Decimal128>
garrow_decimal128_get_raw(GArrowDecimal128 *decimal)
{
auto priv = GARROW_DECIMAL128_GET_PRIVATE(decimal);
return priv->decimal128;
}