mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-26 20:55:35 +03:00
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.
This commit is contained in:
parent
62f84e94c8
commit
c6fafd3e90
Notes:
sideshowbarker
2024-07-18 10:06:28 +09:00
Author: https://github.com/BertalanD Commit: https://github.com/SerenityOS/serenity/commit/c6fafd3e90b Pull-request: https://github.com/SerenityOS/serenity/pull/8470 Reviewed-by: https://github.com/Dexesttp Reviewed-by: https://github.com/Hendiadyoin1 Reviewed-by: https://github.com/alimpfard Reviewed-by: https://github.com/gunnarbeutner ✅
@ -125,6 +125,26 @@ constexpr bool is_constant_evaluated()
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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()) \
|
||||
return num < zero ? -num : num; \
|
||||
else \
|
||||
return __builtin_##intrinsic(num); \
|
||||
}
|
||||
|
||||
__DEFINE_GENERIC_ABS(int, 0, abs);
|
||||
__DEFINE_GENERIC_ABS(long, 0l, labs);
|
||||
__DEFINE_GENERIC_ABS(long long, 0ll, llabs);
|
||||
#ifndef KERNEL
|
||||
__DEFINE_GENERIC_ABS(float, 0.0f, fabsf);
|
||||
__DEFINE_GENERIC_ABS(double, 0.0, fabs);
|
||||
__DEFINE_GENERIC_ABS(long double, 0.0l, fabsl);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
using AK::array_size;
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "EyesWidget.h"
|
||||
#include <AK/StdLibExtraDetails.h>
|
||||
#include <LibGUI/Painter.h>
|
||||
#include <LibGUI/Window.h>
|
||||
#include <LibGUI/WindowServerConnection.h>
|
||||
@ -89,14 +90,14 @@ Gfx::IntPoint EyesWidget::pupil_center(Gfx::IntRect& eyeball_bounds) const
|
||||
double max_distance_along_this_direction;
|
||||
|
||||
// clang-format off
|
||||
if (dx != 0 && abs(dx) >= abs(dy)) {
|
||||
if (dx != 0 && AK::abs(dx) >= AK::abs(dy)) {
|
||||
double slope = dy / dx;
|
||||
double slope_squared = slope * slope;
|
||||
max_distance_along_this_direction = 0.25 * sqrt(
|
||||
(slope_squared + 1) /
|
||||
(1 / width_squared + slope_squared / height_squared)
|
||||
);
|
||||
} else if (dy != 0 && abs(dy) >= abs(dx)) {
|
||||
} else if (dy != 0 && AK::abs(dy) >= AK::abs(dx)) {
|
||||
double slope = dx / dy;
|
||||
double slope_squared = slope * slope;
|
||||
max_distance_along_this_direction = 0.25 * sqrt(
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <LibGfx/Orientation.h>
|
||||
#include <LibIPC/Forward.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
@ -217,7 +216,7 @@ public:
|
||||
// Returns pixels moved from other in either direction
|
||||
[[nodiscard]] T pixels_moved(Point<T> const& other) const
|
||||
{
|
||||
return max(abs(dx_relative_to(other)), abs(dy_relative_to(other)));
|
||||
return max(AK::abs(dx_relative_to(other)), AK::abs(dy_relative_to(other)));
|
||||
}
|
||||
|
||||
[[nodiscard]] float distance_from(Point<T> const& other) const
|
||||
@ -229,7 +228,7 @@ public:
|
||||
|
||||
[[nodiscard]] Point absolute_relative_distance_to(Point const& other) const
|
||||
{
|
||||
return { abs(dx_relative_to(other)), abs(dy_relative_to(other)) };
|
||||
return { AK::abs(dx_relative_to(other)), AK::abs(dy_relative_to(other)) };
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
|
@ -179,7 +179,7 @@ static String double_to_string(double d)
|
||||
else
|
||||
builder.append('-');
|
||||
|
||||
builder.append(String::number(fabs(exponent - 1)));
|
||||
builder.append(String::number(AK::abs(exponent - 1)));
|
||||
return builder.to_string();
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ static String double_to_string(double d)
|
||||
else
|
||||
builder.append('-');
|
||||
|
||||
builder.append(String::number(fabs(exponent - 1)));
|
||||
builder.append(String::number(AK::abs(exponent - 1)));
|
||||
return builder.to_string();
|
||||
}
|
||||
|
||||
|
@ -482,7 +482,7 @@ void FlexFormattingContext::run(Box& box, LayoutMode)
|
||||
|
||||
if (sum_of_unfrozen_flex_items_flex_factors < 1) {
|
||||
auto intermediate_free_space = initial_free_space * sum_of_unfrozen_flex_items_flex_factors;
|
||||
if (abs(intermediate_free_space) < abs(remaining_free_space))
|
||||
if (AK::abs(intermediate_free_space) < AK::abs(remaining_free_space))
|
||||
remaining_free_space = intermediate_free_space;
|
||||
}
|
||||
|
||||
@ -503,7 +503,7 @@ void FlexFormattingContext::run(Box& box, LayoutMode)
|
||||
|
||||
for_each_unfrozen_item([&](FlexItem* flex_item) {
|
||||
float ratio = flex_item->scaled_flex_shrink_factor / sum_of_scaled_flex_shrink_factor_of_unfrozen_items;
|
||||
flex_item->target_main_size = flex_item->flex_base_size - (abs(remaining_free_space) * ratio);
|
||||
flex_item->target_main_size = flex_item->flex_base_size - (AK::abs(remaining_free_space) * ratio);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user