File raptor2-qsort_r.patch of Package mingw64-raptor2

--- raptor2-2.0.16/src/raptor_internal.h	2026-03-10 09:16:50.603870423 +0100
+++ raptor2-2.0.16/src/raptor_internal.h	2026-03-10 09:33:30.675344273 +0100
@@ -182,11 +182,15 @@
 #define PRAGMA_IGNORE_WARNING_LONG_LONG_START \
   _Pragma ("GCC diagnostic push") \
   _Pragma ("GCC diagnostic ignored \"-Wlong-long\"")
+#define PRAGMA_IGNORE_WARNING_REDUNDANT_DECLS_START \
+  _Pragma ("GCC diagnostic push") \
+  _Pragma ("GCC diagnostic ignored \"-Wredundant-decls\"")
 #define PRAGMA_IGNORE_WARNING_END \
   _Pragma ("GCC diagnostic pop")
 #else
 #define PRAGMA_IGNORE_WARNING_FORMAT_NONLITERAL_START
 #define PRAGMA_IGNORE_WARNING_LONG_LONG_STAR
+#define PRAGMA_IGNORE_WARNING_REDUNDANT_DECLS_START
 #define PRAGMA_IGNORE_WARNING_END
 #endif
 
--- raptor2-2.0.16/src/sort_r.h	2026-03-10 09:16:50.604533989 +0100
+++ raptor2-2.0.16/src/sort_r.h	2026-03-10 09:35:12.729863571 +0100
@@ -2,9 +2,11 @@
 #ifndef SORT_R_H_
 #define SORT_R_H_
 
-#include <stdlib.h>
+#include <stdlib.h> /* qsort_r(), qsort_s() */
+#include <string.h> /* needed for memcpy() */
 
 /*
+
 sort_r function to be exported.
 
 Parameters:
@@ -17,38 +19,205 @@
 void sort_r(void *base, size_t nel, size_t width,
             int (*compar)(const void *_a, const void *_b, void *_arg),
             void *arg);
+
 */
 
+#define _SORT_R_INLINE inline
+
 #if (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \
-     defined __FreeBSD__ || defined __BSD__ || defined __bsdi__ || \
-     defined OpenBSD3_1 || defined OpenBSD3_9 || defined __OpenBSD__ || \
-     defined __NetBSD__ || \
-     defined __DragonFly__ || \
-     defined AMIGA)
+     (defined __FreeBSD__ && !defined(qsort_r)) || defined __DragonFly__)
 #  define _SORT_R_BSD
-#elif (defined _GNU_SOURCE || defined __gnu_hurd__ || defined __GNU__ || \
-       defined __linux__ || defined __MINGW32__ || defined __GLIBC__ || \
-       defined __CYGWIN__)
+#elif (defined __GLIBC__ || (defined (__FreeBSD__) && defined(qsort_r)))
 #  define _SORT_R_LINUX
-#elif (defined _WIN32 || defined _WIN64 || defined __WINDOWS__)
+#elif (defined _WIN32 || defined _WIN64 || defined __WINDOWS__ || \
+       defined __MINGW32__ || defined __MINGW64__)
 #  define _SORT_R_WINDOWS
+#  undef _SORT_R_INLINE
+#  define _SORT_R_INLINE __inline
 #else
-#  error Cannot detect operating system
+  /* Using our own recursive quicksort sort_r_simple() */
 #endif
 
 #if (defined NESTED_QSORT && NESTED_QSORT == 0)
 #  undef NESTED_QSORT
-#elif (!defined NESTED_QSORT && \
-       defined __GLIBC__ && __GLIBC__ == 2 && __GLIBC_MINOR__ < 8)
-/* no qsort_r in glibc before 2.8 */
-#  define NESTED_QSORT
 #endif
 
