2020-01-18 08:38:21 +00:00
|
|
|
/*
|
2022-08-01 09:14:20 +00:00
|
|
|
* Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
|
2020-01-18 08:38:21 +00:00
|
|
|
*
|
2021-04-22 08:24:48 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 08:38:21 +00:00
|
|
|
*/
|
|
|
|
|
2018-10-10 09:53:07 +00:00
|
|
|
#pragma once
|
|
|
|
|
2022-10-04 19:04:13 +00:00
|
|
|
#include <AK/Platform.h>
|
|
|
|
|
|
|
|
#if defined(AK_COMPILER_CLANG) || defined(__CLION_IDE__)
|
2022-08-01 09:14:20 +00:00
|
|
|
# pragma clang diagnostic ignored "-Wunqualified-std-cast-call"
|
|
|
|
#endif
|
|
|
|
|
2021-04-10 13:59:06 +00:00
|
|
|
#include <AK/StdLibExtraDetails.h>
|
|
|
|
|
2021-03-07 20:22:36 +00:00
|
|
|
#include <AK/Assertions.h>
|
|
|
|
|
2022-12-12 20:36:11 +00:00
|
|
|
namespace AK {
|
|
|
|
|
2021-05-29 15:18:22 +00:00
|
|
|
template<typename T, typename U>
|
2022-10-16 22:06:11 +00:00
|
|
|
constexpr auto round_up_to_power_of_two(T value, U power_of_two)
|
|
|
|
requires(AK::Detail::IsIntegral<T> && AK::Detail::IsIntegral<U>)
|
2019-05-06 12:04:54 +00:00
|
|
|
{
|
2019-05-28 09:53:16 +00:00
|
|
|
return ((value - 1) & ~(power_of_two - 1)) + power_of_two;
|
2019-05-06 12:04:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-29 07:15:21 +00:00
|
|
|
template<typename T>
|
2022-10-16 22:06:11 +00:00
|
|
|
constexpr bool is_power_of_two(T value)
|
|
|
|
requires(AK::Detail::IsIntegral<T>)
|
2022-01-29 07:15:21 +00:00
|
|
|
{
|
|
|
|
return value && !((value) & (value - 1));
|
|
|
|
}
|
|
|
|
|
2022-12-12 20:36:11 +00:00
|
|
|
}
|
|
|
|
|
2022-12-14 11:51:48 +00:00
|
|
|
#if !USING_AK_GLOBALLY || defined(AK_DONT_REPLACE_STD)
|
2022-12-13 06:59:30 +00:00
|
|
|
# define AK_REPLACED_STD_NAMESPACE AK::replaced_std
|
|
|
|
#else
|
|
|
|
# define AK_REPLACED_STD_NAMESPACE std
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace AK_REPLACED_STD_NAMESPACE { // NOLINT(cert-dcl58-cpp) Names in std to aid tools
|
2021-03-17 15:31:17 +00:00
|
|
|
|
2021-09-01 12:10:44 +00:00
|
|
|
// NOTE: These are in the "std" namespace since some compilers and static analyzers rely on it.
|
2022-12-13 06:59:30 +00:00
|
|
|
// If USING_AK_GLOBALLY is false, we can't put them in ::std, so we put them in AK::replaced_std instead
|
|
|
|
// The user code should not notice anything unless it explicitly asks for std::stuff, so...don't.
|
2021-09-01 12:10:44 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2022-12-12 20:36:11 +00:00
|
|
|
constexpr T&& forward(AK::Detail::RemoveReference<T>& param)
|
2021-09-01 12:10:44 +00:00
|
|
|
{
|
|
|
|
return static_cast<T&&>(param);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2022-12-12 20:36:11 +00:00
|
|
|
constexpr T&& forward(AK::Detail::RemoveReference<T>&& param) noexcept
|
2021-09-01 12:10:44 +00:00
|
|
|
{
|
2022-12-12 20:36:11 +00:00
|
|
|
static_assert(!AK::Detail::IsLvalueReference<T>, "Can't forward an rvalue as an lvalue.");
|
2021-09-01 12:10:44 +00:00
|
|
|
return static_cast<T&&>(param);
|
|
|
|
}
|
2021-03-17 15:31:17 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
constexpr T&& move(T& arg)
|
|
|
|
{
|
|
|
|
return static_cast<T&&>(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-12-12 20:36:11 +00:00
|
|
|
namespace AK {
|
2022-12-13 06:59:30 +00:00
|
|
|
using AK_REPLACED_STD_NAMESPACE::forward;
|
|
|
|
using AK_REPLACED_STD_NAMESPACE::move;
|
2022-12-12 20:36:11 +00:00
|
|
|
}
|
|
|
|
|
2021-04-16 12:03:24 +00:00
|
|
|
namespace AK::Detail {
|
|
|
|
template<typename T>
|
|
|
|
struct _RawPtr {
|
|
|
|
using Type = T*;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-10-10 09:53:07 +00:00
|
|
|
namespace AK {
|
|
|
|
|
2020-08-16 09:04:00 +00:00
|
|
|
template<typename T, typename SizeType = decltype(sizeof(T)), SizeType N>
|
|
|
|
constexpr SizeType array_size(T (&)[N])
|
|
|
|
{
|
|
|
|
return N;
|
|
|
|
}
|
|
|
|
|
2018-10-10 09:53:07 +00:00
|
|
|
template<typename T>
|
2022-10-16 22:06:11 +00:00
|
|
|
constexpr T min(T const& a, IdentityType<T> const& b)
|
2018-10-10 09:53:07 +00:00
|
|
|
{
|
2020-08-06 07:58:45 +00:00
|
|
|
return b < a ? b : a;
|
2018-10-10 09:53:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2022-10-16 22:06:11 +00:00
|
|
|
constexpr T max(T const& a, IdentityType<T> const& b)
|
2018-10-10 09:53:07 +00:00
|
|
|
{
|
|
|
|
return a < b ? b : a;
|
|
|
|
}
|
|
|
|
|
2020-01-20 08:54:15 +00:00
|
|
|
template<typename T>
|
2022-10-16 22:06:11 +00:00
|
|
|
constexpr T clamp(T const& value, IdentityType<T> const& min, IdentityType<T> const& max)
|
2020-01-20 08:54:15 +00:00
|
|
|
{
|
2021-02-23 19:42:32 +00:00
|
|
|
VERIFY(max >= min);
|
2020-01-20 08:54:15 +00:00
|
|
|
if (value > max)
|
|
|
|
return max;
|
|
|
|
if (value < min)
|
|
|
|
return min;
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2022-01-04 14:01:25 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
constexpr T mix(T const& v1, T const& v2, U const& interpolation)
|
|
|
|
{
|
|
|
|
return v1 + (v2 - v1) * interpolation;
|
|
|
|
}
|
|
|
|
|
2018-11-08 14:39:26 +00:00
|
|
|
template<typename T, typename U>
|
2020-10-20 16:08:13 +00:00
|
|
|
constexpr T ceil_div(T a, U b)
|
2018-10-10 09:53:07 +00:00
|
|
|
{
|
2018-11-08 14:39:26 +00:00
|
|
|
static_assert(sizeof(T) == sizeof(U));
|
2018-10-10 09:53:07 +00:00
|
|
|
T result = a / b;
|
|
|
|
if ((a % b) != 0)
|
|
|
|
++result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-10-16 12:33:16 +00:00
|
|
|
template<typename T, typename U>
|
2020-01-19 09:28:58 +00:00
|
|
|
inline void swap(T& a, U& b)
|
2018-10-16 12:33:16 +00:00
|
|
|
{
|
2021-08-28 15:19:21 +00:00
|
|
|
if (&a == &b)
|
|
|
|
return;
|
2018-10-16 12:33:16 +00:00
|
|
|
U tmp = move((U&)a);
|
2019-05-28 09:53:16 +00:00
|
|
|
a = (T &&) move(b);
|
2018-10-16 12:33:16 +00:00
|
|
|
b = move(tmp);
|
|
|
|
}
|
2018-10-16 10:20:51 +00:00
|
|
|
|
2020-04-22 09:52:26 +00:00
|
|
|
template<typename T, typename U = T>
|
2020-10-19 16:30:30 +00:00
|
|
|
constexpr T exchange(T& slot, U&& value)
|
2020-04-22 09:52:26 +00:00
|
|
|
{
|
|
|
|
T old_value = move(slot);
|
|
|
|
slot = forward<U>(value);
|
|
|
|
return old_value;
|
|
|
|
}
|
|
|
|
|
2021-04-16 12:03:24 +00:00
|
|
|
template<typename T>
|
|
|
|
using RawPtr = typename Detail::_RawPtr<T>::Type;
|
|
|
|
|
2021-06-15 13:03:47 +00:00
|
|
|
template<typename V>
|
2022-10-16 22:06:11 +00:00
|
|
|
constexpr decltype(auto) to_underlying(V value)
|
|
|
|
requires(IsEnum<V>)
|
2021-06-15 13:03:47 +00:00
|
|
|
{
|
|
|
|
return static_cast<UnderlyingType<V>>(value);
|
|
|
|
}
|
|
|
|
|
2021-06-27 18:11:38 +00:00
|
|
|
constexpr bool is_constant_evaluated()
|
|
|
|
{
|
|
|
|
#if __has_builtin(__builtin_is_constant_evaluated)
|
|
|
|
return __builtin_is_constant_evaluated();
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
AK+Userland: Add generic `AK::abs()` function and use it
Previously, in LibGFX's `Point` class, calculated distances were passed
to the integer `abs` function, even if the stored type was a float. This
caused the value to unexpectedly be truncated. Luckily, this API was not
used with floating point types, but that can change in the future, so
why not fix it now :^)
Since we are in C++, we can use function overloading to make things
easy, and to automatically use the right version.
This is even better than the LibC/LibM functions, as using a bit of
hackery, they are able to be constant-evaluated. They use compiler
intrinsics, so they do not depend on external code and the compiler can
emit the most optimized code by default.
Since we aren't using the C++ standard library's trick of importing
everything into the `AK` namespace, this `abs` function cannot be
exported to the global namespace, as the names would clash.
2021-07-05 16:38:17 +00:00
|
|
|
// These can't be exported into the global namespace as they would clash with the C standard library.
|
|
|
|
|
|
|
|
#define __DEFINE_GENERIC_ABS(type, zero, intrinsic) \
|
|
|
|
constexpr type abs(type num) \
|
|
|
|
{ \
|
|
|
|
if (is_constant_evaluated()) \
|
2021-11-06 17:24:53 +00:00
|
|
|
return num < (zero) ? -num : num; \
|
|
|
|
return __builtin_##intrinsic(num); \
|
AK+Userland: Add generic `AK::abs()` function and use it
Previously, in LibGFX's `Point` class, calculated distances were passed
to the integer `abs` function, even if the stored type was a float. This
caused the value to unexpectedly be truncated. Luckily, this API was not
used with floating point types, but that can change in the future, so
why not fix it now :^)
Since we are in C++, we can use function overloading to make things
easy, and to automatically use the right version.
This is even better than the LibC/LibM functions, as using a bit of
hackery, they are able to be constant-evaluated. They use compiler
intrinsics, so they do not depend on external code and the compiler can
emit the most optimized code by default.
Since we aren't using the C++ standard library's trick of importing
everything into the `AK` namespace, this `abs` function cannot be
exported to the global namespace, as the names would clash.
2021-07-05 16:38:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
__DEFINE_GENERIC_ABS(int, 0, abs);
|
2021-11-06 17:26:02 +00:00
|
|
|
__DEFINE_GENERIC_ABS(long, 0L, labs);
|
|
|
|
__DEFINE_GENERIC_ABS(long long, 0LL, llabs);
|
AK+Userland: Add generic `AK::abs()` function and use it
Previously, in LibGFX's `Point` class, calculated distances were passed
to the integer `abs` function, even if the stored type was a float. This
caused the value to unexpectedly be truncated. Luckily, this API was not
used with floating point types, but that can change in the future, so
why not fix it now :^)
Since we are in C++, we can use function overloading to make things
easy, and to automatically use the right version.
This is even better than the LibC/LibM functions, as using a bit of
hackery, they are able to be constant-evaluated. They use compiler
intrinsics, so they do not depend on external code and the compiler can
emit the most optimized code by default.
Since we aren't using the C++ standard library's trick of importing
everything into the `AK` namespace, this `abs` function cannot be
exported to the global namespace, as the names would clash.
2021-07-05 16:38:17 +00:00
|
|
|
#ifndef KERNEL
|
2021-11-06 17:26:02 +00:00
|
|
|
__DEFINE_GENERIC_ABS(float, 0.0F, fabsf);
|
AK+Userland: Add generic `AK::abs()` function and use it
Previously, in LibGFX's `Point` class, calculated distances were passed
to the integer `abs` function, even if the stored type was a float. This
caused the value to unexpectedly be truncated. Luckily, this API was not
used with floating point types, but that can change in the future, so
why not fix it now :^)
Since we are in C++, we can use function overloading to make things
easy, and to automatically use the right version.
This is even better than the LibC/LibM functions, as using a bit of
hackery, they are able to be constant-evaluated. They use compiler
intrinsics, so they do not depend on external code and the compiler can
emit the most optimized code by default.
Since we aren't using the C++ standard library's trick of importing
everything into the `AK` namespace, this `abs` function cannot be
exported to the global namespace, as the names would clash.
2021-07-05 16:38:17 +00:00
|
|
|
__DEFINE_GENERIC_ABS(double, 0.0, fabs);
|
2021-11-06 17:26:02 +00:00
|
|
|
__DEFINE_GENERIC_ABS(long double, 0.0L, fabsl);
|
AK+Userland: Add generic `AK::abs()` function and use it
Previously, in LibGFX's `Point` class, calculated distances were passed
to the integer `abs` function, even if the stored type was a float. This
caused the value to unexpectedly be truncated. Luckily, this API was not
used with floating point types, but that can change in the future, so
why not fix it now :^)
Since we are in C++, we can use function overloading to make things
easy, and to automatically use the right version.
This is even better than the LibC/LibM functions, as using a bit of
hackery, they are able to be constant-evaluated. They use compiler
intrinsics, so they do not depend on external code and the compiler can
emit the most optimized code by default.
Since we aren't using the C++ standard library's trick of importing
everything into the `AK` namespace, this `abs` function cannot be
exported to the global namespace, as the names would clash.
2021-07-05 16:38:17 +00:00
|
|
|
#endif
|
|
|
|
|
2021-11-06 17:26:02 +00:00
|
|
|
#undef __DEFINE_GENERIC_ABS
|
|
|
|
|
2018-10-10 09:53:07 +00:00
|
|
|
}
|
|
|
|
|
2022-11-26 11:18:30 +00:00
|
|
|
#if USING_AK_GLOBALLY
|
2020-08-16 09:04:00 +00:00
|
|
|
using AK::array_size;
|
2019-05-28 09:53:16 +00:00
|
|
|
using AK::ceil_div;
|
2020-02-09 14:50:13 +00:00
|
|
|
using AK::clamp;
|
2019-05-28 09:53:16 +00:00
|
|
|
using AK::exchange;
|
2022-12-13 06:59:30 +00:00
|
|
|
using AK::forward;
|
2021-06-27 18:11:38 +00:00
|
|
|
using AK::is_constant_evaluated;
|
2022-12-12 20:36:11 +00:00
|
|
|
using AK::is_power_of_two;
|
2018-10-10 09:53:07 +00:00
|
|
|
using AK::max;
|
2019-05-28 09:53:16 +00:00
|
|
|
using AK::min;
|
2022-01-04 14:01:25 +00:00
|
|
|
using AK::mix;
|
2022-12-13 06:59:30 +00:00
|
|
|
using AK::move;
|
2021-04-16 12:03:24 +00:00
|
|
|
using AK::RawPtr;
|
2022-12-12 20:36:11 +00:00
|
|
|
using AK::round_up_to_power_of_two;
|
2019-06-07 09:46:22 +00:00
|
|
|
using AK::swap;
|
2021-06-15 13:03:47 +00:00
|
|
|
using AK::to_underlying;
|
2022-11-26 11:18:30 +00:00
|
|
|
#endif
|