diff --git a/cpp/src/gandiva/CMakeLists.txt b/cpp/src/gandiva/CMakeLists.txt index 67f455c681a4..f675775967df 100644 --- a/cpp/src/gandiva/CMakeLists.txt +++ b/cpp/src/gandiva/CMakeLists.txt @@ -59,6 +59,7 @@ set(SRC_FILES function_registry_datetime.cc function_registry_hash.cc function_registry_math_ops.cc + function_registry_math_ops_trig.cc function_registry_string.cc function_registry_timestamp_arithmetic.cc function_signature.cc diff --git a/cpp/src/gandiva/function_registry.cc b/cpp/src/gandiva/function_registry.cc index d5d015c10b4b..27f0b4def245 100644 --- a/cpp/src/gandiva/function_registry.cc +++ b/cpp/src/gandiva/function_registry.cc @@ -16,17 +16,19 @@ // under the License. #include "gandiva/function_registry.h" + +#include +#include +#include + #include "gandiva/function_registry_arithmetic.h" #include "gandiva/function_registry_datetime.h" #include "gandiva/function_registry_hash.h" #include "gandiva/function_registry_math_ops.h" +#include "gandiva/function_registry_math_ops_trig.h" #include "gandiva/function_registry_string.h" #include "gandiva/function_registry_timestamp_arithmetic.h" -#include -#include -#include - namespace gandiva { FunctionRegistry::iterator FunctionRegistry::begin() const { @@ -65,6 +67,9 @@ SignatureMap FunctionRegistry::InitPCMap() { auto v6 = GetDateTimeArithmeticFunctionRegistry(); pc_registry_.insert(std::end(pc_registry_), v6.begin(), v6.end()); + auto v7 = GetMathOpsTrigFunctionRegistry(); + pc_registry_.insert(std::end(pc_registry_), v7.begin(), v7.end()); + for (auto& elem : pc_registry_) { for (auto& func_signature : elem.signatures()) { map.insert(std::make_pair(&(func_signature), &elem)); diff --git a/cpp/src/gandiva/function_registry_arithmetic.cc b/cpp/src/gandiva/function_registry_arithmetic.cc index d24020fd0167..0c6976735411 100644 --- a/cpp/src/gandiva/function_registry_arithmetic.cc +++ b/cpp/src/gandiva/function_registry_arithmetic.cc @@ -16,6 +16,7 @@ // under the License. #include "gandiva/function_registry_arithmetic.h" + #include "gandiva/function_registry_common.h" namespace gandiva { @@ -38,11 +39,12 @@ std::vector GetArithmeticFunctionRegistry() { UNARY_SAFE_NULL_IF_NULL(not, {}, boolean, boolean), UNARY_SAFE_NULL_IF_NULL(castBIGINT, {}, int32, int64), UNARY_SAFE_NULL_IF_NULL(castINT, {}, int64, int32), + UNARY_SAFE_NULL_IF_NULL(castINT, {}, int8, int32), UNARY_SAFE_NULL_IF_NULL(castBIGINT, {}, decimal128, int64), // cast to float32 UNARY_CAST_TO_FLOAT32(int32), UNARY_CAST_TO_FLOAT32(int64), - UNARY_CAST_TO_FLOAT32(float64), + UNARY_CAST_TO_FLOAT32(float64), UNARY_CAST_TO_FLOAT32(int8), // cast to float64 UNARY_CAST_TO_FLOAT64(int32), UNARY_CAST_TO_FLOAT64(int64), diff --git a/cpp/src/gandiva/function_registry_math_ops.cc b/cpp/src/gandiva/function_registry_math_ops.cc index 771e363e3048..acd4962f7953 100644 --- a/cpp/src/gandiva/function_registry_math_ops.cc +++ b/cpp/src/gandiva/function_registry_math_ops.cc @@ -16,6 +16,7 @@ // under the License. #include "gandiva/function_registry_math_ops.h" + #include "gandiva/function_registry_common.h" namespace gandiva { @@ -28,6 +29,11 @@ namespace gandiva { UNARY_SAFE_NULL_IF_NULL(name, ALIASES, float32, float64), \ UNARY_SAFE_NULL_IF_NULL(name, ALIASES, float64, float64) +#define MATH_UNARY_OPS_FLOAT(name, ALIASES) \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, int32, float32), \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, uint32, float32), \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, float32, float32) + #define MATH_BINARY_UNSAFE(name, ALIASES) \ BINARY_UNSAFE_NULL_IF_NULL(name, ALIASES, int32, float64), \ BINARY_UNSAFE_NULL_IF_NULL(name, ALIASES, int64, float64), \ @@ -45,11 +51,16 @@ namespace gandiva { std::vector GetMathOpsFunctionRegistry() { static std::vector math_fn_registry_ = { MATH_UNARY_OPS(cbrt, {}), MATH_UNARY_OPS(exp, {}), MATH_UNARY_OPS(log, {}), - MATH_UNARY_OPS(log10, {}), + MATH_UNARY_OPS(log10, {}), MATH_UNARY_OPS(sqrt, {}), + + MATH_UNARY_OPS_FLOAT(sqrtf, {}), MATH_UNARY_OPS_FLOAT(cbrtf, {}), + MATH_UNARY_OPS_FLOAT(expf, {}), MATH_UNARY_OPS_FLOAT(logf, {}), + MATH_UNARY_OPS_FLOAT(log10f, {}), MATH_BINARY_UNSAFE(log, {}), BINARY_SYMMETRIC_SAFE_NULL_IF_NULL(power, {"pow"}, float64), + BINARY_SYMMETRIC_SAFE_NULL_IF_NULL(powerf, {"powf"}, float32), UNARY_SAFE_NULL_NEVER_BOOL_FN(isnull, {}), UNARY_SAFE_NULL_NEVER_BOOL_FN(isnotnull, {}), @@ -61,6 +72,7 @@ std::vector GetMathOpsFunctionRegistry() { // decimal functions UNARY_SAFE_NULL_IF_NULL(abs, {}, decimal128, decimal128), + UNARY_SAFE_NULL_IF_NULL(absf, {}, float32, float32), UNARY_SAFE_NULL_IF_NULL(ceil, {}, decimal128, decimal128), UNARY_SAFE_NULL_IF_NULL(floor, {}, decimal128, decimal128), UNARY_SAFE_NULL_IF_NULL(round, {}, decimal128, decimal128), @@ -82,6 +94,8 @@ std::vector GetMathOpsFunctionRegistry() { #undef MATH_UNARY_OPS +#undef MATH_UNARY_OPS_FLOAT + #undef MATH_BINARY_UNSAFE #undef UNARY_SAFE_NULL_NEVER_BOOL_FN diff --git a/cpp/src/gandiva/function_registry_math_ops_trig.cc b/cpp/src/gandiva/function_registry_math_ops_trig.cc new file mode 100644 index 000000000000..5e7a909b5a9e --- /dev/null +++ b/cpp/src/gandiva/function_registry_math_ops_trig.cc @@ -0,0 +1,52 @@ +// 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 "gandiva/function_registry_math_ops_trig.h" + +#include "gandiva/function_registry_common.h" + +namespace gandiva { + +#define MATH_UNARY_OPS(name, ALIASES) \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, int32, float64), \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, int64, float64), \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, uint32, float64), \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, uint64, float64), \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, float32, float64), \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, float64, float64) + +#define MATH_UNARY_OPS_FLOAT(name, ALIASES) \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, int32, float32), \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, uint32, float32), \ + UNARY_SAFE_NULL_IF_NULL(name, ALIASES, float32, float32) + +std::vector GetMathOpsTrigFunctionRegistry() { + static std::vector math_fn_registry_ = { + MATH_UNARY_OPS(sin, {}), MATH_UNARY_OPS(cos, {}), + MATH_UNARY_OPS(tan, {}), MATH_UNARY_OPS(asin, {}), + MATH_UNARY_OPS(acos, {}), MATH_UNARY_OPS(atan, {}), + + MATH_UNARY_OPS_FLOAT(sinf, {}), MATH_UNARY_OPS_FLOAT(cosf, {}), + MATH_UNARY_OPS_FLOAT(tanf, {}), MATH_UNARY_OPS_FLOAT(asinf, {}), + MATH_UNARY_OPS_FLOAT(acosf, {}), MATH_UNARY_OPS_FLOAT(atanf, {})}; + return math_fn_registry_; +} + +#undef MATH_UNARY_OPS + +#undef MATH_UNARY_OPS_FLOAT +} // namespace gandiva diff --git a/cpp/src/gandiva/function_registry_math_ops_trig.h b/cpp/src/gandiva/function_registry_math_ops_trig.h new file mode 100644 index 000000000000..1046b8ef41a5 --- /dev/null +++ b/cpp/src/gandiva/function_registry_math_ops_trig.h @@ -0,0 +1,28 @@ +// 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. + +#pragma once + +#include + +#include "gandiva/native_function.h" + +namespace gandiva { + +std::vector GetMathOpsTrigFunctionRegistry(); + +} // namespace gandiva diff --git a/cpp/src/gandiva/precompiled/CMakeLists.txt b/cpp/src/gandiva/precompiled/CMakeLists.txt index dff851789b2f..355c2ebbd94e 100644 --- a/cpp/src/gandiva/precompiled/CMakeLists.txt +++ b/cpp/src/gandiva/precompiled/CMakeLists.txt @@ -23,6 +23,7 @@ set(PRECOMPILED_SRCS decimal_ops.cc decimal_wrapper.cc extended_math_ops.cc + extended_math_ops_trig.cc hash.cc print.cc string_ops.cc @@ -119,6 +120,8 @@ if(ARROW_BUILD_TESTS) arithmetic_ops.cc extended_math_ops_test.cc extended_math_ops.cc + extended_math_ops_trig_test.cc + extended_math_ops_trig.cc decimal_ops_test.cc decimal_ops.cc ../decimal_type_util.cc diff --git a/cpp/src/gandiva/precompiled/arithmetic_ops.cc b/cpp/src/gandiva/precompiled/arithmetic_ops.cc index afeb2f9466bf..27f94cc4f217 100644 --- a/cpp/src/gandiva/precompiled/arithmetic_ops.cc +++ b/cpp/src/gandiva/precompiled/arithmetic_ops.cc @@ -18,6 +18,7 @@ extern "C" { #include + #include "./types.h" // Expand inner macro for all numeric types. @@ -107,6 +108,8 @@ NUMERIC_DATE_TYPES(BINARY_RELATIONAL, greater_than_or_equal_to, >=) CAST_UNARY(castBIGINT, int32, int64) CAST_UNARY(castINT, int64, int32) +CAST_UNARY(castINT, int8, int32) +CAST_UNARY(castFLOAT4, int8, float32) CAST_UNARY(castFLOAT4, int32, float32) CAST_UNARY(castFLOAT4, int64, float32) CAST_UNARY(castFLOAT8, int32, float64) diff --git a/cpp/src/gandiva/precompiled/extended_math_ops.cc b/cpp/src/gandiva/precompiled/extended_math_ops.cc index e6b6a6e3af11..9be72a6ac462 100644 --- a/cpp/src/gandiva/precompiled/extended_math_ops.cc +++ b/cpp/src/gandiva/precompiled/extended_math_ops.cc @@ -23,6 +23,7 @@ extern "C" { #include #include #include + #include "./types.h" // Expand the inner fn for types that support extended math. @@ -34,34 +35,79 @@ extern "C" { INNER(float32, OUT_TYPE) \ INNER(float64, OUT_TYPE) +#define ENUMERIC_TYPES_UNARY_FLOAT(INNER, OUT_TYPE) \ + INNER(int32, OUT_TYPE) \ + INNER(uint32, OUT_TYPE) \ + INNER(int64, OUT_TYPE) \ + INNER(uint64, OUT_TYPE) \ + INNER(float32, OUT_TYPE) + +// Square root +#define SQRTF(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE sqrtf_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(sqrtf(static_cast(in))); \ + } +#define SQRT(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE sqrt_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(sqrtl(static_cast(in))); \ + } + +ENUMERIC_TYPES_UNARY_FLOAT(SQRTF, float32) +ENUMERIC_TYPES_UNARY(SQRT, float64) + // Cubic root +#define CBRTF(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE cbrtf_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(cbrtf(static_cast(in))); \ + } #define CBRT(IN_TYPE, OUT_TYPE) \ FORCE_INLINE \ gdv_##OUT_TYPE cbrt_##IN_TYPE(gdv_##IN_TYPE in) { \ return static_cast(cbrtl(static_cast(in))); \ } +ENUMERIC_TYPES_UNARY_FLOAT(CBRTF, float32) ENUMERIC_TYPES_UNARY(CBRT, float64) // Exponent +#define EXPF(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE expf_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(expf(static_cast(in))); \ + } #define EXP(IN_TYPE, OUT_TYPE) \ FORCE_INLINE \ gdv_##OUT_TYPE exp_##IN_TYPE(gdv_##IN_TYPE in) { \ return static_cast(expl(static_cast(in))); \ } +ENUMERIC_TYPES_UNARY_FLOAT(EXPF, float32) ENUMERIC_TYPES_UNARY(EXP, float64) // log +#define LOGF(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE logf_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(logf(static_cast(in))); \ + } #define LOG(IN_TYPE, OUT_TYPE) \ FORCE_INLINE \ gdv_##OUT_TYPE log_##IN_TYPE(gdv_##IN_TYPE in) { \ return static_cast(logl(static_cast(in))); \ } +ENUMERIC_TYPES_UNARY_FLOAT(LOGF, float32) ENUMERIC_TYPES_UNARY(LOG, float64) // log base 10 +#define LOG10F(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE log10f_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(log10f(static_cast(in))); \ + } #define LOG10(IN_TYPE, OUT_TYPE) \ FORCE_INLINE \ gdv_##OUT_TYPE log10_##IN_TYPE(gdv_##IN_TYPE in) { \ @@ -70,6 +116,7 @@ ENUMERIC_TYPES_UNARY(LOG, float64) #define LOGL(VALUE) static_cast(logl(static_cast(VALUE))) +ENUMERIC_TYPES_UNARY_FLOAT(LOG10F, float32) ENUMERIC_TYPES_UNARY(LOG10, float64) FORCE_INLINE @@ -103,14 +150,34 @@ LOG_WITH_BASE(float32, float32, float64) LOG_WITH_BASE(float64, float64, float64) // power +#define POWERF(IN_TYPE1, IN_TYPE2, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE powerf_##IN_TYPE1##_##IN_TYPE2(gdv_##IN_TYPE1 in1, \ + gdv_##IN_TYPE2 in2) { \ + return static_cast(powf(in1, in2)); \ + } #define POWER(IN_TYPE1, IN_TYPE2, OUT_TYPE) \ FORCE_INLINE \ gdv_##OUT_TYPE power_##IN_TYPE1##_##IN_TYPE2(gdv_##IN_TYPE1 in1, gdv_##IN_TYPE2 in2) { \ return static_cast(powl(in1, in2)); \ } +POWERF(float32, float32, float32) POWER(float64, float64, float64) +// ABS +#define ABSF(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE absf_##IN_TYPE(gdv_##IN_TYPE in) { \ + if (static_cast(in) < 0) { \ + return static_cast(-in); \ + } else { \ + return static_cast(in); \ + } \ + } + +ABSF(float32, float32) + FORCE_INLINE gdv_int64 truncate_int64_int32(gdv_int64 in, gdv_int32 out_scale) { bool overflow = false; diff --git a/cpp/src/gandiva/precompiled/extended_math_ops_test.cc b/cpp/src/gandiva/precompiled/extended_math_ops_test.cc index 67ee6f5b3124..b611c43f139c 100644 --- a/cpp/src/gandiva/precompiled/extended_math_ops_test.cc +++ b/cpp/src/gandiva/precompiled/extended_math_ops_test.cc @@ -15,18 +15,23 @@ // specific language governing permissions and limitations // under the License. +#include +#include #include -#include #include "gandiva/execution_context.h" #include "gandiva/precompiled/types.h" namespace gandiva { -static const double MAX_ERROR = 0.00005; +TEST(TestExtendedMathOps, TestSqrt) { + VerifyFuzzyEquals(sqrt_int32(9), 3); + VerifyFuzzyEquals(sqrt_int64(9), 3); + VerifyFuzzyEquals(sqrt_float32(9), 3); + VerifyFuzzyEquals(sqrt_float64(9), 3); -void VerifyFuzzyEquals(double actual, double expected, double max_error = MAX_ERROR) { - EXPECT_TRUE(fabs(actual - expected) < max_error) << actual << " != " << expected; + VerifyFuzzyEquals(sqrt_float32(6.25), 2.5); + VerifyFuzzyEquals(sqrt_float64(6.25), 2.5); } TEST(TestExtendedMathOps, TestCbrt) { diff --git a/cpp/src/gandiva/precompiled/extended_math_ops_trig.cc b/cpp/src/gandiva/precompiled/extended_math_ops_trig.cc new file mode 100644 index 000000000000..a6d705fbd06c --- /dev/null +++ b/cpp/src/gandiva/precompiled/extended_math_ops_trig.cc @@ -0,0 +1,135 @@ +// 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 "gandiva/precompiled/decimal_ops.h" + +extern "C" { + +#include +#include +#include +#include + +#include "./types.h" + +// Expand the inner fn for types that support extended math. +#define ENUMERIC_TYPES_UNARY(INNER, OUT_TYPE) \ + INNER(int32, OUT_TYPE) \ + INNER(uint32, OUT_TYPE) \ + INNER(int64, OUT_TYPE) \ + INNER(uint64, OUT_TYPE) \ + INNER(float32, OUT_TYPE) \ + INNER(float64, OUT_TYPE) + +#define ENUMERIC_TYPES_UNARY_FLOAT(INNER, OUT_TYPE) \ + INNER(int32, OUT_TYPE) \ + INNER(uint32, OUT_TYPE) \ + INNER(int64, OUT_TYPE) \ + INNER(uint64, OUT_TYPE) \ + INNER(float32, OUT_TYPE) + +// Trigonometric functions +// Sine +#define SINF(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE sinf_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(sinf(static_cast(in))); \ + } +#define SIN(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE sin_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(sinl(static_cast(in))); \ + } + +ENUMERIC_TYPES_UNARY_FLOAT(SINF, float32) +ENUMERIC_TYPES_UNARY(SIN, float64) + +// Cosine +#define COSF(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE cosf_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(cosf(static_cast(in))); \ + } +#define COS(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE cos_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(cosl(static_cast(in))); \ + } + +ENUMERIC_TYPES_UNARY_FLOAT(COSF, float32) +ENUMERIC_TYPES_UNARY(COS, float64) + +// Tangent +#define TANF(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE tanf_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(tanf(static_cast(in))); \ + } +#define TAN(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE tan_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(tanl(static_cast(in))); \ + } + +ENUMERIC_TYPES_UNARY_FLOAT(TANF, float32) +ENUMERIC_TYPES_UNARY(TAN, float64) + +// Arc sine +#define ASINF(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE asinf_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(asinf(static_cast(in))); \ + } +#define ASIN(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE asin_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(asinl(static_cast(in))); \ + } + +ENUMERIC_TYPES_UNARY_FLOAT(ASINF, float32) +ENUMERIC_TYPES_UNARY(ASIN, float64) + +// Arc cosine +#define ACOSF(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE acosf_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(acosf(static_cast(in))); \ + } +#define ACOS(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE acos_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(acosl(static_cast(in))); \ + } + +ENUMERIC_TYPES_UNARY_FLOAT(ACOSF, float32) +ENUMERIC_TYPES_UNARY(ACOS, float64) + +// Arc tangent +#define ATANF(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE atanf_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(atanf(static_cast(in))); \ + } +#define ATAN(IN_TYPE, OUT_TYPE) \ + FORCE_INLINE \ + gdv_##OUT_TYPE atan_##IN_TYPE(gdv_##IN_TYPE in) { \ + return static_cast(atanl(static_cast(in))); \ + } + +ENUMERIC_TYPES_UNARY_FLOAT(ATANF, float32) +ENUMERIC_TYPES_UNARY(ATAN, float64) +} // extern "C" diff --git a/cpp/src/gandiva/precompiled/extended_math_ops_trig_test.cc b/cpp/src/gandiva/precompiled/extended_math_ops_trig_test.cc new file mode 100644 index 000000000000..5089688f3a05 --- /dev/null +++ b/cpp/src/gandiva/precompiled/extended_math_ops_trig_test.cc @@ -0,0 +1,68 @@ +// 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 "gandiva/execution_context.h" +#include "gandiva/precompiled/types.h" + +namespace gandiva { + +TEST(TestExtendedMathOps, TestSine) { + VerifyFuzzyEquals(sin_float32(M_PI_2), 1); + VerifyFuzzyEquals(sin_float64(M_PI_2), 1); + VerifyFuzzyEquals(sin_float32(M_PI_4), 0.7071); + VerifyFuzzyEquals(sin_float64(M_PI_4), 0.7071); +} + +TEST(TestExtendedMathOps, TestCosine) { + VerifyFuzzyEquals(cos_float32(M_PI_2), 0); + VerifyFuzzyEquals(cos_float64(M_PI_2), 0); + VerifyFuzzyEquals(cos_float32(M_PI_4), 0.7071); + VerifyFuzzyEquals(cos_float64(M_PI_4), 0.7071); +} + +TEST(TestExtendedMathOps, TestTangent) { + VerifyFuzzyEquals(tan_float32(M_PI / 3.), 1.73205); + VerifyFuzzyEquals(tan_float64(M_PI / 3.), 1.73205); + VerifyFuzzyEquals(tan_float32(M_PI_4), 1); + VerifyFuzzyEquals(tan_float64(M_PI_4), 1); +} + +TEST(TestExtendedMathOps, TestASine) { + VerifyFuzzyEquals(asin_float32(1), M_PI_2); + VerifyFuzzyEquals(asin_float64(1), M_PI_2); + VerifyFuzzyEquals(asin_float32(0.7071), M_PI_4); + VerifyFuzzyEquals(asin_float64(0.7071), M_PI_4); +} + +TEST(TestExtendedMathOps, TestACosine) { + VerifyFuzzyEquals(acos_float32(0), M_PI_2); + VerifyFuzzyEquals(acos_float64(0), M_PI_2); + VerifyFuzzyEquals(acos_float32(0.7071), M_PI_4); + VerifyFuzzyEquals(acos_float64(0.7071), M_PI_4); +} + +TEST(TestExtendedMathOps, TestATangent) { + VerifyFuzzyEquals(atan_float32(1.73205), M_PI / 3.); + VerifyFuzzyEquals(atan_float64(1.73205), M_PI / 3.); + VerifyFuzzyEquals(atan_float32(1), M_PI_4); + VerifyFuzzyEquals(atan_float64(1), M_PI_4); +} +} // namespace gandiva diff --git a/cpp/src/gandiva/precompiled/testing.h b/cpp/src/gandiva/precompiled/testing.h index b1e7753e8fc0..7885ad0c4653 100644 --- a/cpp/src/gandiva/precompiled/testing.h +++ b/cpp/src/gandiva/precompiled/testing.h @@ -17,12 +17,11 @@ #pragma once -#include - #include -#include "arrow/util/logging.h" +#include +#include "arrow/util/logging.h" #include "gandiva/date_utils.h" #include "gandiva/precompiled/types.h" @@ -36,4 +35,11 @@ static inline gdv_timestamp StringToTimestamp(const char* buf) { return out * 1000; } +static const double MAX_ERROR = 0.00005; + +void inline VerifyFuzzyEquals(double actual, double expected, + double max_error = MAX_ERROR) { + EXPECT_TRUE(fabs(actual - expected) < max_error) << actual << " != " << expected; +} + } // namespace gandiva diff --git a/cpp/src/gandiva/precompiled/types.h b/cpp/src/gandiva/precompiled/types.h index 45bc72b1b1d4..44a9b9331e2e 100644 --- a/cpp/src/gandiva/precompiled/types.h +++ b/cpp/src/gandiva/precompiled/types.h @@ -18,6 +18,7 @@ #pragma once #include + #include "gandiva/gdv_function_stubs.h" // Use the same names as in arrow data types. Makes it easy to write pre-processor macros. @@ -132,6 +133,11 @@ gdv_int64 div_int64_int64(gdv_int64 context, gdv_int64 in1, gdv_int64 in2); gdv_float32 div_float32_float32(gdv_int64 context, gdv_float32 in1, gdv_float32 in2); gdv_float64 div_float64_float64(gdv_int64 context, gdv_float64 in1, gdv_float64 in2); +gdv_float64 sqrt_int32(gdv_int32); +gdv_float64 sqrt_int64(gdv_int64); +gdv_float64 sqrt_float32(gdv_float32); +gdv_float64 sqrt_float64(gdv_float64); + gdv_float64 cbrt_int32(gdv_int32); gdv_float64 cbrt_int64(gdv_int64); gdv_float64 cbrt_float32(gdv_float32); @@ -152,6 +158,80 @@ gdv_float64 log10_int64(gdv_int64); gdv_float64 log10_float32(gdv_float32); gdv_float64 log10_float64(gdv_float64); +gdv_float32 sqrtf_int32(gdv_int32); +gdv_float32 sqrtf_int64(gdv_int64); +gdv_float32 sqrtf_float32(gdv_float32); + +gdv_float32 cbrtf_int32(gdv_int32); +gdv_float32 cbrtf_int64(gdv_int64); +gdv_float32 cbrtf_float32(gdv_float32); + +gdv_float32 expf_int32(gdv_int32); +gdv_float32 expf_int64(gdv_int64); +gdv_float32 expf_float32(gdv_float32); + +gdv_float32 logf_int32(gdv_int32); +gdv_float32 logf_int64(gdv_int64); +gdv_float32 logf_float32(gdv_float32); + +gdv_float32 log10f_int32(gdv_int32); +gdv_float32 log10f_int64(gdv_int64); +gdv_float32 log10f_float32(gdv_float32); + +gdv_float64 sin_int32(gdv_int32); +gdv_float64 sin_int64(gdv_int64); +gdv_float64 sin_float32(gdv_float32); +gdv_float64 sin_float64(gdv_float64); + +gdv_float64 cos_int32(gdv_int32); +gdv_float64 cos_int64(gdv_int64); +gdv_float64 cos_float32(gdv_float32); +gdv_float64 cos_float64(gdv_float64); + +gdv_float64 tan_int32(gdv_int32); +gdv_float64 tan_int64(gdv_int64); +gdv_float64 tan_float32(gdv_float32); +gdv_float64 tan_float64(gdv_float64); + +gdv_float64 asin_int32(gdv_int32); +gdv_float64 asin_int64(gdv_int64); +gdv_float64 asin_float32(gdv_float32); +gdv_float64 asin_float64(gdv_float64); + +gdv_float64 acos_int32(gdv_int32); +gdv_float64 acos_int64(gdv_int64); +gdv_float64 acos_float32(gdv_float32); +gdv_float64 acos_float64(gdv_float64); + +gdv_float64 atan_int32(gdv_int32); +gdv_float64 atan_int64(gdv_int64); +gdv_float64 atan_float32(gdv_float32); +gdv_float64 atan_float64(gdv_float64); + +gdv_float32 sinf_int32(gdv_int32); +gdv_float32 sinf_int64(gdv_int64); +gdv_float32 sinf_float32(gdv_float32); + +gdv_float32 cosf_int32(gdv_int32); +gdv_float32 cosf_int64(gdv_int64); +gdv_float32 cosf_float32(gdv_float32); + +gdv_float32 tanf_int32(gdv_int32); +gdv_float32 tanf_int64(gdv_int64); +gdv_float32 tanf_float32(gdv_float32); + +gdv_float32 asinf_int32(gdv_int32); +gdv_float32 asinf_int64(gdv_int64); +gdv_float32 asinf_float32(gdv_float32); + +gdv_float32 acosf_int32(gdv_int32); +gdv_float32 acosf_int64(gdv_int64); +gdv_float32 acosf_float32(gdv_float32); + +gdv_float32 atanf_int32(gdv_int32); +gdv_float32 atanf_int64(gdv_int64); +gdv_float32 atanf_float32(gdv_float32); + gdv_float64 power_float64_float64(gdv_float64, gdv_float64); gdv_float64 log_int32_int32(gdv_int64 context, gdv_int32 base, gdv_int32 value);