+#define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp))
+
+/* swap a and b */
+/* a and b must not be equal! */
+static _SORT_R_INLINE void sort_r_swap(char *__restrict a, char *__restrict b,
+                                       size_t w)
+{
+  char tmp, *end = a+w;
+  for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); }
+}
+
+/* swap a, b iff a>b */
+/* a and b must not be equal! */
+/* __restrict is same as restrict but better support on old machines */
+static _SORT_R_INLINE int sort_r_cmpswap(char *__restrict a,
+                                         char *__restrict b, size_t w,
+                                         int (*compar)(const void *_a,
+                                                       const void *_b,
+                                                       void *_arg),
+                                         void *arg)
+{
+  if(compar(a, b, arg) > 0) {
+    sort_r_swap(a, b, w);
+    return 1;
+  }
+  return 0;
+}
+
+/*
+Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr,
+with the smallest swap so that the blocks are in the opposite order. Blocks may
+be internally re-ordered e.g.
+
+  12345ab  ->   ab34512
+  123abc   ->   abc123
+  12abcde  ->   deabc12
+*/
+static _SORT_R_INLINE void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)
+{
+  if(na > 0 && nb > 0) {
+    if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }
+    else { sort_r_swap(ptr, ptr+nb, na); }
+  }
+}
+
+/* Implement recursive quicksort ourselves */
+/* Note: quicksort is not stable, equivalent values may be swapped */
+static _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w,
+                                         int (*compar)(const void *_a,
+                                                       const void *_b,
+                                                       void *_arg),
+                                         void *arg)
+{
+  char *b = (char *)base, *end = b + nel*w;
+
+  /* for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
+  printf("\n"); */
+
+  if(nel < 10) {
+    /* Insertion sort for arbitrarily small inputs */
+    char *pi, *pj;
+    for(pi = b+w; pi < end; pi += w) {
+      for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}
+    }
+  }
+  else
+  {
+    /* nel > 6; Quicksort */
+
+    int cmp;
+    char *pl, *ple, *pr, *pre, *pivot;
+    char *last = b+w*(nel-1), *tmp;
+
+    /*
+    Use median of second, middle and second-last items as pivot.
+    First and last may have been swapped with pivot and therefore be extreme
+    */
+    char *l[3];
+    l[0] = b + w;
+    l[1] = b+w*(nel/2);
+    l[2] = last - w;
+
+    /* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */
+
+    if(compar(l[0],l[1],arg) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
+    if(compar(l[1],l[2],arg) > 0) {
+      SORT_R_SWAP(l[1], l[2], tmp);
+      if(compar(l[0],l[1],arg) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
+    }
+
+    /* swap mid value (l[1]), and last element to put pivot as last element */
+    if(l[1] != last) { sort_r_swap(l[1], last, w); }
+
+    /*
+    pl is the next item on the left to be compared to the pivot
+    pr is the last item on the right that was compared to the pivot
+    ple is the left position to put the next item that equals the pivot
+    ple is the last right position where we put an item that equals the pivot
+
+                                           v- end (beyond the array)
+      EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.
+      ^- b  ^- ple  ^- pl   ^- pr  ^- pre ^- last (where the pivot is)
+
+    Pivot comparison key:
+      E = equal, L = less than, u = unknown, G = greater than, E = equal
+    */
+    pivot = last;
+    ple = pl = b;
+    pre = pr = last;
+
+    /*
+    Strategy:
+    Loop into the list from the left and right at the same time to find:
+    - an item on the left that is greater than the pivot
+    - an item on the right that is less than the pivot
+    Once found, they are swapped and the loop continues.
+    Meanwhile items that are equal to the pivot are moved to the edges of the
+    array.
+    */
+    while(pl < pr) {
+      /* Move left hand items which are equal to the pivot to the far left.
+         break when we find an item that is greater than the pivot */
+      for(; pl < pr; pl += w) {
+        cmp = compar(pl, pivot, arg);
+        if(cmp > 0) { break; }
+        else if(cmp == 0) {
+          if(ple < pl) { sort_r_swap(ple, pl, w); }
+          ple += w;
+        }
+      }
+      /* break if last batch of left hand items were equal to pivot */
+      if(pl >= pr) { break; }
+      /* Move right hand items which are equal to the pivot to the far right.
+         break when we find an item that is less than the pivot */
+      for(; pl < pr; ) {
+        pr -= w; /* Move right pointer onto an unprocessed item */
+        cmp = compar(pr, pivot, arg);
+        if(cmp == 0) {
+          pre -= w;
+          if(pr < pre) { sort_r_swap(pr, pre, w); }
+        }
+        else if(cmp < 0) {
+          if(pl < pr) { sort_r_swap(pl, pr, w); }
+          pl += w;
+          break;
+        }
+      }
+    }
+
+    pl = pr; /* pr may have gone below pl */
+
+    /*
+    Now we need to go from: EEELLLGGGGEEEE
+                        to: LLLEEEEEEEGGGG
+
+    Pivot comparison key:
+      E = equal, L = less than, u = unknown, G = greater than, E = equal
+    */
+    sort_r_swap_blocks(b, ple-b, pl-ple);
+    sort_r_swap_blocks(pr, pre-pr, end-pre);
+
+    /*for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
+    printf("\n");*/
+
+    sort_r_simple(b, (pl-ple)/w, w, compar, arg);
+    sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, arg);
+  }
+}
+
 
 #if defined NESTED_QSORT
 
