You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ra...@apache.org on 2019/07/08 09:59:12 UTC
[arrow] branch master updated: ARROW-5867: [C++][Gandiva] add
support for cast int to decimal
This is an automated email from the ASF dual-hosted git repository.
ravindra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/master by this push:
new 49ed11b ARROW-5867: [C++][Gandiva] add support for cast int to decimal
49ed11b is described below
commit 49ed11b7d161666952bddb6aace76f0c06c26f98
Author: Pindikura Ravindra <ra...@dremio.com>
AuthorDate: Mon Jul 8 15:28:55 2019 +0530
ARROW-5867: [C++][Gandiva] add support for cast int to decimal
- cleanup and remove indirection for decimal fns
- add fn for casting int/float to decimal
Author: Pindikura Ravindra <ra...@dremio.com>
Closes #4817 from pravindra/int2dec and squashes the following commits:
c80ee0044 <Pindikura Ravindra> fix format
3a5e7530d <Pindikura Ravindra> add fns for casting int/float to decimal
768dcd106 <Pindikura Ravindra> ARROW-5867: add support for cast int to decimal
---
cpp/src/gandiva/decimal_ir.cc | 466 +++---------------------
cpp/src/gandiva/decimal_ir.h | 4 +
cpp/src/gandiva/function_registry_arithmetic.cc | 2 +
cpp/src/gandiva/gdv_function_stubs.cc | 4 +-
cpp/src/gandiva/llvm_generator.cc | 15 +-
cpp/src/gandiva/precompiled/decimal_wrapper.cc | 221 +++++------
cpp/src/gandiva/tests/decimal_test.cc | 34 +-
7 files changed, 208 insertions(+), 538 deletions(-)
diff --git a/cpp/src/gandiva/decimal_ir.cc b/cpp/src/gandiva/decimal_ir.cc
index 463e448..d9ea4e0 100644
--- a/cpp/src/gandiva/decimal_ir.cc
+++ b/cpp/src/gandiva/decimal_ir.cc
@@ -16,6 +16,7 @@
// under the License.
#include <sstream>
+#include <unordered_set>
#include <utility>
#include "arrow/status.h"
@@ -35,6 +36,21 @@ namespace gandiva {
AddTrace128(msg, value); \
}
+// These are the functions defined in this file. The rest are in precompiled folder,
+// and the i128 needs to be dis-assembled for those.
+static const char* kAddFunction = "add_decimal128_decimal128";
+static const char* kSubtractFunction = "subtract_decimal128_decimal128";
+static const char* kEQFunction = "equal_decimal128_decimal128";
+static const char* kNEFunction = "not_equal_decimal128_decimal128";
+static const char* kLTFunction = "less_than_decimal128_decimal128";
+static const char* kLEFunction = "less_than_or_equal_to_decimal128_decimal128";
+static const char* kGTFunction = "greater_than_decimal128_decimal128";
+static const char* kGEFunction = "greater_than_or_equal_to_decimal128_decimal128";
+
+static const std::unordered_set<std::string> kDecimalIRBuilderFunctions{
+ kAddFunction, kSubtractFunction, kEQFunction, kNEFunction,
+ kLTFunction, kLEFunction, kGTFunction, kGEFunction};
+
const char* DecimalIR::kScaleMultipliersName = "gandivaScaleMultipliers";
/// Populate globals required by decimal IR.
@@ -250,7 +266,7 @@ Status DecimalIR::BuildAdd() {
// int32_t out_precision, int32_t out_scale)
auto i32 = types()->i32_type();
auto i128 = types()->i128_type();
- auto function = BuildFunction("add_decimal128_decimal128", i128,
+ auto function = BuildFunction(kAddFunction, i128,
{
{"x_value", i128},
{"x_precision", i32},
@@ -316,7 +332,7 @@ Status DecimalIR::BuildSubtract() {
// int32_t out_precision, int32_t out_scale)
auto i32 = types()->i32_type();
auto i128 = types()->i128_type();
- auto function = BuildFunction("subtract_decimal128_decimal128", i128,
+ auto function = BuildFunction(kSubtractFunction, i128,
{
{"x_value", i128},
{"x_precision", i32},
@@ -345,121 +361,13 @@ Status DecimalIR::BuildSubtract() {
}
++i;
}
- auto value =
- ir_builder()->CreateCall(module()->getFunction("add_decimal128_decimal128"), args);
+ auto value = ir_builder()->CreateCall(module()->getFunction(kAddFunction), args);
// store result to out
ir_builder()->CreateRet(value);
return Status::OK();
}
-Status DecimalIR::BuildMultiply() {
- // Create fn prototype :
- // int128_t
- // multiply_decimal128_decimal128(int128_t x_value, int32_t x_precision, int32_t
- // x_scale,
- // int128_t y_value, int32_t y_precision, int32_t y_scale
- // int32_t out_precision, int32_t out_scale)
- auto i32 = types()->i32_type();
- auto i128 = types()->i128_type();
- auto function = BuildFunction("multiply_decimal128_decimal128", i128,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"y_value", i128},
- {"y_precision", i32},
- {"y_scale", i32},
- {"out_precision", i32},
- {"out_scale", i32},
- });
-
- auto arg_iter = function->arg_begin();
- ValueFull x(&arg_iter[0], &arg_iter[1], &arg_iter[2]);
- ValueFull y(&arg_iter[3], &arg_iter[4], &arg_iter[5]);
- ValueFull out(nullptr, &arg_iter[6], &arg_iter[7]);
-
- auto entry = llvm::BasicBlock::Create(*context(), "entry", function);
- ir_builder()->SetInsertPoint(entry);
-
- // Make call to pre-compiled IR function.
- auto block = ir_builder()->GetInsertBlock();
- auto out_high_ptr = new llvm::AllocaInst(types()->i64_type(), 0, "out_hi", block);
- auto out_low_ptr = new llvm::AllocaInst(types()->i64_type(), 0, "out_low", block);
- auto x_split = ValueSplit::MakeFromInt128(this, x.value());
- auto y_split = ValueSplit::MakeFromInt128(this, y.value());
-
- std::vector<llvm::Value*> args = {
- x_split.high(), x_split.low(), x.precision(), x.scale(),
- y_split.high(), y_split.low(), y.precision(), y.scale(),
- out.precision(), out.scale(), out_high_ptr, out_low_ptr,
- };
- ir_builder()->CreateCall(
- module()->getFunction("multiply_internal_decimal128_decimal128"), args);
-
- auto out_high = ir_builder()->CreateLoad(out_high_ptr);
- auto out_low = ir_builder()->CreateLoad(out_low_ptr);
- auto result = ValueSplit(out_high, out_low).AsInt128(this);
- ADD_TRACE_128("Multiply : result", result);
-
- ir_builder()->CreateRet(result);
- return Status::OK();
-}
-
-Status DecimalIR::BuildDivideOrMod(const std::string& function_name,
- const std::string& internal_fname) {
- // Create fn prototype :
- // int128_t
- // divide_decimal128_decimal128(int64_t execution_context,
- // int128_t x_value, int32_t x_precision, int32_t x_scale,
- // int128_t y_value, int32_t y_precision, int32_t y_scale
- // int32_t out_precision, int32_t out_scale)
- auto i32 = types()->i32_type();
- auto i128 = types()->i128_type();
- auto function = BuildFunction(function_name, i128,
- {
- {"execution_context", types()->i64_type()},
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"y_value", i128},
- {"y_precision", i32},
- {"y_scale", i32},
- {"out_precision", i32},
- {"out_scale", i32},
- });
-
- auto arg_iter = function->arg_begin();
- auto execution_context = &arg_iter[0];
- ValueFull x(&arg_iter[1], &arg_iter[2], &arg_iter[3]);
- ValueFull y(&arg_iter[4], &arg_iter[5], &arg_iter[6]);
- ValueFull out(nullptr, &arg_iter[7], &arg_iter[8]);
-
- auto entry = llvm::BasicBlock::Create(*context(), "entry", function);
- ir_builder()->SetInsertPoint(entry);
-
- // Make call to pre-compiled IR function.
- auto block = ir_builder()->GetInsertBlock();
- auto out_high_ptr = new llvm::AllocaInst(types()->i64_type(), 0, "out_hi", block);
- auto out_low_ptr = new llvm::AllocaInst(types()->i64_type(), 0, "out_low", block);
- auto x_split = ValueSplit::MakeFromInt128(this, x.value());
- auto y_split = ValueSplit::MakeFromInt128(this, y.value());
-
- std::vector<llvm::Value*> args = {
- execution_context, x_split.high(), x_split.low(), x.precision(), x.scale(),
- y_split.high(), y_split.low(), y.precision(), y.scale(), out.precision(),
- out.scale(), out_high_ptr, out_low_ptr,
- };
- ir_builder()->CreateCall(module()->getFunction(internal_fname), args);
-
- auto out_high = ir_builder()->CreateLoad(out_high_ptr);
- auto out_low = ir_builder()->CreateLoad(out_low_ptr);
- auto result = ValueSplit(out_high, out_low).AsInt128(this);
-
- ir_builder()->CreateRet(result);
- return Status::OK();
-}
-
Status DecimalIR::BuildCompare(const std::string& function_name,
llvm::ICmpInst::Predicate cmp_instruction) {
// Create fn prototype :
@@ -495,50 +403,47 @@ Status DecimalIR::BuildCompare(const std::string& function_name,
y_split.high(), y_split.low(), y.precision(), y.scale(),
};
auto cmp_value = ir_builder()->CreateCall(
- module()->getFunction("compare_internal_decimal128_decimal128"), args);
+ module()->getFunction("compare_decimal128_decimal128_internal"), args);
auto result =
ir_builder()->CreateICmp(cmp_instruction, cmp_value, types()->i32_constant(0));
ir_builder()->CreateRet(result);
return Status::OK();
}
-Status DecimalIR::BuildDecimalFunction(const std::string& function_name,
- llvm::Type* return_type,
- std::vector<NamedArg> in_types) {
- auto i64 = types()->i64_type();
- auto i128 = types()->i128_type();
- auto function = BuildFunction(function_name, return_type, in_types);
-
- auto entry = llvm::BasicBlock::Create(*context(), "entry", function);
- ir_builder()->SetInsertPoint(entry);
+llvm::Value* DecimalIR::CallDecimalFunction(const std::string& function_name,
+ llvm::Type* return_type,
+ const std::vector<llvm::Value*>& params) {
+ if (kDecimalIRBuilderFunctions.count(function_name) != 0) {
+ // this is fn built with the irbuilder.
+ return ir_builder()->CreateCall(module()->getFunction(function_name), params);
+ }
- std::vector<llvm::Value*> args;
- int arg_idx = 0;
- auto arg_iter = function->arg_begin();
- for (auto& type : in_types) {
- if (type.type == i128) {
+ // ppre-compiler fn : disassemble i128 to two i64s and re-assemble.
+ auto i128 = types()->i128_type();
+ auto i64 = types()->i64_type();
+ std::vector<llvm::Value*> dis_assembled_args;
+ for (auto& arg : params) {
+ if (arg->getType() == i128) {
// split i128 arg into two int64s.
- auto split = ValueSplit::MakeFromInt128(this, &arg_iter[arg_idx]);
- args.push_back(split.high());
- args.push_back(split.low());
+ auto split = ValueSplit::MakeFromInt128(this, arg);
+ dis_assembled_args.push_back(split.high());
+ dis_assembled_args.push_back(split.low());
} else {
- args.push_back(&arg_iter[arg_idx]);
+ dis_assembled_args.push_back(arg);
}
- ++arg_idx;
}
- auto internal_name = function_name + "_internal";
llvm::Value* result = nullptr;
if (return_type == i128) {
// for i128 ret, replace with two int64* args, and join them.
auto block = ir_builder()->GetInsertBlock();
auto out_high_ptr = new llvm::AllocaInst(i64, 0, "out_hi", block);
auto out_low_ptr = new llvm::AllocaInst(i64, 0, "out_low", block);
- args.push_back(out_high_ptr);
- args.push_back(out_low_ptr);
+ dis_assembled_args.push_back(out_high_ptr);
+ dis_assembled_args.push_back(out_low_ptr);
// Make call to pre-compiled IR function.
- ir_builder()->CreateCall(module()->getFunction(internal_name), args);
+ ir_builder()->CreateCall(module()->getFunction(function_name), dis_assembled_args);
auto out_high = ir_builder()->CreateLoad(out_high_ptr);
auto out_low = ir_builder()->CreateLoad(out_low_ptr);
@@ -547,21 +452,14 @@ Status DecimalIR::BuildDecimalFunction(const std::string& function_name,
DCHECK_NE(return_type, types()->void_type());
// Make call to pre-compiled IR function.
- result = ir_builder()->CreateCall(module()->getFunction(internal_name), args);
+ result = ir_builder()->CreateCall(module()->getFunction(function_name),
+ dis_assembled_args);
}
- ir_builder()->CreateRet(result);
- return Status::OK();
+ return result;
}
Status DecimalIR::AddFunctions(Engine* engine) {
auto decimal_ir = std::make_shared<DecimalIR>(engine);
- auto i128 = decimal_ir->types()->i128_type();
- auto i32 = decimal_ir->types()->i32_type();
- auto i1 = decimal_ir->types()->i1_type();
- auto i64 = decimal_ir->types()->i64_type();
- auto f64 = decimal_ir->types()->double_type();
- auto i8_ptr = decimal_ir->types()->i8_ptr_type();
- auto i32_ptr = decimal_ir->types()->i32_ptr_type();
// Populate global variables used by decimal operations.
decimal_ir->AddGlobals(engine);
@@ -571,278 +469,12 @@ Status DecimalIR::AddFunctions(Engine* engine) {
ARROW_RETURN_NOT_OK(decimal_ir->BuildAdd());
ARROW_RETURN_NOT_OK(decimal_ir->BuildSubtract());
- ARROW_RETURN_NOT_OK(decimal_ir->BuildMultiply());
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDivideOrMod(
- "divide_decimal128_decimal128", "divide_internal_decimal128_decimal128"));
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDivideOrMod("mod_decimal128_decimal128",
- "mod_internal_decimal128_decimal128"));
-
- ARROW_RETURN_NOT_OK(
- decimal_ir->BuildCompare("equal_decimal128_decimal128", llvm::ICmpInst::ICMP_EQ));
- ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare("not_equal_decimal128_decimal128",
- llvm::ICmpInst::ICMP_NE));
- ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare("less_than_decimal128_decimal128",
- llvm::ICmpInst::ICMP_SLT));
- ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(
- "less_than_or_equal_to_decimal128_decimal128", llvm::ICmpInst::ICMP_SLE));
- ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare("greater_than_decimal128_decimal128",
- llvm::ICmpInst::ICMP_SGT));
- ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(
- "greater_than_or_equal_to_decimal128_decimal128", llvm::ICmpInst::ICMP_SGE));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("abs_decimal128", i128,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"out_precision", i32},
- {"out_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("ceil_decimal128", i128,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"out_precision", i32},
- {"out_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("floor_decimal128", i128,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"out_precision", i32},
- {"out_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("round_decimal128", i128,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"out_precision", i32},
- {"out_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("round_decimal128_int32", i128,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"round_scale", i32},
- {"out_precision", i32},
- {"out_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("truncate_decimal128", i128,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"out_precision", i32},
- {"out_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("truncate_decimal128_int32", i128,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"round_scale", i32},
- {"out_precision", i32},
- {"out_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castDECIMAL_int64", i128,
- {
- {"value", i64},
- {"out_precision", i32},
- {"out_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castDECIMAL_float64", i128,
- {
- {"value", f64},
- {"out_precision", i32},
- {"out_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castDECIMAL_decimal128", i128,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"out_precision", i32},
- {"out_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castBIGINT_decimal128", i64,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castFLOAT8_decimal128", f64,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash_decimal128", i32,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash32_decimal128", i32,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash64_decimal128", i64,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash32WithSeed_decimal128", i32,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- {"seed", i32},
- {"seed_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash64WithSeed_decimal128", i64,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- {"seed", i64},
- {"seed_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash32AsDouble_decimal128", i32,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("hash64AsDouble_decimal128", i64,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(
- decimal_ir->BuildDecimalFunction("hash32AsDoubleWithSeed_decimal128", i32,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- {"seed", i32},
- {"seed_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(
- decimal_ir->BuildDecimalFunction("hash64AsDoubleWithSeed_decimal128", i64,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- {"seed", i64},
- {"seed_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("isnull_decimal128", i1,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("isnotnull_decimal128", i1,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("isnumeric_decimal128", i1,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(
- decimal_ir->BuildDecimalFunction("is_distinct_from_decimal128_decimal128", i1,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- {"y_value", i128},
- {"y_precision", i32},
- {"y_scale", i32},
- {"y_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(
- decimal_ir->BuildDecimalFunction("is_not_distinct_from_decimal128_decimal128", i1,
- {
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"x_isvalid", i1},
- {"y_value", i128},
- {"y_precision", i32},
- {"y_scale", i32},
- {"y_isvalid", i1},
- }));
-
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castDECIMAL_utf8", i128,
- {
- {"context", i64},
- {"in", i8_ptr},
- {"in_len", i32},
- {"out_precision", i32},
- {"out_scale", i32},
- }));
- ARROW_RETURN_NOT_OK(decimal_ir->BuildDecimalFunction("castVARCHAR_decimal128_int64",
- i8_ptr,
- {
- {"context", i64},
- {"x_value", i128},
- {"x_precision", i32},
- {"x_scale", i32},
- {"out_len_param", i64},
- {"out_length", i32_ptr},
- }));
-
+ ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kEQFunction, llvm::ICmpInst::ICMP_EQ));
+ ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kNEFunction, llvm::ICmpInst::ICMP_NE));
+ ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kLTFunction, llvm::ICmpInst::ICMP_SLT));
+ ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kLEFunction, llvm::ICmpInst::ICMP_SLE));
+ ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kGTFunction, llvm::ICmpInst::ICMP_SGT));
+ ARROW_RETURN_NOT_OK(decimal_ir->BuildCompare(kGEFunction, llvm::ICmpInst::ICMP_SGE));
return Status::OK();
}
diff --git a/cpp/src/gandiva/decimal_ir.h b/cpp/src/gandiva/decimal_ir.h
index c2a22b3..6503c82 100644
--- a/cpp/src/gandiva/decimal_ir.h
+++ b/cpp/src/gandiva/decimal_ir.h
@@ -37,6 +37,10 @@ class DecimalIR : public FunctionIRBuilder {
void EnableTraces() { enable_ir_traces_ = true; }
+ llvm::Value* CallDecimalFunction(const std::string& function_name,
+ llvm::Type* return_type,
+ const std::vector<llvm::Value*>& args);
+
private:
/// The intrinsic fn for divide with small divisors is about 10x slower, so not
/// using these.
diff --git a/cpp/src/gandiva/function_registry_arithmetic.cc b/cpp/src/gandiva/function_registry_arithmetic.cc
index f7f88bb..f5d5ce7 100644
--- a/cpp/src/gandiva/function_registry_arithmetic.cc
+++ b/cpp/src/gandiva/function_registry_arithmetic.cc
@@ -46,7 +46,9 @@ std::vector<NativeFunction> GetArithmeticFunctionRegistry() {
UNARY_CAST_TO_FLOAT64(float32), UNARY_CAST_TO_FLOAT64(decimal128),
// cast to decimal
+ UNARY_SAFE_NULL_IF_NULL(castDECIMAL, int32, decimal128),
UNARY_SAFE_NULL_IF_NULL(castDECIMAL, int64, decimal128),
+ UNARY_SAFE_NULL_IF_NULL(castDECIMAL, float32, decimal128),
UNARY_SAFE_NULL_IF_NULL(castDECIMAL, float64, decimal128),
UNARY_SAFE_NULL_IF_NULL(castDECIMAL, decimal128, decimal128),
UNARY_UNSAFE_NULL_IF_NULL(castDECIMAL, utf8, decimal128),
diff --git a/cpp/src/gandiva/gdv_function_stubs.cc b/cpp/src/gandiva/gdv_function_stubs.cc
index 1d8fe9b..08d12d0 100644
--- a/cpp/src/gandiva/gdv_function_stubs.cc
+++ b/cpp/src/gandiva/gdv_function_stubs.cc
@@ -119,10 +119,10 @@ char* gdv_fn_dec_to_string(int64_t context, int64_t x_high, uint64_t x_low,
std::string dec_str = dec.ToString(x_scale);
*dec_str_len = static_cast<int32_t>(dec_str.length());
char* ret = reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, *dec_str_len));
- if (ret == NULLPTR) {
+ if (ret == nullptr) {
std::string err_msg = "Could not allocate memory for string: " + dec_str;
gdv_fn_context_set_error_msg(context, err_msg.data());
- return NULLPTR;
+ return nullptr;
}
memcpy(ret, dec_str.data(), *dec_str_len);
return ret;
diff --git a/cpp/src/gandiva/llvm_generator.cc b/cpp/src/gandiva/llvm_generator.cc
index f540755..57f67cb 100644
--- a/cpp/src/gandiva/llvm_generator.cc
+++ b/cpp/src/gandiva/llvm_generator.cc
@@ -25,6 +25,7 @@
#include <vector>
#include "gandiva/bitmap_accumulator.h"
+#include "gandiva/decimal_ir.h"
#include "gandiva/dex.h"
#include "gandiva/expr_decomposer.h"
#include "gandiva/expression.h"
@@ -1112,6 +1113,7 @@ LValuePtr LLVMGenerator::Visitor::BuildFunctionCall(const NativeFunction* func,
auto types = generator_->types();
auto arrow_return_type_id = arrow_return_type->id();
auto llvm_return_type = types->IRType(arrow_return_type_id);
+ DecimalIR decimalIR(generator_->engine_.get());
if (arrow_return_type_id == arrow::Type::DECIMAL) {
// For decimal fns, the output precision/scale are passed along as parameters.
@@ -1127,10 +1129,16 @@ LValuePtr LLVMGenerator::Visitor::BuildFunctionCall(const NativeFunction* func,
params->push_back(ret_lvalue->scale());
// Make the function call
- auto out = generator_->AddFunctionCall(func->pc_name(), llvm_return_type, *params);
+ auto out = decimalIR.CallDecimalFunction(func->pc_name(), llvm_return_type, *params);
ret_lvalue->set_data(out);
return std::move(ret_lvalue);
} else {
+ bool isDecimalFunction = false;
+ for (auto& arg : *params) {
+ if (arg->getType() == types->i128_type()) {
+ isDecimalFunction = true;
+ }
+ }
// add extra arg for return length for variable len return types (alloced on stack).
llvm::AllocaInst* result_len_ptr = nullptr;
if (arrow::is_binary_like(arrow_return_type_id)) {
@@ -1142,7 +1150,10 @@ LValuePtr LLVMGenerator::Visitor::BuildFunctionCall(const NativeFunction* func,
// Make the function call
llvm::IRBuilder<>* builder = ir_builder();
- auto value = generator_->AddFunctionCall(func->pc_name(), llvm_return_type, *params);
+ auto value =
+ isDecimalFunction
+ ? decimalIR.CallDecimalFunction(func->pc_name(), llvm_return_type, *params)
+ : generator_->AddFunctionCall(func->pc_name(), llvm_return_type, *params);
auto value_len =
(result_len_ptr == nullptr) ? nullptr : builder->CreateLoad(result_len_ptr);
return std::make_shared<LValue>(value, value_len);
diff --git a/cpp/src/gandiva/precompiled/decimal_wrapper.cc b/cpp/src/gandiva/precompiled/decimal_wrapper.cc
index 620b443..66ccb3e 100644
--- a/cpp/src/gandiva/precompiled/decimal_wrapper.cc
+++ b/cpp/src/gandiva/precompiled/decimal_wrapper.cc
@@ -35,12 +35,11 @@ void add_large_decimal128_decimal128(int64_t x_high, uint64_t x_low, int32_t x_p
}
FORCE_INLINE
-void multiply_internal_decimal128_decimal128(int64_t x_high, uint64_t x_low,
- int32_t x_precision, int32_t x_scale,
- int64_t y_high, uint64_t y_low,
- int32_t y_precision, int32_t y_scale,
- int32_t out_precision, int32_t out_scale,
- int64_t* out_high, uint64_t* out_low) {
+void multiply_decimal128_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, int64_t y_high, uint64_t y_low,
+ int32_t y_precision, int32_t y_scale,
+ int32_t out_precision, int32_t out_scale,
+ int64_t* out_high, uint64_t* out_low) {
gandiva::BasicDecimalScalar128 x(x_high, x_low, x_precision, x_scale);
gandiva::BasicDecimalScalar128 y(y_high, y_low, y_precision, y_scale);
bool overflow;
@@ -53,10 +52,11 @@ void multiply_internal_decimal128_decimal128(int64_t x_high, uint64_t x_low,
}
FORCE_INLINE
-void divide_internal_decimal128_decimal128(
- int64_t context, int64_t x_high, uint64_t x_low, int32_t x_precision, int32_t x_scale,
- int64_t y_high, uint64_t y_low, int32_t y_precision, int32_t y_scale,
- int32_t out_precision, int32_t out_scale, int64_t* out_high, uint64_t* out_low) {
+void divide_decimal128_decimal128(int64_t context, int64_t x_high, uint64_t x_low,
+ int32_t x_precision, int32_t x_scale, int64_t y_high,
+ uint64_t y_low, int32_t y_precision, int32_t y_scale,
+ int32_t out_precision, int32_t out_scale,
+ int64_t* out_high, uint64_t* out_low) {
gandiva::BasicDecimalScalar128 x(x_high, x_low, x_precision, x_scale);
gandiva::BasicDecimalScalar128 y(y_high, y_low, y_precision, y_scale);
bool overflow;
@@ -69,12 +69,11 @@ void divide_internal_decimal128_decimal128(
}
FORCE_INLINE
-void mod_internal_decimal128_decimal128(int64_t context, int64_t x_high, uint64_t x_low,
- int32_t x_precision, int32_t x_scale,
- int64_t y_high, uint64_t y_low,
- int32_t y_precision, int32_t y_scale,
- int32_t out_precision, int32_t out_scale,
- int64_t* out_high, uint64_t* out_low) {
+void mod_decimal128_decimal128(int64_t context, int64_t x_high, uint64_t x_low,
+ int32_t x_precision, int32_t x_scale, int64_t y_high,
+ uint64_t y_low, int32_t y_precision, int32_t y_scale,
+ int32_t out_precision, int32_t out_scale,
+ int64_t* out_high, uint64_t* out_low) {
gandiva::BasicDecimalScalar128 x(x_high, x_low, x_precision, x_scale);
gandiva::BasicDecimalScalar128 y(y_high, y_low, y_precision, y_scale);
bool overflow;
@@ -87,7 +86,7 @@ void mod_internal_decimal128_decimal128(int64_t context, int64_t x_high, uint64_
}
FORCE_INLINE
-int32_t compare_internal_decimal128_decimal128(int64_t x_high, uint64_t x_low,
+int32_t compare_decimal128_decimal128_internal(int64_t x_high, uint64_t x_low,
int32_t x_precision, int32_t x_scale,
int64_t y_high, uint64_t y_low,
int32_t y_precision, int32_t y_scale) {
@@ -98,9 +97,9 @@ int32_t compare_internal_decimal128_decimal128(int64_t x_high, uint64_t x_low,
}
FORCE_INLINE
-void abs_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, int32_t out_precision, int32_t out_scale,
- int64_t* out_high, uint64_t* out_low) {
+void abs_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, int32_t x_scale,
+ int32_t out_precision, int32_t out_scale, int64_t* out_high,
+ uint64_t* out_low) {
gandiva::BasicDecimal128 x(x_high, x_low);
x.Abs();
*out_high = x.high_bits();
@@ -108,9 +107,9 @@ void abs_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision
}
FORCE_INLINE
-void ceil_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, int32_t out_precision, int32_t out_scale,
- int64_t* out_high, uint64_t* out_low) {
+void ceil_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision, int32_t x_scale,
+ int32_t out_precision, int32_t out_scale, int64_t* out_high,
+ uint64_t* out_low) {
gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale);
bool overflow = false;
@@ -120,9 +119,9 @@ void ceil_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precisio
}
FORCE_INLINE
-void floor_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, int32_t out_precision, int32_t out_scale,
- int64_t* out_high, uint64_t* out_low) {
+void floor_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, int32_t out_precision, int32_t out_scale,
+ int64_t* out_high, uint64_t* out_low) {
gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale);
bool overflow = false;
@@ -132,9 +131,9 @@ void floor_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precisi
}
FORCE_INLINE
-void round_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, int32_t out_precision, int32_t out_scale,
- int64_t* out_high, uint64_t* out_low) {
+void round_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, int32_t out_precision, int32_t out_scale,
+ int64_t* out_high, uint64_t* out_low) {
gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale);
bool overflow = false;
@@ -144,10 +143,10 @@ void round_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precisi
}
FORCE_INLINE
-void round_decimal128_int32_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, int32_t rounding_scale,
- int32_t out_precision, int32_t out_scale,
- int64_t* out_high, uint64_t* out_low) {
+void round_decimal128_int32(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, int32_t rounding_scale,
+ int32_t out_precision, int32_t out_scale, int64_t* out_high,
+ uint64_t* out_low) {
gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale);
bool overflow = false;
@@ -157,10 +156,9 @@ void round_decimal128_int32_internal(int64_t x_high, uint64_t x_low, int32_t x_p
}
FORCE_INLINE
-void truncate_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, int32_t out_precision,
- int32_t out_scale, int64_t* out_high,
- uint64_t* out_low) {
+void truncate_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, int32_t out_precision, int32_t out_scale,
+ int64_t* out_high, uint64_t* out_low) {
gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale);
bool overflow = false;
@@ -170,11 +168,10 @@ void truncate_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_prec
}
FORCE_INLINE
-void truncate_decimal128_int32_internal(int64_t x_high, uint64_t x_low,
- int32_t x_precision, int32_t x_scale,
- int32_t rounding_scale, int32_t out_precision,
- int32_t out_scale, int64_t* out_high,
- uint64_t* out_low) {
+void truncate_decimal128_int32(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, int32_t rounding_scale,
+ int32_t out_precision, int32_t out_scale,
+ int64_t* out_high, uint64_t* out_low) {
gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale);
bool overflow = false;
@@ -184,8 +181,8 @@ void truncate_decimal128_int32_internal(int64_t x_high, uint64_t x_low,
}
FORCE_INLINE
-double castFLOAT8_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale) {
+double castFLOAT8_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale) {
gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale);
bool overflow = false;
@@ -193,8 +190,8 @@ double castFLOAT8_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_
}
FORCE_INLINE
-int64_t castBIGINT_decimal128_internal(int64_t x_high, uint64_t x_low,
- int32_t x_precision, int32_t x_scale) {
+int64_t castBIGINT_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale) {
gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale);
bool overflow = false;
@@ -202,8 +199,8 @@ int64_t castBIGINT_decimal128_internal(int64_t x_high, uint64_t x_low,
}
FORCE_INLINE
-void castDECIMAL_int64_internal(int64_t in, int32_t x_precision, int32_t x_scale,
- int64_t* out_high, uint64_t* out_low) {
+void castDECIMAL_int64(int64_t in, int32_t x_precision, int32_t x_scale,
+ int64_t* out_high, uint64_t* out_low) {
bool overflow = false;
auto out = gandiva::decimalops::FromInt64(in, x_precision, x_scale, &overflow);
*out_high = out.high_bits();
@@ -211,8 +208,14 @@ void castDECIMAL_int64_internal(int64_t in, int32_t x_precision, int32_t x_scale
}
FORCE_INLINE
-void castDECIMAL_float64_internal(double in, int32_t x_precision, int32_t x_scale,
- int64_t* out_high, uint64_t* out_low) {
+void castDECIMAL_int32(int32_t in, int32_t x_precision, int32_t x_scale,
+ int64_t* out_high, uint64_t* out_low) {
+ castDECIMAL_int64(in, x_precision, x_scale, out_high, out_low);
+}
+
+FORCE_INLINE
+void castDECIMAL_float64(double in, int32_t x_precision, int32_t x_scale,
+ int64_t* out_high, uint64_t* out_low) {
bool overflow = false;
auto out = gandiva::decimalops::FromDouble(in, x_precision, x_scale, &overflow);
*out_high = out.high_bits();
@@ -220,10 +223,15 @@ void castDECIMAL_float64_internal(double in, int32_t x_precision, int32_t x_scal
}
FORCE_INLINE
-void castDECIMAL_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, int32_t out_precision,
- int32_t out_scale, int64_t* out_high,
- int64_t* out_low) {
+void castDECIMAL_float32(float in, int32_t x_precision, int32_t x_scale,
+ int64_t* out_high, uint64_t* out_low) {
+ castDECIMAL_float64(in, x_precision, x_scale, out_high, out_low);
+}
+
+FORCE_INLINE
+void castDECIMAL_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, int32_t out_precision, int32_t out_scale,
+ int64_t* out_high, int64_t* out_low) {
gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale);
bool overflow = false;
auto out = gandiva::decimalops::Convert(x, out_precision, out_scale, &overflow);
@@ -232,32 +240,31 @@ void castDECIMAL_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_p
}
FORCE_INLINE
-int32_t hash32_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, boolean x_isvalid) {
+int32_t hash32_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, boolean x_isvalid) {
return x_isvalid
? hash32_buf(gandiva::BasicDecimal128(x_high, x_low).ToBytes().data(), 16, 0)
: 0;
}
FORCE_INLINE
-int32_t hash_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, boolean x_isvalid) {
- return hash32_decimal128_internal(x_high, x_low, x_precision, x_scale, x_isvalid);
+int32_t hash_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, boolean x_isvalid) {
+ return hash32_decimal128(x_high, x_low, x_precision, x_scale, x_isvalid);
}
FORCE_INLINE
-int64_t hash64_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, boolean x_isvalid) {
+int64_t hash64_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, boolean x_isvalid) {
return x_isvalid
? hash64_buf(gandiva::BasicDecimal128(x_high, x_low).ToBytes().data(), 16, 0)
: 0;
}
FORCE_INLINE
-int32_t hash32WithSeed_decimal128_internal(int64_t x_high, uint64_t x_low,
- int32_t x_precision, int32_t x_scale,
- boolean x_isvalid, int32_t seed,
- boolean seed_isvalid) {
+int32_t hash32WithSeed_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, boolean x_isvalid, int32_t seed,
+ boolean seed_isvalid) {
if (!x_isvalid) {
return seed;
}
@@ -265,10 +272,9 @@ int32_t hash32WithSeed_decimal128_internal(int64_t x_high, uint64_t x_low,
}
FORCE_INLINE
-int64_t hash64WithSeed_decimal128_internal(int64_t x_high, uint64_t x_low,
- int32_t x_precision, int32_t x_scale,
- boolean x_isvalid, int64_t seed,
- boolean seed_isvalid) {
+int64_t hash64WithSeed_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, boolean x_isvalid, int64_t seed,
+ boolean seed_isvalid) {
if (!x_isvalid) {
return seed;
}
@@ -276,28 +282,26 @@ int64_t hash64WithSeed_decimal128_internal(int64_t x_high, uint64_t x_low,
}
FORCE_INLINE
-int32_t hash32AsDouble_decimal128_internal(int64_t x_high, uint64_t x_low,
- int32_t x_precision, int32_t x_scale,
- boolean x_isvalid) {
+int32_t hash32AsDouble_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, boolean x_isvalid) {
return x_isvalid
? hash32_buf(gandiva::BasicDecimal128(x_high, x_low).ToBytes().data(), 16, 0)
: 0;
}
FORCE_INLINE
-int64_t hash64AsDouble_decimal128_internal(int64_t x_high, uint64_t x_low,
- int32_t x_precision, int32_t x_scale,
- boolean x_isvalid) {
+int64_t hash64AsDouble_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, boolean x_isvalid) {
return x_isvalid
? hash64_buf(gandiva::BasicDecimal128(x_high, x_low).ToBytes().data(), 16, 0)
: 0;
}
FORCE_INLINE
-int32_t hash32AsDoubleWithSeed_decimal128_internal(int64_t x_high, uint64_t x_low,
- int32_t x_precision, int32_t x_scale,
- boolean x_isvalid, int32_t seed,
- boolean seed_isvalid) {
+int32_t hash32AsDoubleWithSeed_decimal128(int64_t x_high, uint64_t x_low,
+ int32_t x_precision, int32_t x_scale,
+ boolean x_isvalid, int32_t seed,
+ boolean seed_isvalid) {
if (!x_isvalid) {
return seed;
}
@@ -305,10 +309,10 @@ int32_t hash32AsDoubleWithSeed_decimal128_internal(int64_t x_high, uint64_t x_lo
}
FORCE_INLINE
-int64_t hash64AsDoubleWithSeed_decimal128_internal(int64_t x_high, uint64_t x_low,
- int32_t x_precision, int32_t x_scale,
- boolean x_isvalid, int64_t seed,
- boolean seed_isvalid) {
+int64_t hash64AsDoubleWithSeed_decimal128(int64_t x_high, uint64_t x_low,
+ int32_t x_precision, int32_t x_scale,
+ boolean x_isvalid, int64_t seed,
+ boolean seed_isvalid) {
if (!x_isvalid) {
return seed;
}
@@ -316,52 +320,54 @@ int64_t hash64AsDoubleWithSeed_decimal128_internal(int64_t x_high, uint64_t x_lo
}
FORCE_INLINE
-boolean isnull_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, boolean x_isvalid) {
+boolean isnull_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, boolean x_isvalid) {
return !x_isvalid;
}
FORCE_INLINE
-boolean isnotnull_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, boolean x_isvalid) {
+boolean isnotnull_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, boolean x_isvalid) {
return x_isvalid;
}
FORCE_INLINE
-boolean isnumeric_decimal128_internal(int64_t x_high, uint64_t x_low, int32_t x_precision,
- int32_t x_scale, boolean x_isvalid) {
+boolean isnumeric_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
+ int32_t x_scale, boolean x_isvalid) {
return x_isvalid;
}
FORCE_INLINE
-boolean is_not_distinct_from_decimal128_decimal128_internal(
- int64_t x_high, uint64_t x_low, int32_t x_precision, int32_t x_scale,
- boolean x_isvalid, int64_t y_high, uint64_t y_low, int32_t y_precision,
- int32_t y_scale, boolean y_isvalid) {
+boolean is_not_distinct_from_decimal128_decimal128(int64_t x_high, uint64_t x_low,
+ int32_t x_precision, int32_t x_scale,
+ boolean x_isvalid, int64_t y_high,
+ uint64_t y_low, int32_t y_precision,
+ int32_t y_scale, boolean y_isvalid) {
if (x_isvalid != y_isvalid) {
return false;
}
if (!x_isvalid) {
return true;
}
- return 0 == compare_internal_decimal128_decimal128(x_high, x_low, x_precision, x_scale,
+ return 0 == compare_decimal128_decimal128_internal(x_high, x_low, x_precision, x_scale,
y_high, y_low, y_precision, y_scale);
}
FORCE_INLINE
-boolean is_distinct_from_decimal128_decimal128_internal(
- int64_t x_high, uint64_t x_low, int32_t x_precision, int32_t x_scale,
- boolean x_isvalid, int64_t y_high, uint64_t y_low, int32_t y_precision,
- int32_t y_scale, boolean y_isvalid) {
- return !is_not_distinct_from_decimal128_decimal128_internal(
- x_high, x_low, x_precision, x_scale, x_isvalid, y_high, y_low, y_precision, y_scale,
- y_isvalid);
+boolean is_distinct_from_decimal128_decimal128(int64_t x_high, uint64_t x_low,
+ int32_t x_precision, int32_t x_scale,
+ boolean x_isvalid, int64_t y_high,
+ uint64_t y_low, int32_t y_precision,
+ int32_t y_scale, boolean y_isvalid) {
+ return !is_not_distinct_from_decimal128_decimal128(x_high, x_low, x_precision, x_scale,
+ x_isvalid, y_high, y_low,
+ y_precision, y_scale, y_isvalid);
}
FORCE_INLINE
-void castDECIMAL_utf8_internal(int64_t context, const char* in, int32_t in_length,
- int32_t out_precision, int32_t out_scale,
- int64_t* out_high, uint64_t* out_low) {
+void castDECIMAL_utf8(int64_t context, const char* in, int32_t in_length,
+ int32_t out_precision, int32_t out_scale, int64_t* out_high,
+ uint64_t* out_low) {
int64_t dec_high_from_str;
uint64_t dec_low_from_str;
int32_t precision_from_str;
@@ -382,10 +388,9 @@ void castDECIMAL_utf8_internal(int64_t context, const char* in, int32_t in_lengt
}
FORCE_INLINE
-char* castVARCHAR_decimal128_int64_internal(int64_t context, int64_t x_high,
- uint64_t x_low, int32_t x_precision,
- int32_t x_scale, int64_t out_len_param,
- int32_t* out_length) {
+char* castVARCHAR_decimal128_int64(int64_t context, int64_t x_high, uint64_t x_low,
+ int32_t x_precision, int32_t x_scale,
+ int64_t out_len_param, int32_t* out_length) {
int32_t full_dec_str_len;
char* dec_str =
gdv_fn_dec_to_string(context, x_high, x_low, x_scale, &full_dec_str_len);
diff --git a/cpp/src/gandiva/tests/decimal_test.cc b/cpp/src/gandiva/tests/decimal_test.cc
index 1762d5b..2c29ccf 100644
--- a/cpp/src/gandiva/tests/decimal_test.cc
+++ b/cpp/src/gandiva/tests/decimal_test.cc
@@ -412,15 +412,22 @@ TEST_F(TestDecimal, TestCastFunctions) {
constexpr int32_t scale = 2;
auto decimal_type = std::make_shared<arrow::Decimal128Type>(precision, scale);
auto decimal_type_scale_1 = std::make_shared<arrow::Decimal128Type>(precision, 1);
- auto field_int64 = field("intt64", arrow::int64());
+ auto field_int32 = field("int32", arrow::int32());
+ auto field_int64 = field("int64", arrow::int64());
+ auto field_float32 = field("float32", arrow::float32());
auto field_float64 = field("float64", arrow::float64());
auto field_dec = field("dec", decimal_type);
- auto schema = arrow::schema({field_int64, field_float64, field_dec});
+ auto schema =
+ arrow::schema({field_int32, field_int64, field_float32, field_float64, field_dec});
// build expressions
auto exprs = std::vector<ExpressionPtr>{
+ TreeExprBuilder::MakeExpression("castDECIMAL", {field_int32},
+ field("int32_to_dec", decimal_type)),
TreeExprBuilder::MakeExpression("castDECIMAL", {field_int64},
field("int64_to_dec", decimal_type)),
+ TreeExprBuilder::MakeExpression("castDECIMAL", {field_float32},
+ field("float32_to_dec", decimal_type)),
TreeExprBuilder::MakeExpression("castDECIMAL", {field_float64},
field("float64_to_dec", decimal_type)),
TreeExprBuilder::MakeExpression("castDECIMAL", {field_dec},
@@ -440,15 +447,18 @@ TEST_F(TestDecimal, TestCastFunctions) {
int num_records = 4;
auto validity = {true, true, true, true};
+ auto array_int32 = MakeArrowArrayInt32({123, 158, -123, -158});
auto array_int64 = MakeArrowArrayInt64({123, 158, -123, -158});
+ auto array_float32 = MakeArrowArrayFloat32({1.23f, 1.58f, -1.23f, -1.58f});
auto array_float64 = MakeArrowArrayFloat64({1.23, 1.58, -1.23, -1.58});
auto array_dec = MakeArrowArrayDecimal(
decimal_type, MakeDecimalVector({"1.23", "1.58", "-1.23", "-1.58"}, scale),
validity);
// prepare input record batch
- auto in_batch = arrow::RecordBatch::Make(schema, num_records,
- {array_int64, array_float64, array_dec});
+ auto in_batch = arrow::RecordBatch::Make(
+ schema, num_records,
+ {array_int32, array_int64, array_float32, array_float64, array_dec});
// Evaluate expression
arrow::ArrayVector outputs;
@@ -457,28 +467,34 @@ TEST_F(TestDecimal, TestCastFunctions) {
// Validate results
- // castDECIMAL(int64)
+ // castDECIMAL(int32)
EXPECT_ARROW_ARRAY_EQUALS(
MakeArrowArrayDecimal(decimal_type,
MakeDecimalVector({"123", "158", "-123", "-158"}, scale),
validity),
outputs[0]);
+ // castDECIMAL(int64)
+ EXPECT_ARROW_ARRAY_EQUALS(array_dec, outputs[2]);
+
+ // castDECIMAL(float32)
+ EXPECT_ARROW_ARRAY_EQUALS(array_dec, outputs[2]);
+
// castDECIMAL(float64)
- EXPECT_ARROW_ARRAY_EQUALS(array_dec, outputs[1]);
+ EXPECT_ARROW_ARRAY_EQUALS(array_dec, outputs[3]);
// castDECIMAL(decimal)
EXPECT_ARROW_ARRAY_EQUALS(
MakeArrowArrayDecimal(arrow::decimal(precision, 1),
MakeDecimalVector({"1.2", "1.6", "-1.2", "-1.6"}, 1),
validity),
- outputs[2]);
+ outputs[4]);
// castBIGINT(decimal)
- EXPECT_ARROW_ARRAY_EQUALS(MakeArrowArrayInt64({1, 1, -1, -1}), outputs[3]);
+ EXPECT_ARROW_ARRAY_EQUALS(MakeArrowArrayInt64({1, 1, -1, -1}), outputs[5]);
// castDOUBLE(decimal)
- EXPECT_ARROW_ARRAY_EQUALS(array_float64, outputs[4]);
+ EXPECT_ARROW_ARRAY_EQUALS(array_float64, outputs[6]);
}
// isnull, isnumeric