This is an automated email from the ASF dual-hosted git repository. morningman pushed a commit to branch dev-1.0.0 in repository https://gitbox.apache.org/repos/asf/incubator-doris.git
commit d3b9bb20ff63b2bcb5a12501374ad363284408ce Author: HappenLee <happen...@hotmail.com> AuthorDate: Thu Feb 24 11:06:58 2022 +0800 [Function] Refactor the function code of log (#8199) 1. Support return null when input is invalid 2. Del the unless code in vec function Co-authored-by: lihaopeng <lihaop...@baidu.com> --- be/src/exprs/math_functions.cpp | 12 +- be/src/vec/functions/function_binary_arithmetic.h | 7 + .../vec/functions/function_math_binary_float64.h | 248 --------------------- be/src/vec/functions/function_math_unary.h | 1 + ..._unary.h => function_math_unary_to_null_type.h} | 87 ++------ be/src/vec/functions/math.cpp | 131 ++++++----- be/src/vec/functions/modulo.cpp | 2 +- be/src/vec/io/io_helper.h | 1 + be/test/vec/function/function_math_test.cpp | 11 +- be/test/vec/function/function_test_util.h | 1 - gensrc/script/doris_builtins_functions.py | 8 +- 11 files changed, 127 insertions(+), 382 deletions(-) diff --git a/be/src/exprs/math_functions.cpp b/be/src/exprs/math_functions.cpp index 708fc42..13fe610 100644 --- a/be/src/exprs/math_functions.cpp +++ b/be/src/exprs/math_functions.cpp @@ -161,6 +161,12 @@ SmallIntVal MathFunctions::abs(FunctionContext* ctx, const doris_udf::TinyIntVal return SmallIntVal(std::abs(int16_t(val.val))); } +#define LOG_MATH_FN(NAME, RET_TYPE, INPUT_TYPE, FN) \ + RET_TYPE MathFunctions::NAME(FunctionContext* ctx, const INPUT_TYPE& v) { \ + if (v.is_null || v.val <= 0) return RET_TYPE::null(); \ + return RET_TYPE(FN(v.val)); \ + } + // Generates a UDF that always calls FN() on the input val and returns it. #define ONE_ARG_MATH_FN(NAME, RET_TYPE, INPUT_TYPE, FN) \ RET_TYPE MathFunctions::NAME(FunctionContext* ctx, const INPUT_TYPE& v) { \ @@ -179,9 +185,9 @@ ONE_ARG_MATH_FN(atan, DoubleVal, DoubleVal, std::atan); ONE_ARG_MATH_FN(sqrt, DoubleVal, DoubleVal, std::sqrt); ONE_ARG_MATH_FN(ceil, BigIntVal, DoubleVal, std::ceil); ONE_ARG_MATH_FN(floor, BigIntVal, DoubleVal, std::floor); -ONE_ARG_MATH_FN(ln, DoubleVal, DoubleVal, std::log); -ONE_ARG_MATH_FN(log10, DoubleVal, DoubleVal, std::log10); ONE_ARG_MATH_FN(exp, DoubleVal, DoubleVal, std::exp); +LOG_MATH_FN(ln, DoubleVal, DoubleVal, std::log); +LOG_MATH_FN(log10, DoubleVal, DoubleVal, std::log10); TinyIntVal MathFunctions::sign(FunctionContext* ctx, const DoubleVal& v) { if (v.is_null) { @@ -227,7 +233,7 @@ DoubleVal MathFunctions::truncate(FunctionContext* ctx, const DoubleVal& v, cons } DoubleVal MathFunctions::log2(FunctionContext* ctx, const DoubleVal& v) { - if (v.is_null) { + if (v.is_null || v.val <= 0.0) { return DoubleVal::null(); } return DoubleVal(std::log(v.val) / std::log(2.0)); diff --git a/be/src/vec/functions/function_binary_arithmetic.h b/be/src/vec/functions/function_binary_arithmetic.h index f987f90..da1cabb 100644 --- a/be/src/vec/functions/function_binary_arithmetic.h +++ b/be/src/vec/functions/function_binary_arithmetic.h @@ -461,6 +461,8 @@ template <template <typename, typename> class Op, typename Name, bool CanBeExecutedOnDefaultArguments = true> class FunctionBinaryArithmetic : public IFunction { bool check_decimal_overflow = true; + static constexpr bool has_variadic_argument = + !std::is_void_v<decltype(has_variadic_argument_types(std::declval<Op<int,int>>()))>; template <typename F> static bool cast_type(const IDataType* type, F&& f) { @@ -508,6 +510,11 @@ public: size_t get_number_of_arguments() const override { return 2; } + DataTypes get_variadic_argument_types_impl() const override { + if constexpr (has_variadic_argument) return Op<int, int>::get_variadic_argument_types(); + return {}; + } + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { DataTypePtr type_res; bool valid = cast_both_types( diff --git a/be/src/vec/functions/function_math_binary_float64.h b/be/src/vec/functions/function_math_binary_float64.h deleted file mode 100644 index 8f41931..0000000 --- a/be/src/vec/functions/function_math_binary_float64.h +++ /dev/null @@ -1,248 +0,0 @@ -// 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. -// This file is copied from -// https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/FunctionMathBinaryFloat64.h -// and modified by Doris - -#pragma once - -#include "vec/columns/column_const.h" -#include "vec/columns/column_decimal.h" -#include "vec/columns/columns_number.h" -#include "vec/core/call_on_type_index.h" -#include "vec/data_types/data_type_decimal.h" -#include "vec/data_types/data_type_number.h" -#include "vec/functions/function.h" -#include "vec/functions/function_helpers.h" - -namespace doris::vectorized { - -template <typename Impl> -class FunctionMathBinaryFloat64 : public IFunction { -public: - static constexpr auto name = Impl::name; - static constexpr bool has_variadic_argument = - !std::is_void_v<decltype(has_variadic_argument_types(std::declval<Impl>()))>; - static FunctionPtr create() { return std::make_shared<FunctionMathBinaryFloat64>(); } - static_assert(Impl::rows_per_iteration > 0, "Impl must process at least one row per iteration"); - - bool use_default_implementation_for_constants() const override { return true; } - -private: - String get_name() const override { return name; } - - size_t get_number_of_arguments() const override { return 2; } - - DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { - const auto check_argument_type = [this](const IDataType* arg) -> bool { - if (!is_native_number(arg)) { - LOG(ERROR) << "Illegal type " << arg->get_name() << " of argument of function " - << get_name(); - return false; - } - return true; - }; - - if (check_argument_type(arguments.front().get()) && - check_argument_type(arguments.back().get())) { - return std::make_shared<DataTypeFloat64>(); - } else { - return nullptr; - } - } - - DataTypes get_variadic_argument_types_impl() const override { - if constexpr (has_variadic_argument) return Impl::get_variadic_argument_types(); - return {}; - } - - template <typename LeftType, typename RightType> - bool execute_typed(Block& block, const size_t result, const ColumnConst* left_arg, - const IColumn* right_arg) { - if (const auto right_arg_typed = check_and_get_column<ColumnVector<RightType>>(right_arg)) { - auto dst = ColumnVector<Float64>::create(); - - LeftType left_src_data[Impl::rows_per_iteration]; - std::fill(std::begin(left_src_data), std::end(left_src_data), - left_arg->template get_value<LeftType>()); - const auto& right_src_data = right_arg_typed->get_data(); - const auto src_size = right_src_data.size(); - auto& dst_data = dst->get_data(); - dst_data.resize(src_size); - - const auto rows_remaining = src_size % Impl::rows_per_iteration; - const auto rows_size = src_size - rows_remaining; - - for (size_t i = 0; i < rows_size; i += Impl::rows_per_iteration) - Impl::execute(left_src_data, &right_src_data[i], &dst_data[i]); - - if (rows_remaining != 0) { - RightType right_src_remaining[Impl::rows_per_iteration]; - memcpy(right_src_remaining, &right_src_data[rows_size], - rows_remaining * sizeof(RightType)); - memset(right_src_remaining + rows_remaining, 0, - (Impl::rows_per_iteration - rows_remaining) * sizeof(RightType)); - Float64 dst_remaining[Impl::rows_per_iteration]; - - Impl::execute(left_src_data, right_src_remaining, dst_remaining); - - memcpy(&dst_data[rows_size], dst_remaining, rows_remaining * sizeof(Float64)); - } - - block.replace_by_position(result, std::move(dst)); - return true; - } - - return false; - } - - template <typename LeftType, typename RightType> - bool execute_typed(Block& block, const size_t result, const ColumnVector<LeftType>* left_arg, - const IColumn* right_arg) { - if (const auto right_arg_typed = check_and_get_column<ColumnVector<RightType>>(right_arg)) { - auto dst = ColumnVector<Float64>::create(); - - const auto& left_src_data = left_arg->get_data(); - const auto& right_src_data = right_arg_typed->get_data(); - const auto src_size = left_src_data.size(); - auto& dst_data = dst->get_data(); - dst_data.resize(src_size); - - const auto rows_remaining = src_size % Impl::rows_per_iteration; - const auto rows_size = src_size - rows_remaining; - - for (size_t i = 0; i < rows_size; i += Impl::rows_per_iteration) - Impl::execute(&left_src_data[i], &right_src_data[i], &dst_data[i]); - - if (rows_remaining != 0) { - LeftType left_src_remaining[Impl::rows_per_iteration]; - memcpy(left_src_remaining, &left_src_data[rows_size], - rows_remaining * sizeof(LeftType)); - memset(left_src_remaining + rows_remaining, 0, - (Impl::rows_per_iteration - rows_remaining) * sizeof(LeftType)); - RightType right_src_remaining[Impl::rows_per_iteration]; - memcpy(right_src_remaining, &right_src_data[rows_size], - rows_remaining * sizeof(RightType)); - memset(right_src_remaining + rows_remaining, 0, - (Impl::rows_per_iteration - rows_remaining) * sizeof(RightType)); - Float64 dst_remaining[Impl::rows_per_iteration]; - - Impl::execute(left_src_remaining, right_src_remaining, dst_remaining); - - memcpy(&dst_data[rows_size], dst_remaining, rows_remaining * sizeof(Float64)); - } - - block.replace_by_position(result, std::move(dst)); - return true; - } - if (const auto right_arg_typed = - check_and_get_column_const<ColumnVector<RightType>>(right_arg)) { - auto dst = ColumnVector<Float64>::create(); - - const auto& left_src_data = left_arg->get_data(); - RightType right_src_data[Impl::rows_per_iteration]; - std::fill(std::begin(right_src_data), std::end(right_src_data), - right_arg_typed->template get_value<RightType>()); - const auto src_size = left_src_data.size(); - auto& dst_data = dst->get_data(); - dst_data.resize(src_size); - - const auto rows_remaining = src_size % Impl::rows_per_iteration; - const auto rows_size = src_size - rows_remaining; - - for (size_t i = 0; i < rows_size; i += Impl::rows_per_iteration) - Impl::execute(&left_src_data[i], right_src_data, &dst_data[i]); - - if (rows_remaining != 0) { - LeftType left_src_remaining[Impl::rows_per_iteration]; - memcpy(left_src_remaining, &left_src_data[rows_size], - rows_remaining * sizeof(LeftType)); - memset(left_src_remaining + rows_remaining, 0, - (Impl::rows_per_iteration - rows_remaining) * sizeof(LeftType)); - Float64 dst_remaining[Impl::rows_per_iteration]; - - Impl::execute(left_src_remaining, right_src_data, dst_remaining); - - memcpy(&dst_data[rows_size], dst_remaining, rows_remaining * sizeof(Float64)); - } - - block.replace_by_position(result, std::move(dst)); - return true; - } - - return false; - } - - Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, - size_t result, size_t /*input_rows_count*/) override { - const ColumnWithTypeAndName& col_left = block.get_by_position(arguments[0]); - const ColumnWithTypeAndName& col_right = block.get_by_position(arguments[1]); - - auto call = [&](const auto& types) -> bool { - using Types = std::decay_t<decltype(types)>; - using LeftType = typename Types::LeftType; - using RightType = typename Types::RightType; - using ColVecLeft = ColumnVector<LeftType>; - - const IColumn* left_arg = col_left.column.get(); - const IColumn* right_arg = col_right.column.get(); - - if (const auto left_arg_typed = check_and_get_column<ColVecLeft>(left_arg)) { - if (execute_typed<LeftType, RightType>(block, result, left_arg_typed, right_arg)) { - return true; - } - DCHECK(false) << "Illegal column " << right_arg->get_name() - << " of second argument of function " << get_name(); - } - if (const auto left_arg_typed = check_and_get_column_const<ColVecLeft>(left_arg)) { - if (execute_typed<LeftType, RightType>(block, result, left_arg_typed, right_arg)) { - return true; - } - - DCHECK(false) << "Illegal column " << right_arg->get_name() - << " of second argument of function " << get_name(); - } - - return false; - }; - - TypeIndex left_index = col_left.type->get_type_id(); - TypeIndex right_index = col_right.type->get_type_id(); - - if (!call_on_basic_types<true, true, false, false>(left_index, right_index, call)) { - return Status::InvalidArgument("Illegal column " + col_left.column->get_name() + - " of argument of function " + get_name()); - } - return Status::OK(); - } -}; - -template <typename Name, Float64(Function)(Float64, Float64)> -struct BinaryFunctionPlain { - static constexpr auto name = Name::name; - static constexpr auto rows_per_iteration = 1; - - template <typename T1, typename T2> - static void execute(const T1* src_left, const T2* src_right, Float64* dst) { - dst[0] = static_cast<Float64>( - Function(static_cast<Float64>(src_left[0]), static_cast<Float64>(src_right[0]))); - } -}; - -#define BinaryFunctionVectorized BinaryFunctionPlain - -} // namespace doris::vectorized diff --git a/be/src/vec/functions/function_math_unary.h b/be/src/vec/functions/function_math_unary.h index f12936c..acd4deb 100644 --- a/be/src/vec/functions/function_math_unary.h +++ b/be/src/vec/functions/function_math_unary.h @@ -48,6 +48,7 @@ private: } return std::make_shared<typename Impl::Type>(); } + DataTypes get_variadic_argument_types_impl() const override { if constexpr (has_variadic_argument) return Impl::get_variadic_argument_types(); return {}; diff --git a/be/src/vec/functions/function_math_unary.h b/be/src/vec/functions/function_math_unary_to_null_type.h similarity index 57% copy from be/src/vec/functions/function_math_unary.h copy to be/src/vec/functions/function_math_unary_to_null_type.h index f12936c..846f6d9 100644 --- a/be/src/vec/functions/function_math_unary.h +++ b/be/src/vec/functions/function_math_unary_to_null_type.h @@ -1,3 +1,4 @@ + // 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 @@ -14,9 +15,6 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// This file is copied from -// https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/FunctionMathUnary.h -// and modified by Doris #pragma once @@ -30,12 +28,10 @@ namespace doris::vectorized { template <typename Impl> -class FunctionMathUnary : public IFunction { +class FunctionMathUnaryToNullType : public IFunction { public: static constexpr auto name = Impl::name; - static constexpr bool has_variadic_argument = - !std::is_void_v<decltype(has_variadic_argument_types(std::declval<Impl>()))>; - static FunctionPtr create() { return std::make_shared<FunctionMathUnary>(); } + static FunctionPtr create() { return std::make_shared<FunctionMathUnaryToNullType>(); } private: String get_name() const override { return name; } @@ -46,45 +42,13 @@ private: if (!is_number(arg)) { return nullptr; } - return std::make_shared<typename Impl::Type>(); - } - DataTypes get_variadic_argument_types_impl() const override { - if constexpr (has_variadic_argument) return Impl::get_variadic_argument_types(); - return {}; + return make_nullable(std::make_shared<typename Impl::Type>()); } - + template <typename T, typename ReturnType> - static void execute_in_iterations(const T* src_data, ReturnType* dst_data, size_t size) { - if constexpr (Impl::rows_per_iteration == 0) { - /// Process all data as a whole and use FastOps implementation - - /// If the argument is integer, convert to Float64 beforehand - if constexpr (!std::is_floating_point_v<T>) { - PODArray<Float64> tmp_vec(size); - for (size_t i = 0; i < size; ++i) tmp_vec[i] = src_data[i]; - - Impl::execute(tmp_vec.data(), size, dst_data); - } else { - Impl::execute(src_data, size, dst_data); - } - } else { - const size_t rows_remaining = size % Impl::rows_per_iteration; - const size_t rows_size = size - rows_remaining; - - for (size_t i = 0; i < rows_size; i += Impl::rows_per_iteration) - Impl::execute(&src_data[i], &dst_data[i]); - - if (rows_remaining != 0) { - T src_remaining[Impl::rows_per_iteration]; - memcpy(src_remaining, &src_data[rows_size], rows_remaining * sizeof(T)); - memset(src_remaining + rows_remaining, 0, - (Impl::rows_per_iteration - rows_remaining) * sizeof(T)); - ReturnType dst_remaining[Impl::rows_per_iteration]; - - Impl::execute(src_remaining, dst_remaining); - - memcpy(&dst_data[rows_size], dst_remaining, rows_remaining * sizeof(ReturnType)); - } + static void execute_in_iterations(const T* src_data, ReturnType* dst_data, NullMap& null_map, size_t size) { + for (size_t i = 0; i < size; i++) { + Impl::execute(&src_data[i], &dst_data[i], null_map[i]); } } @@ -97,9 +61,13 @@ private: auto& dst_data = dst->get_data(); dst_data.resize(size); - execute_in_iterations(src_data.data(), dst_data.data(), size); + auto null_column = ColumnVector<UInt8>::create(); + auto& null_map = null_column->get_data(); + null_map.resize(size); - block.replace_by_position(result, std::move(dst)); + execute_in_iterations(src_data.data(), dst_data.data(), null_map, size); + + block.replace_by_position(result, ColumnNullable::create(std::move(dst), std::move(null_column))); return true; } @@ -113,13 +81,17 @@ private: auto& dst_data = dst->get_data(); dst_data.resize(size); + auto null_column = ColumnVector<UInt8>::create(); + auto& null_map = null_column->get_data(); + null_map.resize(size); + for (size_t i = 0; i < size; ++i) dst_data[i] = convert_from_decimal<DataTypeDecimal<T>, DataTypeNumber<ReturnType>>( src_data[i], scale); - execute_in_iterations(dst_data.data(), dst_data.data(), size); + execute_in_iterations(dst_data.data(), dst_data.data(), null_map, size); - block.replace_by_position(result, std::move(dst)); + block.replace_by_position(result, ColumnNullable::create(std::move(dst), std::move(null_column))); return true; } @@ -132,13 +104,11 @@ private: auto call = [&](const auto& types) -> bool { using Types = std::decay_t<decltype(types)>; using Type = typename Types::RightType; - using ReturnType = std::conditional_t< - Impl::always_returns_float64, Float64, Int64>; using ColVecType = std::conditional_t<IsDecimalNumber<Type>, ColumnDecimal<Type>, ColumnVector<Type>>; const auto col_vec = check_and_get_column<ColVecType>(col.column.get()); - return execute<Type, ReturnType>(block, col_vec, result); + return execute<Type, typename Impl::RetType>(block, col_vec, result); }; if (!call_on_basic_type<void, true, true, true, false>(col.type->get_type_id(), call)) { @@ -149,19 +119,4 @@ private: } }; -template <typename Name, Float64(Function)(Float64), typename ReturnType = DataTypeFloat64> -struct UnaryFunctionPlain { - using Type = ReturnType; - static constexpr auto name = Name::name; - static constexpr auto rows_per_iteration = 1; - static constexpr bool always_returns_float64 = std::is_same_v<Type, DataTypeFloat64>; - - template <typename T, typename U> - static void execute(const T* src, U* dst) { - dst[0] = static_cast<Float64>(Function(static_cast<Float64>(src[0]))); - } -}; - -#define UnaryFunctionVectorized UnaryFunctionPlain - } // namespace doris::vectorized \ No newline at end of file diff --git a/be/src/vec/functions/math.cpp b/be/src/vec/functions/math.cpp index 540c2c1..a265168 100644 --- a/be/src/vec/functions/math.cpp +++ b/be/src/vec/functions/math.cpp @@ -15,11 +15,12 @@ // specific language governing permissions and limitations // under the License. -#include "vec/common/field_visitors.h" #include "vec/data_types/number_traits.h" #include "vec/functions/function_const.h" -#include "vec/functions/function_math_binary_float64.h" +#include "vec/functions/function_binary_arithmetic.h" +#include "vec/functions/function_binary_arithmetic_to_null_type.h" #include "vec/functions/function_math_unary.h" +#include "vec/functions/function_math_unary_to_null_type.h" #include "vec/functions/function_string.h" #include "vec/functions/function_totype.h" #include "vec/functions/function_unary_arithmetic.h" @@ -125,37 +126,41 @@ struct ExpName { }; using FunctionExp = FunctionMathUnary<UnaryFunctionVectorized<ExpName, std::exp>>; -struct LnName { - static constexpr auto name = "ln"; -}; -using FunctionLn = FunctionMathUnary<UnaryFunctionVectorized<LnName, std::log>>; - -struct Log2Name { - static constexpr auto name = "log2"; -}; -using FunctionLog2 = FunctionMathUnary<UnaryFunctionVectorized<Log2Name, std::log2>>; - -struct Log10Name { - static constexpr auto name = "log10"; -}; -using FunctionLog10 = FunctionMathUnary<UnaryFunctionVectorized<Log10Name, std::log10>>; +#define LOG_FUNCTION_IMPL(CLASS, NAME, FUNC) \ +struct CLASS##Impl { \ + using Type = DataTypeFloat64; \ + using RetType = Float64; \ + static constexpr auto name = #NAME; \ + template <typename T, typename U> \ + static void execute(const T* src, U* dst, UInt8& null_flag) { \ + null_flag = src[0] <= 0; \ + dst[0] = static_cast<U>(FUNC((double)src[0])); \ + } \ +}; \ +using Function##CLASS = FunctionMathUnaryToNullType<CLASS##Impl>; + +LOG_FUNCTION_IMPL(Log10, log10, std::log10); +LOG_FUNCTION_IMPL(Log2, log2, std::log2); +LOG_FUNCTION_IMPL(Ln, ln, std::log); struct LogName { static constexpr auto name = "log"; }; -template <typename Name> +template <typename A, typename B> struct LogImpl { - static constexpr auto name = LogName::name; - static constexpr auto rows_per_iteration = 1; - - template <typename T1, typename T2> - static void execute(const T1* src_left, const T2* src_right, Float64* dst) { - dst[0] = static_cast<Float64>(std::log(static_cast<Float64>(src_right[0])) / - std::log(static_cast<Float64>(src_left[0]))); + using ResultType = Float64; + static const constexpr bool allow_decimal = false; + + template <typename Result> + static inline Result apply(A a, B b, NullMap& null_map, size_t index) { + constexpr double EPSILON = 1e-9; + null_map[index] = a <= 0 || b <= 0 || std::fabs(a - 1.0) < EPSILON; + return static_cast<Float64>(std::log(static_cast<Float64>(b)) / + std::log(static_cast<Float64>(a))); } }; -using FunctionLog = FunctionMathBinaryFloat64<LogImpl<LogName>>; +using FunctionLog = FunctionBinaryArithmeticToNullType<LogImpl, LogName>; struct CeilName { static constexpr auto name = "ceil"; @@ -301,28 +306,6 @@ struct FloorName { }; using FunctionFloor = FunctionMathUnary<UnaryFunctionVectorized<FloorName, std::floor, DataTypeInt64>>; -struct PowName { - static constexpr auto name = "pow"; -}; -using FunctionPow = FunctionMathBinaryFloat64<BinaryFunctionVectorized<PowName, std::pow>>; - -struct TruncateName { - static constexpr auto name = "truncate"; -}; - -template <typename Name> -struct TruncateImpl { - static constexpr auto rows_per_iteration = 1; - static constexpr auto name = TruncateName::name; - - template <typename T1, typename T2> - static void execute(const T1* src_left, const T2* src_right, Float64* dst) { - dst[0] = static_cast<Float64>(my_double_round( - static_cast<Float64>(src_left[0]), static_cast<Int32>(src_right[0]), false, true)); - } -}; -using FunctionTruncate = FunctionMathBinaryFloat64<TruncateImpl<TruncateName>>; - template <typename A> struct RadiansImpl { using ResultType = A; @@ -412,26 +395,62 @@ struct RoundOneImpl { }; using FunctionRoundOne = FunctionMathUnary<RoundOneImpl<RoundName>>; +template <typename A, typename B> +struct PowImpl { + using ResultType = double; + static const constexpr bool allow_decimal = false; + + template <typename type> + static inline double apply(A a, B b) { + /// Next everywhere, static_cast - so that there is no wrong result in expressions of the form Int64 c = UInt32(a) * Int32(-1). + return std::pow((double)a, (double) b); + } +}; +struct PowName { + static constexpr auto name = "pow"; +}; +using FunctionPow = FunctionBinaryArithmetic<PowImpl, PowName>; + +template <typename A, typename B> +struct TruncateImpl { + using ResultType = double; + static const constexpr bool allow_decimal = false; + + template <typename type> + static inline double apply(A a, B b) { + /// Next everywhere, static_cast - so that there is no wrong result in expressions of the form Int64 c = UInt32(a) * Int32(-1). + return static_cast<Float64>(my_double_round( + static_cast<Float64>(a), static_cast<Int32>(b), false, true)); + } +}; +struct TruncateName { + static constexpr auto name = "truncate"; +}; +using FunctionTruncate = FunctionBinaryArithmetic<TruncateImpl, TruncateName>; + /// round(double,int32)-->double /// key_str:roundFloat64Int32 -template <typename Name> +template <typename A, typename B> struct RoundTwoImpl { - static constexpr auto name = RoundName::name; - static constexpr auto rows_per_iteration = 1; - + using ResultType = double; + static const constexpr bool allow_decimal = false; + static DataTypes get_variadic_argument_types() { return {std::make_shared<vectorized::DataTypeFloat64>(), std::make_shared<vectorized::DataTypeInt32>()}; } - template <typename T1, typename T2> - static void execute(const T1* src_left, const T2* src_right, Float64* dst) { - dst[0] = my_double_round(static_cast<Float64>(src_left[0]), - static_cast<Int32>(src_right[0]), false, false); + template <typename type> + static inline double apply(A a, B b) { + /// Next everywhere, static_cast - so that there is no wrong result in expressions of the form Int64 c = UInt32(a) * Int32(-1). + return static_cast<Float64>(my_double_round( + static_cast<Float64>(a), static_cast<Int32>(b), false, false)); } }; -using FunctionRoundTwo = FunctionMathBinaryFloat64<RoundTwoImpl<RoundName>>; +using FunctionRoundTwo = FunctionBinaryArithmetic<RoundTwoImpl, RoundName>; +// TODO: Now math may cause one thread compile time too long, because the function in math +// so mush. Split it to speed up compile time in the future void register_function_math(SimpleFunctionFactory& factory) { factory.register_function<FunctionAcos>(); factory.register_function<FunctionAsin>(); diff --git a/be/src/vec/functions/modulo.cpp b/be/src/vec/functions/modulo.cpp index 3bd15c3..0e8bf49 100644 --- a/be/src/vec/functions/modulo.cpp +++ b/be/src/vec/functions/modulo.cpp @@ -38,7 +38,7 @@ struct ModuloImpl { template <typename Result = ResultType> static inline Result apply(A a, B b, NullMap& null_map, size_t index) { if constexpr (std::is_floating_point_v<Result>) { - null_map[index] = 0; + null_map[index] = b == 0; return std::fmod((double)a, (double)b); } else { null_map[index] = b == 0; diff --git a/be/src/vec/io/io_helper.h b/be/src/vec/io/io_helper.h index bc09fe8..99253c9 100644 --- a/be/src/vec/io/io_helper.h +++ b/be/src/vec/io/io_helper.h @@ -258,6 +258,7 @@ bool read_datetime_text_impl(T& x, ReadBuffer& buf) { static_assert(std::is_same_v<Int64, T>); auto dv = binary_cast<Int64, VecDateTimeValue>(x); auto ans = dv.from_date_str(buf.position(), buf.count()); + dv.to_datetime(); // only to match the is_all_read() check to prevent return null buf.position() = buf.end(); diff --git a/be/test/vec/function/function_math_test.cpp b/be/test/vec/function/function_math_test.cpp index a6b92c7..448cf84 100644 --- a/be/test/vec/function/function_math_test.cpp +++ b/be/test/vec/function/function_math_test.cpp @@ -144,9 +144,10 @@ TEST(MathFunctionTest, ln_test) { DataSet data_set = {{{1.0}, 0.0}, {{0.5}, -0.69314718055994529}, + {{-2.0}, Null()}, {{100.0}, 4.6051701859880918}, {{1000.0}, 6.9077552789821368}}; - + check_function<DataTypeFloat64, true>(func_name, input_types, data_set); } @@ -158,7 +159,8 @@ TEST(MathFunctionTest, log2_test) { DataSet data_set = {{{1.0}, 0.0}, {{0.5}, -1.0}, {{100.0}, 6.6438561897747244}, - {{1000.0}, 9.965784284662087}}; + {{1000.0}, 9.965784284662087}, + {{-1.0}, Null()}}; check_function<DataTypeFloat64, true>(func_name, input_types, data_set); } @@ -169,7 +171,8 @@ TEST(MathFunctionTest, log10_test) { InputTypeSet input_types = {TypeIndex::Float64}; DataSet data_set = { - {{1.0}, 0.0}, {{0.5}, -0.3010299956639812}, {{100.0}, 2.0}, {{1000.0}, 3.0}}; + {{1.0}, 0.0}, {{0.5}, -0.3010299956639812}, + {{100.0}, 2.0}, {{-1.0}, Null()}, {{1000.0}, 3.0}}; check_function<DataTypeFloat64, true>(func_name, input_types, data_set); } @@ -182,6 +185,8 @@ TEST(MathFunctionTest, log_test) { DataSet data_set = {{{10.0, 1.0}, 0.0}, {{10.0, 100.0}, 2.0}, {{0.1, 5.0}, -0.69897000433601886}, + {{-2.0, 5.0}, Null()}, + {{2.0, -5.0}, Null()}, {{2.0, 0.5}, -1.0}}; check_function<DataTypeFloat64, true>(func_name, input_types, data_set); diff --git a/be/test/vec/function/function_test_util.h b/be/test/vec/function/function_test_util.h index c1dc3d1..247c309 100644 --- a/be/test/vec/function/function_test_util.h +++ b/be/test/vec/function/function_test_util.h @@ -86,7 +86,6 @@ void insert_column_to_block(std::list<ColumnPtr>& columns, ColumnsWithTypeAndNam // Null values are represented by Null() // The type of the constant column is represented as follows: Consted {TypeIndex::String} // A DataSet with a constant column can only have one row of data - template <typename ReturnType, bool nullable = false> void check_function(const std::string& func_name, const std::vector<std::any>& input_types, const DataSet& data_set) { diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py index 8e3cec7..4d1f5d3 100755 --- a/gensrc/script/doris_builtins_functions.py +++ b/gensrc/script/doris_builtins_functions.py @@ -579,13 +579,13 @@ visible_functions = [ '15FunctionContextERKNS1_9DoubleValERKNS1_6IntValE', '', '', 'vec', ''], [['ln', 'dlog1'], 'DOUBLE', ['DOUBLE'], - '_ZN5doris13MathFunctions2lnEPN9doris_udf15FunctionContextERKNS1_9DoubleValE', '', '', 'vec', ''], + '_ZN5doris13MathFunctions2lnEPN9doris_udf15FunctionContextERKNS1_9DoubleValE', '', '', 'vec', 'ALWAYS_NULLABLE'], [['log'], 'DOUBLE', ['DOUBLE', 'DOUBLE'], - '_ZN5doris13MathFunctions3logEPN9doris_udf15FunctionContextERKNS1_9DoubleValES6_', '', '', 'vec', ''], + '_ZN5doris13MathFunctions3logEPN9doris_udf15FunctionContextERKNS1_9DoubleValES6_', '', '', 'vec', 'ALWAYS_NULLABLE'], [['log2'], 'DOUBLE', ['DOUBLE'], - '_ZN5doris13MathFunctions4log2EPN9doris_udf15FunctionContextERKNS1_9DoubleValE', '', '', 'vec', ''], + '_ZN5doris13MathFunctions4log2EPN9doris_udf15FunctionContextERKNS1_9DoubleValE', '', '', 'vec', 'ALWAYS_NULLABLE'], [['log10', 'dlog10'], 'DOUBLE', ['DOUBLE'], - '_ZN5doris13MathFunctions5log10EPN9doris_udf15FunctionContextERKNS1_9DoubleValE', '', '', 'vec', ''], + '_ZN5doris13MathFunctions5log10EPN9doris_udf15FunctionContextERKNS1_9DoubleValE', '', '', 'vec', 'ALWAYS_NULLABLE'], [['exp', 'dexp'], 'DOUBLE', ['DOUBLE'], '_ZN5doris13MathFunctions3expEPN9doris_udf15FunctionContextERKNS1_9DoubleValE', '', '', 'vec', ''], --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org