From c7e912f36f193b299a42c6e98dc31a78d9957395 Mon Sep 17 00:00:00 2001
From: Mats Kindahl <mats@timescale.com>
Date: Fri, 9 Feb 2024 21:24:42 +0100
Subject: Add integer comparison functions

Introduce functions pg_cmp_xyz() that will standardize integer comparison
for implementing comparison function for qsort(). The functions will
returns negative, 0, or positive integer without risking overflow as a
result of subtracting the two integers, which is otherwise a common
pattern for implementing this.

For integer sizes less than sizeof(int) we can use normal subtraction,
which is faster, but for integers with size greater than or equal to
sizeof(int) we need to handle this differently.
---
 src/include/common/int.h | 55 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/src/include/common/int.h b/src/include/common/int.h
index fedf7b3999..03afc04b2e 100644
--- a/src/include/common/int.h
+++ b/src/include/common/int.h
@@ -1,7 +1,8 @@
 /*-------------------------------------------------------------------------
  *
  * int.h
- *	  Routines to perform integer math, while checking for overflows.
+ *	  Routines to perform signed and unsigned integer arithmetics, including
+ *	  comparisons, in an overflow-safe way.
  *
  * The routines in this file are intended to be well defined C, without
  * relying on compiler flags like -fwrapv.
@@ -438,4 +439,56 @@ pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
 #endif
 }
 
+/*------------------------------------------------------------------------
+ * Comparison routines for integers.
+ *
+ * These routines are used to implement comparison functions for, e.g.,
+ * qsort(). They are designed to be efficient and not risk overflows in
+ * internal computations that could cause strange results, such as INT_MIN >
+ * INT_MAX if you just return "lhs - rhs".
+ *------------------------------------------------------------------------
+ */
+
+static inline int
+pg_cmp_s16(int16 a, int16 b)
+{
+	return (int32)a - (int32)b;
+}
+
+static inline int
+pg_cmp_u16(uint16 a, uint16 b)
+{
+	return (int32)a - (int32)b;
+}
+
+static inline int
+pg_cmp_s32(int32 a, int32 b)
+{
+	return (a > b) - (a < b);	/* Comparison operators return int 0 or 1 */
+}
+
+static inline int
+pg_cmp_u32(uint32 a, uint32 b)
+{
+	return (a > b) - (a < b);	/* Comparison operators return int 0 or 1 */
+}
+
+static inline int
+pg_cmp_s64(int64 a, int64 b)
+{
+	return (a > b) - (a < b);	/* Comparison operators return int 0 or 1 */
+}
+
+static inline int
+pg_cmp_u64(uint64 a, uint64 b)
+{
+	return (a > b) - (a < b);	/* Comparison operators return int 0 or 1 */
+}
+
+static inline int
+pg_cmp_size(size_t a, size_t b)
+{
+	return (a > b) - (a < b);	/* Comparison operators return int 0 or 1 */
+}
+
 #endif							/* COMMON_INT_H */
-- 
2.34.1

