blob: 3e9d8a5d2cd44a975c7bbdfba33d2f81956ec673 [file]
// 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.
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#include <gtest/gtest.h>
#include <cmath>
#include "gandiva/execution_context.h"
#include "gandiva/precompiled/types.h"
namespace gandiva {
static const double MAX_ERROR = 0.00005;
void VerifyFuzzyEquals(double actual, double expected, double max_error = MAX_ERROR) {
EXPECT_TRUE(fabs(actual - expected) < max_error) << actual << " != " << expected;
}
TEST(TestExtendedMathOps, TestCbrt) {
VerifyFuzzyEquals(cbrt_int32(27), 3);
VerifyFuzzyEquals(cbrt_int64(27), 3);
VerifyFuzzyEquals(cbrt_float32(27), 3);
VerifyFuzzyEquals(cbrt_float64(27), 3);
VerifyFuzzyEquals(cbrt_float64(-27), -3);
VerifyFuzzyEquals(cbrt_float32(15.625), 2.5);
VerifyFuzzyEquals(cbrt_float64(15.625), 2.5);
}
TEST(TestExtendedMathOps, TestFactorial) {
gandiva::ExecutionContext context;
auto ctx = reinterpret_cast<int64_t>(&context);
for (int32_t i = 0; i <= 20; ++i) {
int64_t expected_factorial = 1;
for (int64_t j = 1; j <= i; ++j) {
expected_factorial *= j;
}
EXPECT_EQ(factorial_int32(ctx, i), expected_factorial);
}
factorial_int32(ctx, 21);
EXPECT_TRUE(context.get_error().find("overflow") != std::string::npos);
context.Reset();
factorial_int32(ctx, -5);
EXPECT_TRUE(context.get_error().find("Factorial of negative") != std::string::npos);
context.Reset();
for (int64_t i = 0; i <= 20; ++i) {
int64_t expected_factorial = 1;
for (int64_t j = 1; j <= i; ++j) {
expected_factorial *= j;
}
EXPECT_EQ(factorial_int64(ctx, i), expected_factorial);
}
factorial_int64(ctx, 21);
EXPECT_TRUE(context.get_error().find("overflow") != std::string::npos);
context.Reset();
factorial_int64(ctx, -5);
EXPECT_TRUE(context.get_error().find("Factorial of negative") != std::string::npos);
context.Reset();
}
TEST(TestExtendedMathOps, TestExp) {
double val = 20.085536923187668;
VerifyFuzzyEquals(exp_int32(3), val);
VerifyFuzzyEquals(exp_int64(3), val);
VerifyFuzzyEquals(exp_float32(3), val);
VerifyFuzzyEquals(exp_float64(3), val);
}
TEST(TestExtendedMathOps, TestLog) {
double val = 4.1588830833596715;
VerifyFuzzyEquals(log_int32(64), val);
VerifyFuzzyEquals(log_int64(64), val);
VerifyFuzzyEquals(log_float32(64), val);
VerifyFuzzyEquals(log_float64(64), val);
EXPECT_EQ(log_int32(0), -std::numeric_limits<double>::infinity());
}
TEST(TestExtendedMathOps, TestLog10) {
VerifyFuzzyEquals(log10_int32(100), 2);
VerifyFuzzyEquals(log10_int64(100), 2);
VerifyFuzzyEquals(log10_float32(100), 2);
VerifyFuzzyEquals(log10_float64(100), 2);
}
TEST(TestExtendedMathOps, TestPower) {
VerifyFuzzyEquals(power_float64_float64(2, 5.4), 42.22425314473263);
VerifyFuzzyEquals(power_float64_float64(5.4, 2), 29.160000000000004);
}
TEST(TestExtendedMathOps, TestLogWithBase) {
gandiva::ExecutionContext context;
gdv_float64 out =
log_int32_int32(reinterpret_cast<gdv_int64>(&context), 1 /*base*/, 10 /*value*/);
VerifyFuzzyEquals(out, 0);
EXPECT_EQ(context.has_error(), true);
EXPECT_TRUE(context.get_error().find("divide by zero error") != std::string::npos)
<< context.get_error();
gandiva::ExecutionContext context1;
out = log_int32_int32(reinterpret_cast<gdv_int64>(&context), 2 /*base*/, 64 /*value*/);
VerifyFuzzyEquals(out, 6);
EXPECT_EQ(context1.has_error(), false);
}
TEST(TestExtendedMathOps, TestRoundDecimal) {
EXPECT_FLOAT_EQ(round_float32(1234.245f), 1234);
EXPECT_FLOAT_EQ(round_float32(-11.7892f), -12);
EXPECT_FLOAT_EQ(round_float32(1.4999999f), 1);
EXPECT_EQ(std::signbit(round_float32(0)), 0);
EXPECT_FLOAT_EQ(round_float32_int32(1234.789f, 2), 1234.79f);
EXPECT_FLOAT_EQ(round_float32_int32(1234.12345f, -3), 1000);
EXPECT_FLOAT_EQ(round_float32_int32(-1234.4567f, 3), -1234.457f);
EXPECT_FLOAT_EQ(round_float32_int32(-1234.4567f, -3), -1000);
EXPECT_FLOAT_EQ(round_float32_int32(1234.4567f, 0), 1234);
EXPECT_FLOAT_EQ(round_float32_int32(1.5499999523162842f, 1), 1.5f);
EXPECT_EQ(std::signbit(round_float32_int32(0, 5)), 0);
EXPECT_FLOAT_EQ(round_float32_int32(static_cast<float>(1.55), 1), 1.5f);
EXPECT_FLOAT_EQ(round_float32_int32(static_cast<float>(9.134123), 2), 9.13f);
EXPECT_FLOAT_EQ(round_float32_int32(static_cast<float>(-1.923), 1), -1.9f);
VerifyFuzzyEquals(round_float64(1234.245), 1234);
VerifyFuzzyEquals(round_float64(-11.7892), -12);
VerifyFuzzyEquals(round_float64(1.4999999), 1);
EXPECT_EQ(std::signbit(round_float64(0)), 0);
VerifyFuzzyEquals(round_float64_int32(1234.789, 2), 1234.79);
VerifyFuzzyEquals(round_float64_int32(1234.12345, -3), 1000);
VerifyFuzzyEquals(round_float64_int32(-1234.4567, 3), -1234.457);
VerifyFuzzyEquals(round_float64_int32(-1234.4567, -3), -1000);
VerifyFuzzyEquals(round_float64_int32(1234.4567, 0), 1234);
EXPECT_EQ(std::signbit(round_float64_int32(0, -2)), 0);
VerifyFuzzyEquals(round_float64_int32((double)INT_MAX + 1, 0), (double)INT_MAX + 1);
VerifyFuzzyEquals(round_float64_int32((double)INT_MIN - 1, 0), (double)INT_MIN - 1);
}
TEST(TestExtendedMathOps, TestBRoundDecimal) {
EXPECT_DOUBLE_EQ(bround_float64(0.0), 0);
EXPECT_DOUBLE_EQ(bround_float64(2.5), 2);
EXPECT_DOUBLE_EQ(bround_float64(3.5), 4);
EXPECT_DOUBLE_EQ(bround_float64(-2.5), -2);
EXPECT_DOUBLE_EQ(bround_float64(-3.5), -4);
EXPECT_DOUBLE_EQ(bround_float64(1.4999999), 1);
EXPECT_DOUBLE_EQ(bround_float64(1.50001), 2);
EXPECT_EQ(std::signbit(bround_float64(0)), 0);
VerifyFuzzyEquals(bround_float64(2.5), 2);
VerifyFuzzyEquals(bround_float64(3.5), 4);
VerifyFuzzyEquals(bround_float64(-2.5), -2);
VerifyFuzzyEquals(bround_float64(-3.5), -4);
VerifyFuzzyEquals(bround_float64(1.4999999), 1);
VerifyFuzzyEquals(bround_float64(1.50001), 2);
}
TEST(TestExtendedMathOps, TestRound) {
EXPECT_EQ(round_int32(21134), 21134);
EXPECT_EQ(round_int32(-132422), -132422);
EXPECT_EQ(round_int32_int32(7589, -1), 7590);
EXPECT_EQ(round_int32_int32(8532, -2), 8500);
EXPECT_EQ(round_int32_int32(-8579, -1), -8580);
EXPECT_EQ(round_int32_int32(-8612, -2), -8600);
EXPECT_EQ(round_int32_int32(758, 2), 758);
EXPECT_EQ(round_int32_int32(8612, -5), 0);
EXPECT_EQ(round_int64(3453562312), 3453562312);
EXPECT_EQ(round_int64(-23453462343), -23453462343);
EXPECT_EQ(round_int64_int32(3453562312, -2), 3453562300);
EXPECT_EQ(round_int64_int32(3453562343, -5), 3453600000);
EXPECT_EQ(round_int64_int32(345353425343, 12), 345353425343);
EXPECT_EQ(round_int64_int32(-23453462343, -4), -23453460000);
EXPECT_EQ(round_int64_int32(-23453462343, -5), -23453500000);
EXPECT_EQ(round_int64_int32(345353425343, -12), 0);
}
TEST(TestExtendedMathOps, TestTruncate) {
EXPECT_EQ(truncate_int64_int32(1234, 4), 1234);
EXPECT_EQ(truncate_int64_int32(-1234, 4), -1234);
EXPECT_EQ(truncate_int64_int32(1234, -4), 0);
EXPECT_EQ(truncate_int64_int32(-1234, -2), -1200);
EXPECT_EQ(truncate_int64_int32(8124674407369523212, 0), 8124674407369523212);
EXPECT_EQ(truncate_int64_int32(8124674407369523212, -2), 8124674407369523200);
}
TEST(TestExtendedMathOps, TestTrigonometricFunctions) {
auto pi_float = static_cast<float>(M_PI);
// Sin functions
VerifyFuzzyEquals(sin_float32(0), sin(0));
VerifyFuzzyEquals(sin_float32(0), sin(0));
VerifyFuzzyEquals(sin_float32(pi_float / 2), sin(M_PI / 2));
VerifyFuzzyEquals(sin_float32(pi_float), sin(M_PI));
VerifyFuzzyEquals(sin_float32(-pi_float / 2), sin(-M_PI / 2));
VerifyFuzzyEquals(sin_float64(0), sin(0));
VerifyFuzzyEquals(sin_float64(M_PI / 2), sin(M_PI / 2));
VerifyFuzzyEquals(sin_float64(M_PI), sin(M_PI));
VerifyFuzzyEquals(sin_float64(-M_PI / 2), sin(-M_PI / 2));
VerifyFuzzyEquals(sin_int32(0), sin(0));
VerifyFuzzyEquals(sin_int64(0), sin(0));
// Cos functions
VerifyFuzzyEquals(cos_float32(0), cos(0));
VerifyFuzzyEquals(cos_float32(pi_float / 2), cos(M_PI / 2));
VerifyFuzzyEquals(cos_float32(pi_float), cos(M_PI));
VerifyFuzzyEquals(cos_float32(-pi_float / 2), cos(-M_PI / 2));
VerifyFuzzyEquals(cos_float64(0), cos(0));
VerifyFuzzyEquals(cos_float64(M_PI / 2), cos(M_PI / 2));
VerifyFuzzyEquals(cos_float64(M_PI), cos(M_PI));
VerifyFuzzyEquals(cos_float64(-M_PI / 2), cos(-M_PI / 2));
VerifyFuzzyEquals(cos_int32(0), cos(0));
VerifyFuzzyEquals(cos_int64(0), cos(0));
// Asin functions
VerifyFuzzyEquals(asin_float32(-1.0), asin(-1.0));
VerifyFuzzyEquals(asin_float32(1.0), asin(1.0));
VerifyFuzzyEquals(asin_float64(-1.0), asin(-1.0));
VerifyFuzzyEquals(asin_float64(1.0), asin(1.0));
VerifyFuzzyEquals(asin_int32(0), asin(0));
VerifyFuzzyEquals(asin_int64(0), asin(0));
// Acos functions
VerifyFuzzyEquals(acos_float32(-1.0), acos(-1.0));
VerifyFuzzyEquals(acos_float32(1.0), acos(1.0));
VerifyFuzzyEquals(acos_float64(-1.0), acos(-1.0));
VerifyFuzzyEquals(acos_float64(1.0), acos(1.0));
VerifyFuzzyEquals(acos_int32(0), acos(0));
VerifyFuzzyEquals(acos_int64(0), acos(0));
// Tan
VerifyFuzzyEquals(tan_float32(pi_float), tan(M_PI));
VerifyFuzzyEquals(tan_float32(-pi_float), tan(-M_PI));
VerifyFuzzyEquals(tan_float64(M_PI), tan(M_PI));
VerifyFuzzyEquals(tan_float64(-M_PI), tan(-M_PI));
VerifyFuzzyEquals(tan_int32(0), tan(0));
VerifyFuzzyEquals(tan_int64(0), tan(0));
// Atan
VerifyFuzzyEquals(atan_float32(pi_float), atan(M_PI));
VerifyFuzzyEquals(atan_float32(-pi_float), atan(-M_PI));
VerifyFuzzyEquals(atan_float64(M_PI), atan(M_PI));
VerifyFuzzyEquals(atan_float64(-M_PI), atan(-M_PI));
VerifyFuzzyEquals(atan_int32(0), atan(0));
VerifyFuzzyEquals(atan_int64(0), atan(0));
// Sinh functions
VerifyFuzzyEquals(sinh_float32(0), sinh(0));
VerifyFuzzyEquals(sinh_float32(pi_float / 2), sinh(M_PI / 2));
VerifyFuzzyEquals(sinh_float32(pi_float), sinh(M_PI));
VerifyFuzzyEquals(sinh_float32(-pi_float / 2), sinh(-M_PI / 2));
VerifyFuzzyEquals(sinh_float64(0), sinh(0));
VerifyFuzzyEquals(sinh_float64(M_PI / 2), sinh(M_PI / 2));
VerifyFuzzyEquals(sinh_float64(M_PI), sinh(M_PI));
VerifyFuzzyEquals(sinh_float64(-M_PI / 2), sinh(-M_PI / 2));
VerifyFuzzyEquals(sinh_int32(0), sinh(0));
VerifyFuzzyEquals(sinh_int64(0), sinh(0));
// Cosh functions
VerifyFuzzyEquals(cosh_float32(0), cosh(0));
VerifyFuzzyEquals(cosh_float32(pi_float / 2), cosh(M_PI / 2));
VerifyFuzzyEquals(cosh_float32(pi_float), cosh(M_PI));
VerifyFuzzyEquals(cosh_float32(-pi_float / 2), cosh(-M_PI / 2));
VerifyFuzzyEquals(cosh_float64(0), cosh(0));
VerifyFuzzyEquals(cosh_float64(M_PI / 2), cosh(M_PI / 2));
VerifyFuzzyEquals(cosh_float64(M_PI), cosh(M_PI));
VerifyFuzzyEquals(cosh_float64(-M_PI / 2), cosh(-M_PI / 2));
VerifyFuzzyEquals(cosh_int32(0), cosh(0));
VerifyFuzzyEquals(cosh_int64(0), cosh(0));
// Tanh
VerifyFuzzyEquals(tanh_float32(pi_float), tanh(M_PI));
VerifyFuzzyEquals(tanh_float32(-pi_float), tanh(-M_PI));
VerifyFuzzyEquals(tanh_float64(M_PI), tanh(M_PI));
VerifyFuzzyEquals(tanh_float64(-M_PI), tanh(-M_PI));
VerifyFuzzyEquals(tanh_int32(0), tanh(0));
VerifyFuzzyEquals(tanh_int64(0), tanh(0));
// Atan2
VerifyFuzzyEquals(atan2_float32_float32(1, 0), atan2(1, 0));
VerifyFuzzyEquals(atan2_float32_float32(-1.0, 0), atan2(-1, 0));
VerifyFuzzyEquals(atan2_float64_float64(1.0, 0.0), atan2(1, 0));
VerifyFuzzyEquals(atan2_float64_float64(-1, 0), atan2(-1, 0));
VerifyFuzzyEquals(atan2_int32_int32(1, 0), atan2(1, 0));
VerifyFuzzyEquals(atan2_int64_int64(-1, 0), atan2(-1, 0));
// Radians
VerifyFuzzyEquals(radians_float32(0), 0);
VerifyFuzzyEquals(radians_float32(180.0), M_PI);
VerifyFuzzyEquals(radians_float32(90.0), M_PI / 2);
VerifyFuzzyEquals(radians_float64(0), 0);
VerifyFuzzyEquals(radians_float64(180.0), M_PI);
VerifyFuzzyEquals(radians_float64(90.0), M_PI / 2);
VerifyFuzzyEquals(radians_int32(180), M_PI);
VerifyFuzzyEquals(radians_int64(90), M_PI / 2);
// Degrees
VerifyFuzzyEquals(degrees_float32(0), 0.0);
VerifyFuzzyEquals(degrees_float32(pi_float), 180.0);
VerifyFuzzyEquals(degrees_float32(pi_float / 2), 90.0);
VerifyFuzzyEquals(degrees_float64(0), 0.0);
VerifyFuzzyEquals(degrees_float64(M_PI), 180.0);
VerifyFuzzyEquals(degrees_float64(M_PI / 2), 90.0);
VerifyFuzzyEquals(degrees_int32(1), 57.2958);
VerifyFuzzyEquals(degrees_int64(1), 57.2958);
// Cot
VerifyFuzzyEquals(cot_float32(pi_float / 2), tan(M_PI / 2 - M_PI / 2));
VerifyFuzzyEquals(cot_float64(M_PI / 2), tan(M_PI / 2 - M_PI / 2));
}
TEST(TestExtendedMathOps, TestBinRepresentation) {
gandiva::ExecutionContext ctx;
uint64_t ctx_ptr = reinterpret_cast<gdv_int64>(&ctx);
gdv_int32 out_len = 0;
const char* out_str = bin_int32(ctx_ptr, 7, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "111");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int32(ctx_ptr, 0, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "0");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int32(ctx_ptr, 28550, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "110111110000110");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int32(ctx_ptr, -28550, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "11111111111111111001000001111010");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int32(ctx_ptr, 58117, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "1110001100000101");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int32(ctx_ptr, -58117, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "11111111111111110001110011111011");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int32(ctx_ptr, INT32_MAX, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "1111111111111111111111111111111");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int32(ctx_ptr, INT32_MIN, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "10000000000000000000000000000000");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int64(ctx_ptr, 7, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "111");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int64(ctx_ptr, 0, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "0");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int64(ctx_ptr, 28550, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "110111110000110");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int64(ctx_ptr, -28550, &out_len);
EXPECT_EQ(std::string(out_str, out_len),
"1111111111111111111111111111111111111111111111111001000001111010");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int64(ctx_ptr, 58117, &out_len);
EXPECT_EQ(std::string(out_str, out_len), "1110001100000101");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int64(ctx_ptr, -58117, &out_len);
EXPECT_EQ(std::string(out_str, out_len),
"1111111111111111111111111111111111111111111111110001110011111011");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int64(ctx_ptr, INT64_MAX, &out_len);
EXPECT_EQ(std::string(out_str, out_len),
"111111111111111111111111111111111111111111111111111111111111111");
EXPECT_FALSE(ctx.has_error());
out_str = bin_int64(ctx_ptr, INT64_MIN, &out_len);
EXPECT_EQ(std::string(out_str, out_len),
"1000000000000000000000000000000000000000000000000000000000000000");
EXPECT_FALSE(ctx.has_error());
}
} // namespace gandiva