From 2277b7c693d9e05c5e7360bf00311092799e0022 Mon Sep 17 00:00:00 2001 From: John Sanpe Date: Tue, 14 Jan 2025 03:32:20 +0800 Subject: [PATCH 1/2] feat math: added abs functions Signed-off-by: John Sanpe --- include/bfdev/math.h | 73 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/include/bfdev/math.h b/include/bfdev/math.h index 36f17250..8de107cf 100644 --- a/include/bfdev/math.h +++ b/include/bfdev/math.h @@ -38,6 +38,79 @@ BFDEV_BEGIN_DECLS (x) & ~bfdev_round_mask(x, y) \ ) +#define bfdev_abs_expr(var, type, other) __builtin_choose_expr( \ + __builtin_types_compatible_p(typeof(var), signed type) || \ + __builtin_types_compatible_p(typeof(var), unsigned type), \ + ({ \ + signed type __var; \ + __var = (signed type)(var); \ + __var < 0 ? - __var : __var; \ + }), other \ +) + +/** + * bfdev_abs - return absolute value of an argument. + * + * If it is unsigned type, it is converted to signed type first. + * char is treated as if it was signed but the macro's + * return type is preserved as char. + */ +#define bfdev_abs(var) \ + bfdev_abs_expr(var, long long, \ + bfdev_abs_expr(var, long, \ + bfdev_abs_expr(var, int, \ + bfdev_abs_expr(var, short, \ + bfdev_abs_expr(var, char, \ + __builtin_choose_expr( \ + __builtin_types_compatible_p( \ + typeof(var), char), \ + (char) ({ \ + signed char __var; \ + __var = (signed char)(var); \ + __var < 0 ? - __var : __var; \ + }), \ + ((void)0) \ + ) \ + )))) \ +) + +/** + * bfdev_abs_diff - return absolute value of the difference between the args. + * @var1: the first argument. + * @var2: the second argument. + */ +#define bfdev_abs_diff(var1, var2) ({ \ + typeof(var1) __var1, __var2; \ + \ + __var1 = (typeof(var1))(var1); \ + __var2 = (typeof(var1))(var2); \ + \ + __var1 > __var2 \ + ? (__var1 - __var2) \ + : (__var2 - __var1); \ +}) + +/** + * BFDEV_MULT_FRAC + * + * Calculate "value * numer / denom" + * without unnecessary overflow or loss of precision. + */ +#define BFDEV_MULT_FRAC(value, numer, denom) ({ \ + typeof(value) __value, __numer, __denom; \ + typeof(value) __quot, __rem; \ + \ + __value = (typeof(value))(value); \ + __numer = (typeof(value))(numer); \ + __denom = (typeof(value))(denom); \ + \ + __quot = (__value) / (__denom); \ + __rem = (__value) % (__denom); \ + \ + (__quot * (__numer)) + \ + ((__rem * (__numer)) / (__denom)); \ +}) + /** * BFDEV_DIV_ROUND_UP - round up division. * @n: divisor number. From 3c65b8122731f1946c496dd54abc7adb366cae01 Mon Sep 17 00:00:00 2001 From: John Sanpe Date: Tue, 14 Jan 2025 03:32:47 +0800 Subject: [PATCH 2/2] feat examples: added math abs example Signed-off-by: John Sanpe --- examples/CMakeLists.txt | 1 + examples/math/.gitignore | 2 ++ examples/math/CMakeLists.txt | 22 ++++++++++++++++++++++ examples/math/abs.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 examples/math/.gitignore create mode 100644 examples/math/CMakeLists.txt create mode 100644 examples/math/abs.c diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d5c0bb9d..bfc718ee 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -30,6 +30,7 @@ add_subdirectory(levenshtein) add_subdirectory(list) add_subdirectory(log) add_subdirectory(log2) +add_subdirectory(math) add_subdirectory(matrix) add_subdirectory(mpi) add_subdirectory(notifier) diff --git a/examples/math/.gitignore b/examples/math/.gitignore new file mode 100644 index 00000000..cadac6b5 --- /dev/null +++ b/examples/math/.gitignore @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +/math-abs diff --git a/examples/math/CMakeLists.txt b/examples/math/CMakeLists.txt new file mode 100644 index 00000000..14e6e329 --- /dev/null +++ b/examples/math/CMakeLists.txt @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright(c) 2023 ffashion +# + +add_executable(math-abs abs.c) +target_link_libraries(math-abs bfdev) +add_test(math-abs math-abs) + +if(${CMAKE_PROJECT_NAME} STREQUAL "bfdev") + install(FILES + abs.c + DESTINATION + ${CMAKE_INSTALL_DOCDIR}/examples/list + ) + + install(TARGETS + math-abs + DESTINATION + ${CMAKE_INSTALL_DOCDIR}/bin + ) +endif() diff --git a/examples/math/abs.c b/examples/math/abs.c new file mode 100644 index 00000000..e334fbc0 --- /dev/null +++ b/examples/math/abs.c @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * Copyright(c) 2024 John Sanpe + */ + +#define MODULE_NAME "math-abs" +#define bfdev_log_fmt(fmt) MODULE_NAME ": " fmt + +#include +#include +#include + +#define ABS_TEST(name, min, max) ({ \ + long long __result; \ + __result = (long long)bfdev_abs(min); \ + bfdev_log_info(name " %lld -> %lld\n", \ + (long long)min, __result); \ + if (max != __result) { \ + bfdev_log_err("test failed"); \ + return 1; \ + } \ +}) + +int +main(int argc, const char *argv[]) +{ + ABS_TEST("char", BFDEV_CHAR_MIN + 1, BFDEV_CHAR_MAX); + ABS_TEST("short", BFDEV_SHRT_MIN + 1, BFDEV_SHRT_MAX); + ABS_TEST("int", BFDEV_INT_MIN + 1, BFDEV_INT_MAX); + ABS_TEST("long", BFDEV_LONG_MIN + 1, BFDEV_LONG_MAX); + ABS_TEST("long long", BFDEV_LLONG_MIN + 1, BFDEV_LLONG_MAX); + + return 0; +}