Skip to content

Commit

Permalink
Add from_ieee754_32 Presto scalar function
Browse files Browse the repository at this point in the history
  • Loading branch information
pdabre12 authored and Pratik Joseph Dabre committed Mar 28, 2024
1 parent 93b2544 commit 0d9494e
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 4 deletions.
13 changes: 9 additions & 4 deletions velox/docs/functions/presto/binary.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ Binary Functions

Decodes binary data from the hex encoded ``string``.

.. function:: from_ieee754_32(binary) -> real

Decodes the 32-bit big-endian ``binary`` in IEEE 754 single-precision floating-point format.
Throws a VeloxException if input size is shorter / longer than 32 bits.

.. function:: from_ieee754_64(binary) -> double

Decodes the 64-bit big-endian ``binary`` in IEEE 754 double-precision floating-point format.

.. function:: hmac_md5(binary, key) -> varbinary

Computes the HMAC with md5 of ``binary`` with the given ``key``.
Expand Down Expand Up @@ -98,10 +107,6 @@ Binary Functions

Encodes ``double`` in a 64-bit big-endian binary according to IEEE 754 double-precision floating-point format.

.. function:: from_ieee754_64(binary) -> double

Decodes the 64-bit big-endian ``binary`` in IEEE 754 double-precision floating-point format.

.. function:: xxhash64(binary) -> varbinary

Computes the xxhash64 hash of ``binary``.
17 changes: 17 additions & 0 deletions velox/functions/prestosql/BinaryFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -424,4 +424,21 @@ struct ToIEEE754Bits32 {
}
};

template <typename T>
struct FromIEEE754Bits32 {
VELOX_DEFINE_FUNCTION_TYPES(T);

FOLLY_ALWAYS_INLINE void call(
out_type<float>& result,
const arg_type<Varbinary>& input) {
static constexpr auto kTypeLength = sizeof(int32_t);
VELOX_USER_CHECK_EQ(
input.size(),
kTypeLength,
"Input floating-point value must be exactly 4 bytes long");
memcpy(&result, input.data(), kTypeLength);
result = folly::Endian::big(result);
}
};

} // namespace facebook::velox::functions
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ void registerSimpleFunctions(const std::string& prefix) {
{prefix + "from_ieee754_64"});
registerFunction<ToIEEE754Bits32, Varbinary, float>(
{prefix + "to_ieee754_32"});
registerFunction<FromIEEE754Bits32, float, Varbinary>(
{prefix + "from_ieee754_32"});
}
} // namespace

Expand Down
58 changes: 58 additions & 0 deletions velox/functions/prestosql/tests/BinaryFunctionsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <array>
#include <limits>
#include "velox/common/base/VeloxException.h"
#include "velox/common/base/tests/GTestUtils.h"
#include "velox/expression/Expr.h"
#include "velox/functions/prestosql/tests/utils/FunctionBaseTest.h"

Expand Down Expand Up @@ -697,4 +698,61 @@ TEST_F(BinaryFunctionsTest, toIEEE754Bits32) {
hexToDec("FF7FFFFF"),
toIEEE754Bits32(std::numeric_limits<float>::lowest()));
}

TEST_F(BinaryFunctionsTest, fromIEEE754Bits32) {
const auto fromIEEE754Bits32 = [&](const std::optional<std::string>& arg) {
return evaluateOnce<float, std::string>(
"from_ieee754_32(c0)", {arg}, {VARBINARY()});
};

const auto toIEEE754Bits32 = [&](std::optional<float> arg) {
return evaluateOnce<std::string, float>("to_ieee754_32(c0)", arg);
};

EXPECT_EQ(std::nullopt, fromIEEE754Bits32(std::nullopt));
EXPECT_EQ(1.0f, fromIEEE754Bits32(hexToDec("3F800000")));
EXPECT_EQ(3.14f, fromIEEE754Bits32(hexToDec("4048F5C3")));
EXPECT_EQ(3.4028235E38f, fromIEEE754Bits32(hexToDec("7f7fffff")));
EXPECT_EQ(-3.4028235E38f, fromIEEE754Bits32(hexToDec("ff7fffff")));
EXPECT_EQ(1.4E-45f, fromIEEE754Bits32(hexToDec("00000001")));
EXPECT_EQ(-1.4E-45f, fromIEEE754Bits32(hexToDec("80000001")));
EXPECT_EQ(
std::numeric_limits<float>::infinity(),
fromIEEE754Bits32(hexToDec("7f800000")));
EXPECT_EQ(
-std::numeric_limits<float>::infinity(),
fromIEEE754Bits32(hexToDec("ff800000")));
EXPECT_THROW(fromIEEE754Bits32("YQ"), VeloxUserError);
EXPECT_EQ(3.4028235E38f, fromIEEE754Bits32(toIEEE754Bits32(3.4028235E38f)));
EXPECT_EQ(-3.4028235E38f, fromIEEE754Bits32(toIEEE754Bits32(-3.4028235E38f)));
EXPECT_EQ(1.4E-45f, fromIEEE754Bits32(toIEEE754Bits32(1.4E-45f)));
EXPECT_EQ(-1.4E-45f, fromIEEE754Bits32(toIEEE754Bits32(-1.4E-45f)));
EXPECT_EQ(
std::numeric_limits<float>::infinity(),
fromIEEE754Bits32(
toIEEE754Bits32(std::numeric_limits<float>::infinity())));
EXPECT_EQ(
-std::numeric_limits<float>::infinity(),
fromIEEE754Bits32(
toIEEE754Bits32(-std::numeric_limits<float>::infinity())));
EXPECT_EQ(
std::numeric_limits<float>::max(),
fromIEEE754Bits32(toIEEE754Bits32(std::numeric_limits<float>::max())));
EXPECT_EQ(
std::numeric_limits<float>::min(),
fromIEEE754Bits32(toIEEE754Bits32(std::numeric_limits<float>::min())));
EXPECT_TRUE(
std::isnan(fromIEEE754Bits32(
toIEEE754Bits32(std::numeric_limits<float>::quiet_NaN()))
.value()));
EXPECT_TRUE(std::isnan(
fromIEEE754Bits32(
toIEEE754Bits32(std::numeric_limits<float>::signaling_NaN()))
.value()));
EXPECT_TRUE(
std::isnan(fromIEEE754Bits32(toIEEE754Bits32(std::nan("nan"))).value()));
VELOX_ASSERT_THROW(
fromIEEE754Bits32(hexToDec("0000000000000001")),
"Input floating-point value must be exactly 4 bytes long");
}
} // namespace

0 comments on commit 0d9494e

Please sign in to comment.