-  static inline void sort_r(void *base, size_t nel, size_t width,
-                            int (*compar)(const void *_a, const void *_b, void *aarg),
+  static _SORT_R_INLINE void sort_r(void *base, size_t nel, size_t width,
+                                    int (*compar)(const void *_a,
+                                                  const void *_b,
+                                                  void *aarg),
                             void *arg)
   {
     int nested_cmp(const void *a, const void *b)
@@ -62,11 +231,19 @@
 #else /* !NESTED_QSORT */
 
   /* Declare structs and functions */
+
   #if defined _SORT_R_BSD
 
-    /* BSD requires argument swap */
+    /* Ensure qsort_r is defined */
     extern void qsort_r(void *base, size_t nel, size_t width, void *thunk,
-                        int (*compar)(void *_thunk, const void *_a, const void *_b));
+                        int (*compar)(void *_thunk,
+                                      const void *_a, const void *_b));
+
+  #endif
+
+  #if defined _SORT_R_BSD || defined _SORT_R_WINDOWS
+
+    /* BSD (qsort_r), Windows (qsort_s) require argument swap */
 
     struct sort_r_data
     {
@@ -74,16 +251,19 @@
       int (*compar)(const void *_a, const void *_b, void *_arg);
     };
 
-    static inline int sort_r_arg_swap(void *s, const void *a, const void *b)
+    static _SORT_R_INLINE int sort_r_arg_swap(void *s,
+                                              const void *a, const void *b)
     {
       struct sort_r_data *ss = (struct sort_r_data*)s;
       return (ss->compar)(a, b, ss->arg);
     }
 
-  #elif defined _SORT_R_LINUX
+  #endif
+
+  #if defined _SORT_R_LINUX
 
     typedef int(* __compar_d_fn_t)(const void *, const void *, void *);
-    extern void qsort_r(void *base, size_t nel, size_t width,
+    extern void (qsort_r)(void *base, size_t nel, size_t width,
                         __compar_d_fn_t __compar, void *arg)
       __attribute__((nonnull (1, 4)));
 
@@ -91,14 +271,24 @@
 
   /* implementation */
 
-  static inline void sort_r(void *base, size_t nel, size_t width,
-                            int (*compar)(const void *_a, const void *_b, void *_arg),
+  static _SORT_R_INLINE void sort_r(void *base, size_t nel, size_t width,
+                                    int (*compar)(const void *_a,
+                                                  const void *_b, void *_arg),
                             void *arg)
   {
     #if defined _SORT_R_LINUX
 
+      #if defined __GLIBC__ && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8))
+
+        /* no qsort_r in glibc before 2.8, need to use nested qsort */
+        sort_r_simple(base, nel, width, compar, arg);
+
+      #else
+
       qsort_r(base, nel, width, compar, arg);
 
+      #endif
+
     #elif defined _SORT_R_BSD
 
       struct sort_r_data tmp;
@@ -106,18 +296,24 @@
       tmp.compar = compar;
       qsort_r(base, nel, width, &tmp, sort_r_arg_swap);
 
-    #else /* defined _SORT_R_WINDOWS */
+    #elif defined _SORT_R_WINDOWS
 
       struct sort_r_data tmp;
       tmp.arg = arg;
       tmp.compar = compar;
       qsort_s(base, nel, width, sort_r_arg_swap, &tmp);
 
+    #else
+
+      /* Fall back to our own quicksort implementation */
+      sort_r_simple(base, nel, width, compar, arg);
+
     #endif
   }
 
 #endif /* !NESTED_QSORT */
 
+#undef _SORT_R_INLINE
 #undef _SORT_R_WINDOWS
 #undef _SORT_R_LINUX
 #undef _SORT_R_BSD
openSUSE Build Service is sponsored by