From 0111fa506aac40b0e10fbed115dad44847269f49 Mon Sep 17 00:00:00 2001 From: Matej Ferencevic <matej.ferencevic@memgraph.io> Date: Thu, 17 Jan 2019 13:46:01 +0100 Subject: [PATCH] Add logarithmic functions Reviewers: mtomic, teon.banek Reviewed By: mtomic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1811 --- src/utils/math.hpp | 26 ++++++++++++++++++++++++++ tests/unit/CMakeLists.txt | 3 +++ tests/unit/utils_math.cpp | 12 ++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 src/utils/math.hpp create mode 100644 tests/unit/utils_math.cpp diff --git a/src/utils/math.hpp b/src/utils/math.hpp new file mode 100644 index 000000000..c686fdaff --- /dev/null +++ b/src/utils/math.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include <cstdint> +#include <experimental/type_traits> + +#include <glog/logging.h> + +namespace utils { + +static_assert( + std::experimental::is_same_v<uint64_t, unsigned long>, + "utils::Log requires uint64_t to be implemented as unsigned long."); + +/// This function computes the log2 function on integer types. It is faster than +/// the cmath `log2` function because it doesn't use floating point values for +/// calculation. +inline uint64_t Log2(uint64_t val) { + // The `clz` function is undefined when the passed value is 0 and the value of + // `log` is `-inf` so we special case it here. + if (val == 0) return 0; + // clzl = count leading zeros from long + // ^ ^ ^ ^ + int ret = __builtin_clzl(val); + return 64UL - static_cast<uint64_t>(ret) - 1UL; +} +} // namespace utils diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 0c1654d64..c603b6f4d 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -323,6 +323,9 @@ target_link_libraries(${test_prefix}utils_exceptions mg-utils) add_unit_test(utils_executor.cpp) target_link_libraries(${test_prefix}utils_executor mg-utils) +add_unit_test(utils_math.cpp) +target_link_libraries(${test_prefix}utils_math mg-utils) + add_unit_test(utils_on_scope_exit.cpp) target_link_libraries(${test_prefix}utils_on_scope_exit mg-utils) diff --git a/tests/unit/utils_math.cpp b/tests/unit/utils_math.cpp new file mode 100644 index 000000000..7e74cf3ae --- /dev/null +++ b/tests/unit/utils_math.cpp @@ -0,0 +1,12 @@ +#include <cmath> + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include "utils/math.hpp" + +TEST(UtilsMath, Log2) { + for (uint64_t i = 1; i < 1000000; ++i) { + ASSERT_EQ(utils::Log2(i), static_cast<uint64_t>(log2(i))); + } +}