1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef _LIBCPP___CXX03___BIT_ROTATE_H 10 #define _LIBCPP___CXX03___BIT_ROTATE_H 11 12 #include <__cxx03/__config> 13 #include <__cxx03/__type_traits/is_unsigned_integer.h> 14 #include <__cxx03/limits> 15 16 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 17 # pragma GCC system_header 18 #endif 19 20 _LIBCPP_BEGIN_NAMESPACE_STD 21 22 // Writing two full functions for rotl and rotr makes it easier for the compiler 23 // to optimize the code. On x86 this function becomes the ROL instruction and 24 // the rotr function becomes the ROR instruction. 25 template <class _Tp> __rotl(_Tp __x,int __s)26_LIBCPP_HIDE_FROM_ABI _Tp __rotl(_Tp __x, int __s) _NOEXCEPT { 27 static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotl requires an unsigned integer type"); 28 const int __N = numeric_limits<_Tp>::digits; 29 int __r = __s % __N; 30 31 if (__r == 0) 32 return __x; 33 34 if (__r > 0) 35 return (__x << __r) | (__x >> (__N - __r)); 36 37 return (__x >> -__r) | (__x << (__N + __r)); 38 } 39 40 template <class _Tp> __rotr(_Tp __x,int __s)41_LIBCPP_HIDE_FROM_ABI _Tp __rotr(_Tp __x, int __s) _NOEXCEPT { 42 static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotr requires an unsigned integer type"); 43 const int __N = numeric_limits<_Tp>::digits; 44 int __r = __s % __N; 45 46 if (__r == 0) 47 return __x; 48 49 if (__r > 0) 50 return (__x >> __r) | (__x << (__N - __r)); 51 52 return (__x << -__r) | (__x >> (__N + __r)); 53 } 54 55 _LIBCPP_END_NAMESPACE_STD 56 57 #endif // _LIBCPP___CXX03___BIT_ROTATE_H 58