From nobody Fri Dec 19 11:01:30 2025 Received: from pb-smtp21.pobox.com (pb-smtp21.pobox.com [173.228.157.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C5A25588B for ; Sun, 7 Jul 2024 19:07:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.228.157.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720379227; cv=none; b=Z2yv7Lf8YVytPTIbc1WCmBLsf61R6XFPlnp9sS4NY8ttCG778QYq0qksyFNO49/pwmtc08NHAZhTCyryutGyHBlvOORm4sx4Voc3QAznCXPPEDDXV5bhosDy0jThPFBDMqzy47Cmh0pRaR7MNc34FvzhntAEioKyLGvKs17dnL0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720379227; c=relaxed/simple; bh=6kW25pg6VPwOxN0PpF7KB3SJguMNccZ4U3jj4C23kcc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lNLYsu9OPLWyGsCnArRMpu1w3p3cx1Z5E35Ktw1AEtdNW24uDVIKeQZTePUsizJTFqBkeCNtUKF6r7ZyHYxcWX8GCqvvyuFMSLz8kGj0LcRhdW+MdHdxJYS+3iIAknJfrhvw9NLHTu9szCz5/EarUfLh0yrpqD3mfFJCrNPMv00= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=fluxnic.net; spf=pass smtp.mailfrom=fluxnic.net; dkim=pass (1024-bit key) header.d=pobox.com header.i=@pobox.com header.b=RvCMm0hU; dkim=fail (1024-bit key) header.d=fluxnic.net header.i=@fluxnic.net header.b=cqswCqqi reason="signature verification failed"; arc=none smtp.client-ip=173.228.157.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=fluxnic.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=fluxnic.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=pobox.com header.i=@pobox.com header.b="RvCMm0hU"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=fluxnic.net header.i=@fluxnic.net header.b="cqswCqqi" Received: from pb-smtp21.pobox.com (unknown [127.0.0.1]) by pb-smtp21.pobox.com (Postfix) with ESMTP id 2A98D32D97; Sun, 7 Jul 2024 15:07:00 -0400 (EDT) (envelope-from nico@fluxnic.net) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed; d=pobox.com; h=from:to:cc :subject:date:message-id:in-reply-to:references:mime-version :content-type:content-transfer-encoding; s=sasl; bh=6kW25pg6VPwO xN0PpF7KB3SJguMNccZ4U3jj4C23kcc=; b=RvCMm0hUqJXJjAewrYJKbI5g0PJV +tocvkBu2Zc4j6SLLej5nxckXdiYHauVvlaAXqkScod7TjaxH+l38QPjE/eLT3bW oL+ZCURrdooyFpgXhngeUzFz1ARDN0A8SzID/v+dNu/DN3aahCDxN4FFF+zayKZ5 LooRsm5sHFI2Lag= Received: from pb-smtp21.sea.icgroup.com (unknown [127.0.0.1]) by pb-smtp21.pobox.com (Postfix) with ESMTP id 23FB332D96; Sun, 7 Jul 2024 15:07:00 -0400 (EDT) (envelope-from nico@fluxnic.net) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed; d=fluxnic.net; h=from:to:cc:subject:date:message-id:in-reply-to:references:mime-version:content-type:content-transfer-encoding; s=2016-12.pbsmtp; bh=tp8lbijNKahXKUhHOOemSyS81f5Q5sXhy0yV3icmOLs=; b=cqswCqqi7ImjMCPCdUNnHAIenSp/Gl4+n049XGJJ0OlHr8klK3Y5FCxTL6LozKNEVcxNYqYB71wW5E3a7OLi3+qh5bebLv3S6bRMOJWlUwDBmNrMwD9dtGg+lGTB+hZ8xsE2Hn91uxdpzrbgCV+K5Vm3zkj2VggpF09VW/zQ5us= Received: from yoda.fluxnic.net (unknown [184.162.15.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pb-smtp21.pobox.com (Postfix) with ESMTPSA id 1869732D92; Sun, 7 Jul 2024 15:06:56 -0400 (EDT) (envelope-from nico@fluxnic.net) Received: from xanadu.lan (OpenWrt.lan [192.168.1.1]) by yoda.fluxnic.net (Postfix) with ESMTPSA id CB977D3B4E2; Sun, 7 Jul 2024 15:06:53 -0400 (EDT) From: Nicolas Pitre To: Andrew Morton , =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Cc: Nicolas Pitre , linux-kernel@vger.kernel.org Subject: [PATCH v3 1/2] mul_u64_u64_div_u64: make it precise always Date: Sun, 7 Jul 2024 15:05:19 -0400 Message-ID: <20240707190648.1982714-2-nico@fluxnic.net> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240707190648.1982714-1-nico@fluxnic.net> References: <20240707190648.1982714-1-nico@fluxnic.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Pobox-Relay-ID: 140FC1A4-3C94-11EF-ADB1-DFF1FEA446E2-78420484!pb-smtp21.pobox.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Nicolas Pitre 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 =3D 18446462598732840960 b =3D 18446462598732840960 c =3D 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. Signed-off-by: Nicolas Pitre Tested-by: Uwe Kleine-K=C3=B6nig Tested-by: Biju Das Reviewed-by: Uwe Kleine-K=C3=B6nig --- lib/math/div64.c | 108 ++++++++++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 43 deletions(-) diff --git a/lib/math/div64.c b/lib/math/div64.c index 191761b1b6..b7fc752463 100644 --- a/lib/math/div64.c +++ b/lib/math/div64.c @@ -186,55 +186,77 @@ EXPORT_SYMBOL(iter_div_u64_rem); #ifndef mul_u64_u64_div_u64 u64 mul_u64_u64_div_u64(u64 a, u64 b, u64 c) { - u64 res =3D 0, div, rem; - int shift; + if (ilog2(a) + ilog2(b) <=3D 62) + return div64_u64(a * b, c); =20 - /* can a * b overflow ? */ - if (ilog2(a) + ilog2(b) > 62) { - /* - * Note that the algorithm after the if block below might lose - * some precision and the result is more exact for b > a. So - * exchange a and b if a is bigger than b. - * - * For example with a =3D 43980465100800, b =3D 100000000, c =3D 1000000= 000 - * the below calculation doesn't modify b at all because div =3D=3D 0 - * and then shift becomes 45 + 26 - 62 =3D 9 and so the result - * becomes 4398035251080. However with a and b swapped the exact - * result is calculated (i.e. 4398046510080). - */ - if (a > b) - swap(a, b); +#if defined(__SIZEOF_INT128__) + + /* native 64x64=3D128 bits multiplication */ + u128 prod =3D (u128)a * b; + u64 n_lo =3D prod, n_hi =3D prod >> 64; + +#else + + /* perform a 64x64=3D128 bits multiplication manually */ + u32 a_lo =3D a, a_hi =3D a >> 32, b_lo =3D b, b_hi =3D b >> 32; + u64 x, y, z; + + x =3D (u64)a_lo * b_lo; + y =3D (u64)a_lo * b_hi + (u32)(x >> 32); + z =3D (u64)a_hi * b_hi + (u32)(y >> 32); + y =3D (u64)a_hi * b_lo + (u32)y; + z +=3D (u32)(y >> 32); + x =3D (y << 32) + (u32)x; + + u64 n_lo =3D x, n_hi =3D z; + +#endif + + int shift =3D __builtin_ctzll(c); =20 + /* try reducing the fraction in case the dividend becomes <=3D 64 bits */ + if ((n_hi >> shift) =3D=3D 0) { + u64 n =3D (n_lo >> shift) | (n_hi << (64 - shift)); + + return div64_u64(n, c >> shift); /* - * (b * a) / c is equal to - * - * (b / c) * a + - * (b % c) * a / c - * - * if nothing overflows. Can the 1st multiplication - * overflow? Yes, but we do not care: this can only - * happen if the end result can't fit in u64 anyway. - * - * So the code below does - * - * res =3D (b / c) * a; - * b =3D b % c; + * The remainder value if needed would be: + * res =3D div64_u64_rem(n, c >> shift, &rem); + * rem =3D (rem << shift) + (n_lo - (n << shift)); */ - div =3D div64_u64_rem(b, c, &rem); - res =3D div * a; - b =3D rem; - - shift =3D ilog2(a) + ilog2(b) - 62; - if (shift > 0) { - /* drop precision */ - b >>=3D shift; - c >>=3D shift; - if (!c) - return res; - } } =20 - return res + div64_u64(a * b, c); + if (n_hi >=3D c) { + /* overflow: result is unrepresentable in a u64 */ + return -1; + } + + /* Do the full 128 by 64 bits division */ + + shift =3D __builtin_clzll(c); + c <<=3D shift; + + int p =3D 64 + shift; + u64 res =3D 0; + bool carry; + + do { + carry =3D n_hi >> 63; + shift =3D carry ? 1 : __builtin_clzll(n_hi); + if (p < shift) + break; + p -=3D shift; + n_hi <<=3D shift; + n_hi |=3D n_lo >> (64 - shift); + n_lo <<=3D shift; + if (carry || (n_hi >=3D c)) { + n_hi -=3D c; + res |=3D 1ULL << p; + } + } while (n_hi); + /* The remainder value if needed would be n_hi << p */ + + return res; } EXPORT_SYMBOL(mul_u64_u64_div_u64); #endif --=20 2.45.2 From nobody Fri Dec 19 11:01:30 2025 Received: from pb-smtp2.pobox.com (pb-smtp2.pobox.com [64.147.108.71]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 10B262E85E for ; Sun, 7 Jul 2024 19:07:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=64.147.108.71 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720379226; cv=none; b=TXPRGQQ3k4hQIOZzJYnpLAcjP4MBWOawdkrmSJm3goXJiA4OaB93HXodv37iDZ8RF/CQRvIxUV0zsV5GhvkJ0ifkardScPi+k4TKGI+7rVT753llsUPYiPVQ16kvXlxk4BbJ3WN5rwTJRN08gQxkmaZZFYyHhR3WpTdAP/fgCD4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720379226; c=relaxed/simple; bh=y5E7OBngPfDkY3XfbPU8rxbUJdyujoY6VWRWe5uTCEA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eSfAf4oqBwdH1AUJIF0V8ikSoOgqEwdHQcrYJYKE/x/xRHkRnIiwQEpbB3/H9UIFXXeyro7t4kHMcc7oMW20UEKxsryd0zPdQe/5irbTEQi5kGbNLnjSAzyL8dWc+6VakgjPYecuPhofXbR+OPq7yUl4ytBQWHMrp5NM4Hi4S8o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=fluxnic.net; spf=pass smtp.mailfrom=fluxnic.net; dkim=pass (1024-bit key) header.d=pobox.com header.i=@pobox.com header.b=BY8BipP5; dkim=fail (1024-bit key) header.d=fluxnic.net header.i=@fluxnic.net header.b=Y3ipbB4V reason="signature verification failed"; arc=none smtp.client-ip=64.147.108.71 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=fluxnic.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=fluxnic.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=pobox.com header.i=@pobox.com header.b="BY8BipP5"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=fluxnic.net header.i=@fluxnic.net header.b="Y3ipbB4V" Received: from pb-smtp2.pobox.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id BF8351A0E3; Sun, 7 Jul 2024 15:06:55 -0400 (EDT) (envelope-from nico@fluxnic.net) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed; d=pobox.com; h=from:to:cc :subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; s=sasl; bh=y5E7OBngPfDkY3XfbPU8rxbUJ dyujoY6VWRWe5uTCEA=; b=BY8BipP5TRTQ70GdWG3xVEFfccYi+/8IGOV9Tm4ap 1KcD6fL9h2NuxdGb17eaijUVh9Lf/LO7DMUlpMrGDynD+elKcEW/cpN2bBvJkK7Y RFX51n4WBFA7S1Q5k7KR6DudCPKoUp9gn+vvlFbcMz+lP/3GPnntTVywpfdUCEDT wc= Received: from pb-smtp2.nyi.icgroup.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id B58091A0E2; Sun, 7 Jul 2024 15:06:55 -0400 (EDT) (envelope-from nico@fluxnic.net) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed; d=fluxnic.net; h=from:to:cc:subject:date:message-id:in-reply-to:references:mime-version:content-transfer-encoding; s=2016-12.pbsmtp; bh=tszzF1rafpYU6uyroSx0MMv1pkglcDvKtgmQW7oeGQ0=; b=Y3ipbB4V/o9XVKgMm7MFIIMn0MwuzClHi8jn8mBQhPvNJkQI6pxnruhuYND+PMPv95dck0/vZIym167cupxNRRRIBJktcLvNfSusNt/qIoAiScyfYcqfuGbjymI/VqL0qDW+iKdKV+e9wXjkDvRARnfm7qs8JZHczVD7oT0IV58= Received: from yoda.fluxnic.net (unknown [184.162.15.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pb-smtp2.pobox.com (Postfix) with ESMTPSA id 072851A0E1; Sun, 7 Jul 2024 15:06:55 -0400 (EDT) (envelope-from nico@fluxnic.net) Received: from xanadu.lan (OpenWrt.lan [192.168.1.1]) by yoda.fluxnic.net (Postfix) with ESMTPSA id E7006D3B4E3; Sun, 7 Jul 2024 15:06:53 -0400 (EDT) From: Nicolas Pitre To: Andrew Morton , =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Cc: Nicolas Pitre , linux-kernel@vger.kernel.org Subject: [PATCH v3 2/2] mul_u64_u64_div_u64: basic sanity test Date: Sun, 7 Jul 2024 15:05:20 -0400 Message-ID: <20240707190648.1982714-3-nico@fluxnic.net> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240707190648.1982714-1-nico@fluxnic.net> References: <20240707190648.1982714-1-nico@fluxnic.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Pobox-Relay-ID: 136C90EC-3C94-11EF-8CC2-965B910A682E-78420484!pb-smtp2.pobox.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Nicolas Pitre Verify that edge cases produce proper results, and some more. Signed-off-by: Nicolas Pitre --- lib/Kconfig.debug | 10 +++ lib/math/Makefile | 1 + lib/math/test_mul_u64_u64_div_u64.c | 98 +++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 lib/math/test_mul_u64_u64_div_u64.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 59b6765d86..cc570c6f34 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2278,6 +2278,16 @@ config TEST_DIV64 =20 If unsure, say N. =20 +config TEST_MULDIV64 + tristate "mul_u64_u64_div_u64() test" + depends on DEBUG_KERNEL || m + help + Enable this to turn on 'mul_u64_u64_div_u64()' function test. + This test is executed only once during system boot (so affects + only boot time), or at module load time. + + If unsure, say N. + config TEST_IOV_ITER tristate "Test iov_iter operation" if !KUNIT_ALL_TESTS depends on KUNIT diff --git a/lib/math/Makefile b/lib/math/Makefile index 91fcdb0c9e..981a26127e 100644 --- a/lib/math/Makefile +++ b/lib/math/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_PRIME_NUMBERS) +=3D prime_numbers.o obj-$(CONFIG_RATIONAL) +=3D rational.o =20 obj-$(CONFIG_TEST_DIV64) +=3D test_div64.o +obj-$(CONFIG_TEST_MULDIV64) +=3D test_mul_u64_u64_div_u64.o obj-$(CONFIG_RATIONAL_KUNIT_TEST) +=3D rational-test.o diff --git a/lib/math/test_mul_u64_u64_div_u64.c b/lib/math/test_mul_u64_u6= 4_div_u64.c new file mode 100644 index 0000000000..a25640d349 --- /dev/null +++ b/lib/math/test_mul_u64_u64_div_u64.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 BayLibre SAS + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include + +typedef struct { u64 a; u64 b; u64 c; u64 result; } test_params; + +static test_params test_values[] =3D { +/* this contains many edge values followed by a couple random values */ +{ 0xb, 0x7, 0x3, = 0x19 }, +{ 0xffff0000, 0xffff0000, 0xf, 0x1110eeef00= 000000 }, +{ 0xffffffff, 0xffffffff, 0x1, 0xfffffffe00= 000001 }, +{ 0xffffffff, 0xffffffff, 0x2, 0x7fffffff00= 000000 }, +{ 0x1ffffffff, 0xffffffff, 0x2, 0xfffffffe80= 000000 }, +{ 0x1ffffffff, 0xffffffff, 0x3, 0xaaaaaaa9aa= aaaaab }, +{ 0x1ffffffff, 0x1ffffffff, 0x4, 0xffffffff00= 000000 }, +{ 0xffff000000000000, 0xffff000000000000, 0xffff000000000001, 0xfffeffffff= ffffff }, +{ 0x3333333333333333, 0x3333333333333333, 0x5555555555555555, 0x1eb851eb85= 1eb851 }, +{ 0xffffffffffffffff, 0x2, 0x8000000000000000, = 0x3 }, +{ 0xffffffffffffffff, 0x2, 0xc000000000000000, = 0x2 }, +{ 0xffffffffffffffff, 0x4000000000000004, 0x8000000000000000, 0x8000000000= 000007 }, +{ 0xffffffffffffffff, 0x4000000000000001, 0x8000000000000000, 0x8000000000= 000001 }, +{ 0xffffffffffffffff, 0x8000000000000001, 0xffffffffffffffff, 0x8000000000= 000001 }, +{ 0xfffffffffffffffe, 0x8000000000000001, 0xffffffffffffffff, 0x8000000000= 000000 }, +{ 0xffffffffffffffff, 0x8000000000000001, 0xfffffffffffffffe, 0x8000000000= 000001 }, +{ 0xffffffffffffffff, 0x8000000000000001, 0xfffffffffffffffd, 0x8000000000= 000002 }, +{ 0x7fffffffffffffff, 0xffffffffffffffff, 0xc000000000000000, 0xaaaaaaaaaa= aaaaa8 }, +{ 0xffffffffffffffff, 0x7fffffffffffffff, 0xa000000000000000, 0xcccccccccc= ccccca }, +{ 0xffffffffffffffff, 0x7fffffffffffffff, 0x9000000000000000, 0xe38e38e38e= 38e38b }, +{ 0x7fffffffffffffff, 0x7fffffffffffffff, 0x5000000000000000, 0xcccccccccc= ccccc9 }, +{ 0xffffffffffffffff, 0xfffffffffffffffe, 0xffffffffffffffff, 0xffffffffff= fffffe }, +{ 0xe6102d256d7ea3ae, 0x70a77d0be4c31201, 0xd63ec35ab3220357, 0x78f8bf8cc8= 6c6e18 }, +{ 0xf53bae05cb86c6e1, 0x3847b32d2f8d32e0, 0xcfd4f55a647f403c, 0x42687f79d8= 998d35 }, +{ 0x9951c5498f941092, 0x1f8c8bfdf287a251, 0xa3c8dc5f81ea3fe2, 0x1d887cb259= 00091f }, +{ 0x374fee9daa1bb2bb, 0x0d0bfbff7b8ae3ef, 0xc169337bd42d5179, 0x03bb2dbaff= cbb961 }, +{ 0xeac0d03ac10eeaf0, 0x89be05dfa162ed9b, 0x92bb1679a41f0e4b, 0xdc5f5cc9e2= 70d216 }, +}; + +/* + * The above table can be verified with the following shell script: + * + * #!/bin/sh + * sed -ne 's/^{ \+\(.*\), \+\(.*\), \+\(.*\), \+\(.*\) },$/\1 \2 \3 \4/p'= \ + * lib/math/test_mul_u64_u64_div_u64.c | + * while read a b c r; do + * expected=3D$( printf "obase=3D16; ibase=3D16; %X * %X / %X\n" $a $b $= c | bc ) + * given=3D$( printf "%X\n" $r ) + * if [ "$expected" =3D "$given" ]; then + * echo "$a * $b / $c =3D $r OK" + * else + * echo "$a * $b / $c =3D $r is wrong" >&2 + * echo "should be equivalent to 0x$expected" >&2 + * exit 1 + * fi + * done + */ + +static int __init test_init(void) +{ + int i; + + pr_info("Starting mul_u64_u64_div_u64() test\n"); + + for (i =3D 0; i < ARRAY_SIZE(test_values); i++) { + u64 a =3D test_values[i].a; + u64 b =3D test_values[i].b; + u64 c =3D test_values[i].c; + u64 expected_result =3D test_values[i].result; + u64 result =3D mul_u64_u64_div_u64(a, b, c); + + if (result !=3D expected_result) { + pr_err("ERROR: 0x%016llx * 0x%016llx / 0x%016llx\n", a, b, c); + pr_err("ERROR: expected result: %016llx\n", expected_result); + pr_err("ERROR: obtained result: %016llx\n", result); + } + } + + pr_info("Completed mul_u64_u64_div_u64() test\n"); + return 0; +} + +static void __exit test_exit(void) +{ +} + +module_init(test_init); +module_exit(test_exit); + +MODULE_AUTHOR("Nicolas Pitre"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("mul_u64_u64_div_u64() test module"); --=20 2.45.2