linux/lib/math
Nicolas Pitre b29a62d87c mul_u64_u64_div_u64: make it precise always
Patch series "mul_u64_u64_div_u64: new implementation", v3.

This provides an implementation for mul_u64_u64_div_u64() that always
produces exact results.


This patch (of 2):

Library facilities must always return exact results.  If the caller may be
contented with approximations then it should do the approximation on its
own.

In this particular case the comment in the code says "the algorithm
... below might lose some precision". Well, if you try it with e.g.:

	a = 18446462598732840960
	b = 18446462598732840960
	c = 18446462598732840961

then the produced answer is 0 whereas the exact answer should be
18446462598732840959.  This is _some_ precision lost indeed!

Let's reimplement this function so it always produces the exact result
regardless of its inputs while preserving existing fast paths when
possible.

Uwe said:

: My personal interest is to get the calculations in pwm drivers right. 
: This function is used in several drivers below drivers/pwm/ .  With the
: errors in mul_u64_u64_div_u64(), pwm consumers might not get the
: settings they request.  Although I have to admit that I'm not aware it
: breaks real use cases (because typically the periods used are too short
: to make the involved multiplications overflow), but I pretty sure am
: not aware of all usages and it breaks testing.
: 
: Another justification is commits like
: https://git.kernel.org/tip/77baa5bafcbe1b2a15ef9c37232c21279c95481c,
: where people start to work around the precision shortcomings of
: mul_u64_u64_div_u64().

Link: https://lkml.kernel.org/r/20240707190648.1982714-1-nico@fluxnic.net
Link: https://lkml.kernel.org/r/20240707190648.1982714-2-nico@fluxnic.net
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Tested-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Reviewed-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Tested-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2024-09-01 20:43:22 -07:00
..
cordic.c
div64.c mul_u64_u64_div_u64: make it precise always 2024-09-01 20:43:22 -07:00
gcd.c treewide: Add SPDX license identifier for missed files 2019-05-21 10:50:45 +02:00
int_log.c lib/math/int_log: Replace LGPL-2.1-or-later boilerplate with SPDX identifier 2023-07-09 22:47:50 +01:00
int_pow.c kernel.h: split out mathematical helpers 2020-12-15 22:46:15 -08:00
int_sqrt.c kernel.h: split out mathematical helpers 2020-12-15 22:46:15 -08:00
Kconfig math: make RATIONAL tristate 2021-09-08 11:50:26 -07:00
lcm.c treewide: Add SPDX license identifier for missed files 2019-05-21 10:50:45 +02:00
Makefile lib/math: Move dvb_math.c into lib/math/int_log.c 2023-07-09 22:47:48 +01:00
prime_numbers.c lib/math: add missing MODULE_DESCRIPTION() macros 2024-06-04 17:40:07 +02:00
rational-test.c lib/math: add missing MODULE_DESCRIPTION() macros 2024-06-04 17:40:07 +02:00
rational.c math: rational: add missing MODULE_DESCRIPTION() macro 2024-07-04 23:43:11 -07:00
reciprocal_div.c kernel.h: split out mathematical helpers 2020-12-15 22:46:15 -08:00
test_div64.c lib/math/test_div64: Correct the spelling of "dividend" 2021-04-23 13:40:05 +02:00