From 07cb3680c565640236cc6231cc9fcb7431581dde Mon Sep 17 00:00:00 2001 From: Rafael Siejakowski Date: Sun, 11 May 2025 19:08:21 +0200 Subject: [PATCH] C++20 modernization of mathfns.h The header mathfns.h containing inline mathematical utility functions is modernized: * All uses of std::enable_if are eliminated. * The function floorlog2 is reimplemented, resolving a TODO comment. * Duplicated, closely related code is moved to the header. --- src/helper/mathfns.h | 52 ++++++++++++++------------ src/ui/widget/canvas/pixelstreamer.cpp | 12 +++++- src/ui/widget/canvas/texturecache.cpp | 2 +- 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/helper/mathfns.h b/src/helper/mathfns.h index 730b6ba215..b9d467b30c 100644 --- a/src/helper/mathfns.h +++ b/src/helper/mathfns.h @@ -13,11 +13,11 @@ #ifndef INKSCAPE_HELPER_MATHFNS_H #define INKSCAPE_HELPER_MATHFNS_H +#include #include -#include <2geom/point.h> +#include -namespace Inkscape { -namespace Util { +namespace Inkscape::Util { /** * \return x rounded to the nearest multiple of c1 plus c0. @@ -55,22 +55,20 @@ inline double round_to_upper_multiple_plus(double x, double const c1, double con return std::ceil((x - c0) / c1) * c1 + c0; } -/// Returns floor(log_2(x)), assuming x >= 1. -// Note: This is a naive implementation. -// Todo: (C++20) Replace with std::bit_floor. -template -int constexpr floorlog2(T x) +/// Returns floor(log_2(x)), assuming x >= 1; if x == 0, returns -1. +int constexpr floorlog2(std::unsigned_integral auto x) { - int n = -1; - while (x > 0) { - x /= 2; - n++; - } - return n; + return std::bit_width(x) - 1; +} + +template +int constexpr index_to_binary_bucket(T index) +{ + return floorlog2((index - 1) / size) + 1; } /// Returns \a a mod \a b, always in the range 0..b-1, assuming b >= 1. -template ::value, bool>::type = true> +template T constexpr safemod(T a, T b) { a %= b; @@ -78,33 +76,41 @@ T constexpr safemod(T a, T b) } /// Returns \a a rounded down to the nearest multiple of \a b, assuming b >= 1. -template ::value, bool>::type = true> +template T constexpr round_down(T a, T b) { return a - safemod(a, b); } /// Returns \a a rounded up to the nearest multiple of \a b, assuming b >= 1. -template ::value, bool>::type = true> +template T constexpr round_up(T a, T b) { return round_down(a - 1, b) + b; } +template +concept strictly_ordered = requires(T a, T b) { + { a < b } -> std::convertible_to; + { a > b } -> std::convertible_to; +}; + /** * Just like std::clamp, except it doesn't deliberately crash if lo > hi due to rounding errors, * so is safe to use with floating-point types. (Note: compiles to branchless.) */ -template +template T safeclamp(T val, T lo, T hi) { - if (val < lo) return lo; - if (val > hi) return hi; + if (val < lo) { + return lo; + } + if (val > hi) { + return hi; + } return val; } - -} // namespace Util -} // namespace Inkscape +} // namespace Inkscape::Util #endif // INKSCAPE_HELPER_MATHFNS_H diff --git a/src/ui/widget/canvas/pixelstreamer.cpp b/src/ui/widget/canvas/pixelstreamer.cpp index 700e0505ac..1726e40f37 100644 --- a/src/ui/widget/canvas/pixelstreamer.cpp +++ b/src/ui/widget/canvas/pixelstreamer.cpp @@ -1,7 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include #include "pixelstreamer.h" + +#include +#include +#include +#include + #include "helper/mathfns.h" namespace Inkscape { @@ -234,7 +239,10 @@ class AsynchronousPixelStreamer : public PixelStreamer static int constexpr minbufsize = 0x4000; // 16 KiB static int constexpr expire_timeout = 10000; - static int constexpr size_to_bucket(int size) { return Util::floorlog2((size - 1) / minbufsize) + 1; } + static int constexpr size_to_bucket(unsigned size) + { + return Util::index_to_binary_bucket(size); + } static int constexpr bucket_maxsize(int b) { return minbufsize * (1 << b); } struct Buffer diff --git a/src/ui/widget/canvas/texturecache.cpp b/src/ui/widget/canvas/texturecache.cpp index ace1096cc2..67c784c223 100644 --- a/src/ui/widget/canvas/texturecache.cpp +++ b/src/ui/widget/canvas/texturecache.cpp @@ -17,7 +17,7 @@ class BasicTextureCache : public TextureCache static int constexpr min_dimension = 16; static int constexpr expiration_timeout = 10000; - static int constexpr dim_to_ind(int dim) { return Util::floorlog2((dim - 1) / min_dimension) + 1; } + static int constexpr dim_to_ind(unsigned dim) { return Util::index_to_binary_bucket(dim); } static int constexpr ind_to_maxdim(int index) { return min_dimension * (1 << index); } static std::pair dims_to_inds(Geom::IntPoint const &dims) { return { dim_to_ind(dims.x()), dim_to_ind(dims.y()) }; } -- GitLab