/** * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * 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. */ #ifndef PANDA_INTERPRETER_MATH_HELPERS_H_ #define PANDA_INTERPRETER_MATH_HELPERS_H_ #include #include #include #include #include "libpandabase/macros.h" namespace panda::interpreter::math_helpers { template struct bit_shl : public std::binary_function { // NOLINT(readability-identifier-naming) constexpr T operator()(const T &x, const T &y) const { using unsigned_type = std::make_unsigned_t; size_t mask = std::numeric_limits::digits - 1; size_t shift = static_cast(y) & mask; return static_cast(static_cast(x) << shift); } }; template struct bit_shr : public std::binary_function { // NOLINT(readability-identifier-naming) constexpr T operator()(const T &x, const T &y) const { using unsigned_type = std::make_unsigned_t; size_t mask = std::numeric_limits::digits - 1; size_t shift = static_cast(y) & mask; return static_cast(static_cast(x) >> shift); } }; template struct bit_ashr : public std::binary_function { // NOLINT(readability-identifier-naming) constexpr T operator()(const T &x, const T &y) const { using unsigned_type = std::make_unsigned_t; size_t mask = std::numeric_limits::digits - 1; size_t shift = static_cast(y) & mask; return x >> shift; // NOLINT(hicpp-signed-bitwise) } }; template struct fmodulus : public std::binary_function { // NOLINT(readability-identifier-naming) constexpr T operator()(const T &x, const T &y) const { static_assert(std::is_floating_point_v, "T should be floating point type"); return std::fmod(x, y); } }; template struct cmp : public std::binary_function { // NOLINT(readability-identifier-naming) constexpr int32_t operator()(const T &x, const T &y) const { static_assert(std::is_integral_v, "T should be integral type"); if (x > y) { return 1; } if (x == y) { return 0; } return -1; } }; template struct fcmpl : public std::binary_function { // NOLINT(readability-identifier-naming) constexpr int32_t operator()(const T &x, const T &y) const { static_assert(std::is_floating_point_v, "T should be floating point type"); if (x > y) { return 1; } if (x == y) { return 0; } return -1; } }; template struct fcmpg : public std::binary_function { // NOLINT(readability-identifier-naming) constexpr int32_t operator()(const T &x, const T &y) const { static_assert(std::is_floating_point_v, "T should be floating point type"); if (x < y) { return -1; } if (x == y) { return 0; } return 1; } }; template struct idivides : public std::binary_function { // NOLINT(readability-identifier-naming) constexpr T operator()(const T &x, const T &y) const { static_assert(std::is_integral_v, "T should be integral type"); // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203 // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) if constexpr (std::is_signed_v) { constexpr T MIN = std::numeric_limits::min(); if (UNLIKELY(x == MIN && y == -1)) { return MIN; } } return x / y; } }; template struct imodulus : public std::binary_function { // NOLINT(readability-identifier-naming) constexpr T operator()(const T &x, const T &y) const { static_assert(std::is_integral_v, "T should be integral type"); // Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203 // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) if constexpr (std::is_signed_v) { constexpr T MIN = std::numeric_limits::min(); if (UNLIKELY(x == MIN && y == -1)) { return 0; } } return x % y; } }; template