Skip to content

Commit

Permalink
Refactor greatest and least Presto functions using simple function API (
Browse files Browse the repository at this point in the history
facebookincubator#9308)

Summary:
Refactor the greatest/least functions using simple function API.

Also, add support for NaN comparisons for DOUBLE and REAL. NaN is the biggest according to prestodb/presto#22391

Fixes facebookincubator#3728

Pull Request resolved: facebookincubator#9308

Reviewed By: xiaoxmeng

Differential Revision: D55793910

Pulled By: mbasmanova

fbshipit-source-id: c389bad91197f00ced549d816a15efab5a2dd910
  • Loading branch information
Real-Chen-Happy authored and Joe-Abraham committed Jun 7, 2024
1 parent 34b2e8c commit 92394be
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 235 deletions.
1 change: 0 additions & 1 deletion velox/functions/prestosql/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ add_library(
FindFirst.cpp
FromUnixTime.cpp
FromUtf8.cpp
GreatestLeast.cpp
InPredicate.cpp
JsonFunctions.cpp
Map.cpp
Expand Down
207 changes: 0 additions & 207 deletions velox/functions/prestosql/GreatestLeast.cpp

This file was deleted.

101 changes: 101 additions & 0 deletions velox/functions/prestosql/GreatestLeast.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed 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 <cmath>
#include "velox/functions/Macros.h"

namespace facebook::velox::functions {
namespace details {
/**
* This class implements two functions:
*
* greatest(value1, value2, ..., valueN) → [same as input]
* Returns the largest of the provided values.
*
* least(value1, value2, ..., valueN) → [same as input]
* Returns the smallest of the provided values.
*
* For DOUBLE and REAL type, NaN is considered as the biggest according to
* https://github.com/prestodb/presto/issues/22391
**/
template <typename TExec, typename T, bool isLeast>
struct ExtremeValueFunction {
VELOX_DEFINE_FUNCTION_TYPES(TExec);

FOLLY_ALWAYS_INLINE void call(
out_type<T>& result,
const arg_type<T>& firstElement,
const arg_type<Variadic<T>>& remainingElement) {
auto currentValue = firstElement;

for (auto element : remainingElement) {
auto candidateValue = element.value();

if constexpr (isLeast) {
if (smallerThan(candidateValue, currentValue)) {
currentValue = candidateValue;
}
} else {
if (greaterThan(candidateValue, currentValue)) {
currentValue = candidateValue;
}
}
}

result = currentValue;
}

private:
template <typename K>
bool greaterThan(const K& lhs, const K& rhs) const {
if constexpr (std::is_same_v<K, double> || std::is_same_v<K, float>) {
if (std::isnan(lhs)) {
return true;
}

if (std::isnan(rhs)) {
return false;
}
}

return lhs > rhs;
}

template <typename K>
bool smallerThan(const K& lhs, const K& rhs) const {
if constexpr (std::is_same_v<K, double> || std::is_same_v<K, float>) {
if (std::isnan(lhs)) {
return false;
}

if (std::isnan(rhs)) {
return true;
}
}

return lhs < rhs;
}
};
} // namespace details

template <typename TExec, typename T>
using LeastFunction = details::ExtremeValueFunction<TExec, T, true>;

template <typename TExec, typename T>
using GreatestFunction = details::ExtremeValueFunction<TExec, T, false>;

} // namespace facebook::velox::functions
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,35 @@
#include "velox/functions/Registerer.h"
#include "velox/functions/lib/IsNull.h"
#include "velox/functions/prestosql/Cardinality.h"
#include "velox/functions/prestosql/GreatestLeast.h"
#include "velox/functions/prestosql/InPredicate.h"

namespace facebook::velox::functions {

template <typename T>
inline void registerGreatestLeastFunction(const std::string& prefix) {
registerFunction<ParameterBinder<GreatestFunction, T>, T, T, Variadic<T>>(
{prefix + "greatest"});

registerFunction<ParameterBinder<LeastFunction, T>, T, T, Variadic<T>>(
{prefix + "least"});
}

inline void registerAllGreatestLeastFunctions(const std::string& prefix) {
registerGreatestLeastFunction<bool>(prefix);
registerGreatestLeastFunction<int8_t>(prefix);
registerGreatestLeastFunction<int16_t>(prefix);
registerGreatestLeastFunction<int32_t>(prefix);
registerGreatestLeastFunction<int64_t>(prefix);
registerGreatestLeastFunction<float>(prefix);
registerGreatestLeastFunction<double>(prefix);
registerGreatestLeastFunction<Varchar>(prefix);
registerGreatestLeastFunction<LongDecimal<P1, S1>>(prefix);
registerGreatestLeastFunction<ShortDecimal<P1, S1>>(prefix);
registerGreatestLeastFunction<Date>(prefix);
registerGreatestLeastFunction<Timestamp>(prefix);
}

extern void registerSubscriptFunction(
const std::string& name,
bool enableCaching);
Expand Down Expand Up @@ -47,12 +73,10 @@ void registerGeneralFunctions(const std::string& prefix) {
VELOX_REGISTER_VECTOR_FUNCTION(udf_transform, prefix + "transform");
VELOX_REGISTER_VECTOR_FUNCTION(udf_reduce, prefix + "reduce");
VELOX_REGISTER_VECTOR_FUNCTION(udf_array_filter, prefix + "filter");

VELOX_REGISTER_VECTOR_FUNCTION(udf_least, prefix + "least");
VELOX_REGISTER_VECTOR_FUNCTION(udf_greatest, prefix + "greatest");

VELOX_REGISTER_VECTOR_FUNCTION(udf_typeof, prefix + "typeof");

registerAllGreatestLeastFunctions(prefix);

registerFunction<CardinalityFunction, int64_t, Array<Any>>(
{prefix + "cardinality"});
registerFunction<CardinalityFunction, int64_t, Map<Any, Any>>(
Expand Down
Loading

0 comments on commit 92394be

Please sign in to comment.