git: 743d4b7cc5e2 - main - Fix the logic which determines if the destination Q variable can represent the source Q variable's value with full accuracy.

From: Lawrence Stewart <lstewart_at_FreeBSD.org>
Date: Tue, 02 Apr 2024 07:24:17 UTC
The branch main has been updated by lstewart:

URL: https://cgit.FreeBSD.org/src/commit/?id=743d4b7cc5e217a2120b3b5d4d1b284e1e5b7ea2

commit 743d4b7cc5e217a2120b3b5d4d1b284e1e5b7ea2
Author:     Lawrence Stewart <lstewart@FreeBSD.org>
AuthorDate: 2024-04-02 05:07:04 +0000
Commit:     Lawrence Stewart <lstewart@FreeBSD.org>
CommitDate: 2024-04-02 06:16:00 +0000

    Fix the logic which determines if the destination Q variable can represent the source Q variable's value with full accuracy.
    
    The new logic is mostly self explanatory except for the value fit checks.
    
    If b has fewer integer bits than a, 0 == (Q_GIABSVAL(a) & (~Q_TC(a, 0) << Q_NIBITS(b))) is checking that a's integer value does not have high-order bits set above what b is capable of storing.
    
    If b has fewer fractional bits than a, 0 == (Q_GFABSVAL(a) & ~(~Q_TC(a, 0) << (Q_NFBITS(a) - Q_NFBITS(b))))) is checking that a's fractional value does not have low-order bits set below what b is capable of storing.
    
    Obtained from:  Netflix, Inc.
    MFC afer:       1 week
---
 sys/sys/qmath.h | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/sys/sys/qmath.h b/sys/sys/qmath.h
index fa5acdb985be..bfaad75e77ee 100644
--- a/sys/sys/qmath.h
+++ b/sys/sys/qmath.h
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2018 Netflix, Inc.
+ * Copyright (c) 2018-2024 Netflix, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -378,15 +378,18 @@ typedef	u64q_t		umaxq_t;
 #define	Q_QMINQ(a, b)	(Q_LT(a, b) ? (a) : (b))
 
 /*
- * Test if 'a' can be represented by 'b' with full accuracy (T) or not (F).
- * The type casting has to be done to a's type so that any truncation caused by
- * the casts will not affect the logic.
+ * Test if 'a' can be represented by 'b' with full accuracy (0) or not
+ * (EOVERFLOW). If 'b' has fewer integer and/or fractional bits than 'a',
+ * the integer and fractional values stored in 'a' must fit in the available
+ * number of integer and fractional bits in 'b'.
  */
-#define	Q_QCANREPQ(a, b) \
-    ((((Q_LTZ(a) && Q_SIGNED(b)) || !Q_LTZ(a)) && \
-    Q_GIABSVAL(a) <= Q_TC(a, Q_IMAXVAL(b)) && \
-    Q_GFABSVAL(a) <= Q_TC(a, Q_FMAXVAL(b))) ? \
-    0 : EOVERFLOW)
+#define	Q_QCANREPQ(a, b) (( \
+    (!Q_LTZ(a) || Q_SIGNED(b)) \
+ && (   Q_NIBITS(a) <= Q_NIBITS(b) \
+     || 0 == (Q_GIABSVAL(a) & (~Q_TC(a, 0) << Q_NIBITS(b)))) \
+ && (   Q_NFBITS(a) <= Q_NFBITS(b) \
+     || 0 == (Q_GFABSVAL(a) & ~(~Q_TC(a, 0) << (Q_NFBITS(a) - Q_NFBITS(b))))) \
+    ) ? 0 : EOVERFLOW)
 
 /* Test if raw integer value 'i' can be represented by 'q' (T) or not (F). */
 #define	Q_QCANREPI(q, i) \