StdLibExtras.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/StdLibExtraDetails.h>
  8. #include <AK/Assertions.h>
  9. template<typename T, typename U>
  10. constexpr auto round_up_to_power_of_two(T value, U power_of_two) requires(IsIntegral<T>&& IsIntegral<U>)
  11. {
  12. return ((value - 1) & ~(power_of_two - 1)) + power_of_two;
  13. }
  14. namespace std {
  15. // NOTE: This is in the "std" namespace since some compiler features rely on it.
  16. template<typename T>
  17. constexpr T&& move(T& arg)
  18. {
  19. return static_cast<T&&>(arg);
  20. }
  21. }
  22. using std::move;
  23. namespace AK::Detail {
  24. template<typename T>
  25. struct _RawPtr {
  26. using Type = T*;
  27. };
  28. }
  29. namespace AK {
  30. template<class T>
  31. constexpr T&& forward(RemoveReference<T>& param)
  32. {
  33. return static_cast<T&&>(param);
  34. }
  35. template<class T>
  36. constexpr T&& forward(RemoveReference<T>&& param) noexcept
  37. {
  38. static_assert(!IsLvalueReference<T>, "Can't forward an rvalue as an lvalue.");
  39. return static_cast<T&&>(param);
  40. }
  41. template<typename T, typename SizeType = decltype(sizeof(T)), SizeType N>
  42. constexpr SizeType array_size(T (&)[N])
  43. {
  44. return N;
  45. }
  46. template<typename T>
  47. constexpr T min(const T& a, const IdentityType<T>& b)
  48. {
  49. return b < a ? b : a;
  50. }
  51. template<typename T>
  52. constexpr T max(const T& a, const IdentityType<T>& b)
  53. {
  54. return a < b ? b : a;
  55. }
  56. template<typename T>
  57. constexpr T clamp(const T& value, const IdentityType<T>& min, const IdentityType<T>& max)
  58. {
  59. VERIFY(max >= min);
  60. if (value > max)
  61. return max;
  62. if (value < min)
  63. return min;
  64. return value;
  65. }
  66. template<typename T, typename U>
  67. constexpr T ceil_div(T a, U b)
  68. {
  69. static_assert(sizeof(T) == sizeof(U));
  70. T result = a / b;
  71. if ((a % b) != 0)
  72. ++result;
  73. return result;
  74. }
  75. template<typename T, typename U>
  76. inline void swap(T& a, U& b)
  77. {
  78. U tmp = move((U&)a);
  79. a = (T &&) move(b);
  80. b = move(tmp);
  81. }
  82. template<typename T, typename U = T>
  83. constexpr T exchange(T& slot, U&& value)
  84. {
  85. T old_value = move(slot);
  86. slot = forward<U>(value);
  87. return old_value;
  88. }
  89. template<typename T>
  90. using RawPtr = typename Detail::_RawPtr<T>::Type;
  91. template<typename V>
  92. constexpr decltype(auto) to_underlying(V value) requires(IsEnum<V>)
  93. {
  94. return static_cast<UnderlyingType<V>>(value);
  95. }
  96. constexpr bool is_constant_evaluated()
  97. {
  98. #if __has_builtin(__builtin_is_constant_evaluated)
  99. return __builtin_is_constant_evaluated();
  100. #else
  101. return false;
  102. #endif
  103. }
  104. // These can't be exported into the global namespace as they would clash with the C standard library.
  105. #define __DEFINE_GENERIC_ABS(type, zero, intrinsic) \
  106. constexpr type abs(type num) \
  107. { \
  108. if (is_constant_evaluated()) \
  109. return num < zero ? -num : num; \
  110. else \
  111. return __builtin_##intrinsic(num); \
  112. }
  113. __DEFINE_GENERIC_ABS(int, 0, abs);
  114. __DEFINE_GENERIC_ABS(long, 0l, labs);
  115. __DEFINE_GENERIC_ABS(long long, 0ll, llabs);
  116. #ifndef KERNEL
  117. __DEFINE_GENERIC_ABS(float, 0.0f, fabsf);
  118. __DEFINE_GENERIC_ABS(double, 0.0, fabs);
  119. __DEFINE_GENERIC_ABS(long double, 0.0l, fabsl);
  120. #endif
  121. }
  122. using AK::array_size;
  123. using AK::ceil_div;
  124. using AK::clamp;
  125. using AK::exchange;
  126. using AK::forward;
  127. using AK::is_constant_evaluated;
  128. using AK::max;
  129. using AK::min;
  130. using AK::RawPtr;
  131. using AK::swap;
  132. using AK::to_underlying;