| /* |
| * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| * |
| */ |
| |
| #ifndef SHARE_UTILITIES_POWEROFTWO_HPP |
| #define SHARE_UTILITIES_POWEROFTWO_HPP |
| |
| #include "metaprogramming/enableIf.hpp" |
| #include "utilities/count_leading_zeros.hpp" |
| #include "utilities/count_trailing_zeros.hpp" |
| #include "utilities/debug.hpp" |
| #include "utilities/globalDefinitions.hpp" |
| #include <limits> |
| #include <type_traits> |
| |
| // Power of two convenience library. |
| |
| template <typename T, ENABLE_IF(std::is_integral<T>::value)> |
| constexpr T max_power_of_2() { |
| T max_val = std::numeric_limits<T>::max(); |
| return max_val - (max_val >> 1); |
| } |
| |
| // Returns true iff there exists integer i such that (T(1) << i) == value. |
| template <typename T, ENABLE_IF(std::is_integral<T>::value)> |
| constexpr bool is_power_of_2(T value) { |
| return (value > T(0)) && ((value & (value - 1)) == T(0)); |
| } |
| |
| // Log2 of a positive, integral value, i.e., largest i such that 2^i <= value |
| // Precondition: value > 0 |
| template<typename T, ENABLE_IF(std::is_integral<T>::value)> |
| inline int log2i(T value) { |
| assert(value > T(0), "value must be > 0"); |
| const int bits = sizeof(value) * BitsPerByte; |
| return bits - count_leading_zeros(value) - 1; |
| } |
| |
| // Log2 of positive, integral value, i.e., largest i such that 2^i <= value |
| // Returns -1 if value is zero |
| // For negative values this will return 63 for 64-bit types, 31 for |
| // 32-bit types, and so on. |
| template<typename T, ENABLE_IF(std::is_integral<T>::value)> |
| inline int log2i_graceful(T value) { |
| if (value == 0) { |
| return -1; |
| } |
| const int bits = sizeof(value) * BitsPerByte; |
| return bits - count_leading_zeros(value) - 1; |
| } |
| |
| // Log2 of a power of 2, i.e., i such that 2^i == value |
| // Preconditions: value > 0, value is a power of two |
| template<typename T, ENABLE_IF(std::is_integral<T>::value)> |
| inline int log2i_exact(T value) { |
| assert(is_power_of_2(value), |
| "value must be a power of 2: " UINT64_FORMAT_X, |
| static_cast<uint64_t>(value)); |
| return count_trailing_zeros(value); |
| } |
| |
| // Preconditions: value != 0, and the unsigned representation of value is a power of two |
| inline int exact_log2(intptr_t value) { |
| return log2i_exact((uintptr_t)value); |
| } |
| |
| // Preconditions: value != 0, and the unsigned representation of value is a power of two |
| inline int exact_log2_long(jlong value) { |
| return log2i_exact((julong)value); |
| } |
| |
| // Round down to the closest power of two less than or equal to the given value. |
| // precondition: value > 0. |
| template<typename T, ENABLE_IF(std::is_integral<T>::value)> |
| inline T round_down_power_of_2(T value) { |
| assert(value > 0, "Invalid value"); |
| return T(1) << log2i(value); |
| } |
| |
| // Round up to the closest power of two greater to or equal to the given value. |
| // precondition: value > 0. |
| // precondition: value <= maximum power of two representable by T. |
| template<typename T, ENABLE_IF(std::is_integral<T>::value)> |
| inline T round_up_power_of_2(T value) { |
| assert(value > 0, "Invalid value"); |
| assert(value <= max_power_of_2<T>(), "Overflowing maximum allowed power of two with " UINT64_FORMAT_X, |
| static_cast<uint64_t>(value)); |
| if (is_power_of_2(value)) { |
| return value; |
| } |
| return T(1) << (log2i(value) + 1); |
| } |
| |
| // Calculate the next power of two greater than the given value. |
| // precondition: if signed, value >= 0. |
| // precondition: value < maximum power of two representable by T. |
| template <typename T, ENABLE_IF(std::is_integral<T>::value)> |
| inline T next_power_of_2(T value) { |
| assert(value < std::numeric_limits<T>::max(), "Overflow"); |
| return round_up_power_of_2(value + 1); |
| } |
| |
| // Find log2 value greater than this input |
| template <typename T, ENABLE_IF(std::is_integral<T>::value)> |
| inline T ceil_log2(T value) { |
| T ret; |
| for (ret = 1; ((T)1 << ret) < value; ++ret); |
| return ret; |
| } |
| |
| // Return the largest power of two that is a submultiple of the given value. |
| // This is the same as the numeric value of the least-significant set bit. |
| // For unsigned values, it replaces the old trick of (value & -value). |
| // precondition: value > 0. |
| template<typename T, ENABLE_IF(std::is_integral<T>::value)> |
| inline T submultiple_power_of_2(T value) { |
| assert(value > 0, "Invalid value"); |
| return value & -value; |
| } |
| |
| #endif // SHARE_UTILITIES_POWEROFTWO_HPP |