/* * Copyright (c) 2018-2020 Arm Limited. * * SPDX-License-Identifier: MIT * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef ARM_COMPUTE_UTILS_CAST_SATURATE_CAST_H #define ARM_COMPUTE_UTILS_CAST_SATURATE_CAST_H #include "arm_compute/core/utils/misc/Traits.h" #include "arm_compute/core/utils/misc/Utility.h" #include "support/Rounding.h" namespace arm_compute { namespace utils { namespace cast { // *INDENT-OFF* // clang-format off // same type template::value, int >::type = 0 > T saturate_cast(U v) { return v; } // signed -> signed widening/same_width template::value && std::is_integral::value && std::is_signed() && std::is_signed() && !std::is_same::value && sizeof(T) >= sizeof(U), int >::type = 0 > inline T saturate_cast(U v) { return static_cast(v); } // signed -> signed narrowing template::value && std::is_integral::value && std::is_signed() && std::is_signed() && !std::is_same::value && sizeof(T) < sizeof(U), int >::type = 0 > inline T saturate_cast(U v) { return static_cast(utility::clamp(v, std::numeric_limits::lowest(), std::numeric_limits::max())); } // unsigned -> signed widening template::value && std::is_integral::value && std::is_unsigned() && std::is_signed() && !std::is_same::value && (sizeof(T) > sizeof(U)), int >::type = 0 > inline T saturate_cast(U v) { return static_cast(v); } // unsigned -> signed narrowing template::value && std::is_integral::value && std::is_unsigned() && std::is_signed() && !std::is_same::value && sizeof(T) < sizeof(U), int >::type = 0 > inline T saturate_cast(U v) { return static_cast(std::min(v, std::numeric_limits::max())); } // unsigned -> signed same_width template::value && std::is_integral::value && std::is_unsigned() && std::is_signed() && !std::is_same::value && sizeof(T) == sizeof(U), int >::type = 0 > inline T saturate_cast(U v) { return static_cast(std::min(v, std::numeric_limits::max())); } // signed -> unsigned widening/same width template::value && std::is_integral::value && std::is_signed() && std::is_unsigned() && !std::is_same::value && sizeof(T) >= sizeof(U), int >::type = 0 > inline T saturate_cast(U v) { return static_cast(std::max(0, v)); } // signed -> unsigned narrowing template::value && std::is_integral::value && std::is_signed() && std::is_unsigned() && !std::is_same::value && sizeof(T) < sizeof(U), int >::type = 0 > inline T saturate_cast(U v) { return static_cast(utility::clamp(v, 0, std::numeric_limits::max())); } // unsigned -> unsigned widening/same width template::value && std::is_integral::value && std::is_unsigned() && std::is_unsigned() && !std::is_same::value && sizeof(T) >= sizeof(U), int >::type = 0 > inline T saturate_cast(U v) { return static_cast(v); } // unsigned -> unsigned narrowing template::value && std::is_integral::value && std::is_unsigned() && std::is_unsigned() && !std::is_same::value && sizeof(T) < sizeof(U), int >::type = 0 > inline T saturate_cast(U v) { return static_cast(utility::clamp(v, std::numeric_limits::lowest(), std::numeric_limits::max())); } // float -> int template::value && traits::is_floating_point::value, int >::type = 0 > inline T saturate_cast(U v) { int32_t vi = utils::rounding::round_half_away_from_zero(v); return saturate_cast(vi); } // int -> float template::value && std::is_integral::value, int >::type = 0 > inline T saturate_cast(U v) { return static_cast(v); } // float -> float template::value && traits::is_floating_point::value, int >::type = 0 > inline T saturate_cast(U v) { return static_cast(v); } // clang-format on // *INDENT-ON* } // namespace cast } // namespace utils } // namespace arm_compute #endif /* ARM_COMPUTE_UTILS_CAST_SATURATE_CAST_H */