Use qs22j for qsort
This commit is contained in:
parent
9f83abf50f
commit
3de35a78d4
8 changed files with 309 additions and 14 deletions
|
|
@ -1,3 +1,4 @@
|
|||
qs22j.c
|
||||
string.c
|
||||
d_main.c
|
||||
d_clisrv.c
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include "stun.h"
|
||||
#include "byteptr.h"
|
||||
|
||||
#include "qs22j.h"
|
||||
|
||||
//
|
||||
// NETWORKING
|
||||
//
|
||||
|
|
@ -1471,7 +1473,7 @@ void Command_Ping_f(void)
|
|||
else if (ms_width < 100) ms_width = 2;
|
||||
else ms_width = 3;
|
||||
|
||||
qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp);
|
||||
qs22j(pingv, pingc, sizeof (struct pingcell), &pingcellcmp);
|
||||
|
||||
for (i = 0; i < pingc; ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "hw_glob.h"
|
||||
#include "hw_batching.h"
|
||||
#include "../i_system.h"
|
||||
#include "../qs22j.h"
|
||||
|
||||
// The texture for the next polygon given to HWR_ProcessPolygon.
|
||||
// Set with HWR_SetCurrentTexture.
|
||||
|
|
@ -261,9 +262,9 @@ void HWR_RenderBatches(void)
|
|||
// sort polygons
|
||||
ps_hw_batchsorttime = I_GetPreciseTime();
|
||||
if (cv_glshaders.value && gl_shadersavailable)
|
||||
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
|
||||
qs22j(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
|
||||
else
|
||||
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
|
||||
qs22j(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
|
||||
ps_hw_batchsorttime = I_GetPreciseTime() - ps_hw_batchsorttime;
|
||||
// sort order
|
||||
// 1. shader
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "../doomstat.h"
|
||||
|
||||
#include "../qs22j.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hw_glob.h"
|
||||
#include "hw_light.h"
|
||||
|
|
@ -4712,7 +4714,7 @@ static void HWR_SortVisSprites(void)
|
|||
{
|
||||
gl_vsprorder[i] = HWR_GetVisSprite(i);
|
||||
}
|
||||
qsort(gl_vsprorder, gl_visspritecount, sizeof(gl_vissprite_t*), CompareVisSprites);
|
||||
qs22j(gl_vsprorder, gl_visspritecount, sizeof(gl_vissprite_t*), CompareVisSprites);
|
||||
}
|
||||
|
||||
// A drawnode is something that points to a 3D floor, 3D side, or masked
|
||||
|
|
@ -4932,7 +4934,7 @@ static void HWR_CreateDrawNodes(void)
|
|||
// p is the number of stuff to sort
|
||||
|
||||
// sort the list based on the value of the 'drawcount' member of the drawnodes.
|
||||
qsort(sortindex, p, sizeof(size_t), CompareDrawNodes);
|
||||
qs22j(sortindex, p, sizeof(size_t), CompareDrawNodes);
|
||||
|
||||
// an additional pass is needed to correct the order of consecutive planes in the list.
|
||||
// for each consecutive run of planes in the list, sort that run based on plane height and view height.
|
||||
|
|
@ -4951,7 +4953,7 @@ static void HWR_CreateDrawNodes(void)
|
|||
if (run_end > run_start)// if there are multiple consecutive planes, not just one
|
||||
{
|
||||
// consecutive run of planes found, now sort it
|
||||
qsort(sortindex + run_start, run_end - run_start + 1, sizeof(size_t), CompareDrawNodePlanes);
|
||||
qs22j(sortindex + run_start, run_end - run_start + 1, sizeof(size_t), CompareDrawNodePlanes);
|
||||
}
|
||||
run_start = run_end + 1;// continue looking for runs coming right after this one
|
||||
}
|
||||
|
|
|
|||
14
src/m_menu.c
14
src/m_menu.c
|
|
@ -94,6 +94,8 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
|||
#include "discord.h"
|
||||
#endif
|
||||
|
||||
#include "qs22j.h"
|
||||
|
||||
#define SKULLXOFF -32
|
||||
#define LINEHEIGHT 16
|
||||
#define STRINGHEIGHT 8
|
||||
|
|
@ -8753,22 +8755,22 @@ void M_SortServerList(void)
|
|||
switch(cv_serversort.value)
|
||||
{
|
||||
case 0: // Ping.
|
||||
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_time);
|
||||
qs22j(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_time);
|
||||
break;
|
||||
case 1: // Modified state.
|
||||
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_modified);
|
||||
qs22j(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_modified);
|
||||
break;
|
||||
case 2: // Most players.
|
||||
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer_reverse);
|
||||
qs22j(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer_reverse);
|
||||
break;
|
||||
case 3: // Least players.
|
||||
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer);
|
||||
qs22j(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer);
|
||||
break;
|
||||
case 4: // Max players.
|
||||
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_maxplayer_reverse);
|
||||
qs22j(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_maxplayer_reverse);
|
||||
break;
|
||||
case 5: // Gametype.
|
||||
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametypename);
|
||||
qs22j(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametypename);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
278
src/qs22j.c
Normal file
278
src/qs22j.c
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
// License: 0BSD
|
||||
//
|
||||
// Copyright 2022 Raymond Gardner
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "qs22j.h"
|
||||
|
||||
#define INSORTTHRESH 5 // if n < this use insertion sort
|
||||
// MUST be >= 2
|
||||
#define MIDTHRESH 20 // < this use middle as pivot
|
||||
#define MEDOF3THRESH 50 // < this use median-of-3 as pivot
|
||||
// larger subfiles use med-of-3-medians
|
||||
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
typedef int32_t WORD;
|
||||
typedef int64_t DWORD;
|
||||
typedef void *pref_typ;
|
||||
|
||||
// if no uintptr_t, use Bentley-McIlroy trick (undefined behavior)
|
||||
//#define ptr_to_int(p) (p-(char*)0)
|
||||
#define ptr_to_int(p) ((uintptr_t)(void *)p)
|
||||
|
||||
#define ASWAP(a, b, t) ((void)(t = a, a = b, b = t))
|
||||
|
||||
#define SWAP(a, b) if (swap_type) swapf(a, b, size);\
|
||||
else do {pref_typ t; ASWAP(*(pref_typ*)(a), *(pref_typ*)(b), t);} while (0)
|
||||
|
||||
#define COMP(a, b) ((*compar)((void *)(a), (void *)(b)))
|
||||
|
||||
static void swapbytes(void *a0, void *b0, size_t n)
|
||||
{
|
||||
char *a = a0, *b = b0, t;
|
||||
do {ASWAP(*a, *b, t); a++; b++;} while (--n);
|
||||
}
|
||||
|
||||
static void swapdword(void *a0, void *b0, size_t n)
|
||||
{
|
||||
DWORD *a = a0, *b = b0, t;
|
||||
ASWAP(*a, *b, t);
|
||||
(void)n;
|
||||
}
|
||||
|
||||
static void swapdwords(void *a0, void *b0, size_t n)
|
||||
{
|
||||
DWORD *a = a0, *b = b0, t;
|
||||
do {ASWAP(*a, *b, t); a++; b++;} while (n -= sizeof(DWORD));
|
||||
}
|
||||
|
||||
static void swapword(void *a0, void *b0, size_t n)
|
||||
{
|
||||
WORD *a = a0, *b = b0, t;
|
||||
ASWAP(*a, *b, t);
|
||||
(void)n;
|
||||
}
|
||||
|
||||
static void swapwords(void *a0, void *b0, size_t n)
|
||||
{
|
||||
WORD *a = a0, *b = b0, t;
|
||||
do {ASWAP(*a, *b, t); a++; b++;} while (n -= sizeof(WORD));
|
||||
}
|
||||
|
||||
typedef void (*swapf_typ)(void *, void *, size_t);
|
||||
|
||||
static char *med3(char *a, char *b, char *c, int (*compar)(const void *, const void *))
|
||||
{
|
||||
return COMP(a, b) < 0 ?
|
||||
(COMP(b, c) < 0 ? b : COMP(a, c) < 0 ? c : a) :
|
||||
(COMP(b, c) > 0 ? b : COMP(a, c) > 0 ? c : a);
|
||||
}
|
||||
|
||||
void qs22j(void *base, size_t nmemb, size_t size,
|
||||
int (*compar)(const void *, const void *))
|
||||
{
|
||||
char *stack[2*8*sizeof(size_t)], **sp = stack; // stack and stack pointer
|
||||
char *left = base; // set up char * base pointer
|
||||
char *limit = left + nmemb * size; // pointer past end of array
|
||||
char *i, *ii, *j, *jj; // scan pointers
|
||||
int ki = 0, kj = 0;
|
||||
int swap_type = 1;
|
||||
swapf_typ swapf, vecswapf;
|
||||
|
||||
vecswapf = swapf = swapbytes;
|
||||
if ((ptr_to_int(left) | size) % sizeof(WORD))
|
||||
{
|
||||
; // unaligned or not multple of WORD size; swap bytes
|
||||
}
|
||||
else if (size == sizeof(DWORD))
|
||||
{
|
||||
swapf = swapdword;
|
||||
vecswapf = swapdwords;
|
||||
if (size == sizeof(pref_typ))
|
||||
swap_type = 0;
|
||||
}
|
||||
else if (size == sizeof(WORD))
|
||||
{
|
||||
swapf = swapword;
|
||||
vecswapf = swapwords;
|
||||
if (size == sizeof(pref_typ))
|
||||
swap_type = 0;
|
||||
}
|
||||
else if ((size % sizeof(DWORD)) == 0)
|
||||
{
|
||||
swapf = vecswapf = swapdwords;
|
||||
}
|
||||
else if ((size % sizeof(WORD)) == 0)
|
||||
{
|
||||
swapf = vecswapf = swapwords;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
nmemb = (limit - left) / size;
|
||||
for (i = left + size; i < limit && COMP(i - size, i) <= 0; i += size)
|
||||
;
|
||||
|
||||
if (i == limit) // if already in order
|
||||
goto pop;
|
||||
|
||||
if (nmemb >= INSORTTHRESH) // otherwise use insertion sort
|
||||
{
|
||||
char *right = limit - size;
|
||||
// best so far? fewer compares, a few more swaps
|
||||
char *p = left + (nmemb / 2) * size;
|
||||
if (nmemb >= MIDTHRESH)
|
||||
{
|
||||
char *pleft = left + size;
|
||||
char *pright = right - size;
|
||||
|
||||
if (nmemb >= MEDOF3THRESH)
|
||||
{
|
||||
size_t k = (nmemb / 8) * size;
|
||||
pleft = med3(pleft, left + k, left + k * 2, compar);
|
||||
p = med3(p - k, p, p + k, compar);
|
||||
pright = med3(right - k * 2, right - k, pright, compar);
|
||||
}
|
||||
|
||||
p = med3(pleft, p, pright, compar);
|
||||
}
|
||||
|
||||
i = ii = left; // i scans left to right
|
||||
j = jj = right; // j scans right to left
|
||||
for (;;)
|
||||
{
|
||||
|
||||
while (i <= j)
|
||||
{
|
||||
if (i != p && ((ki = COMP(i, p)) >= 0))
|
||||
{
|
||||
if (ki)
|
||||
break;
|
||||
|
||||
if (ii == p)
|
||||
{
|
||||
p = i;
|
||||
}
|
||||
else if (i != ii)
|
||||
{
|
||||
SWAP(i, ii);
|
||||
}
|
||||
|
||||
ii += size;
|
||||
}
|
||||
i += size;
|
||||
}
|
||||
|
||||
while (i < j)
|
||||
{
|
||||
if (j != p && ((kj = COMP(j, p)) <= 0))
|
||||
{
|
||||
if (kj)
|
||||
break;
|
||||
|
||||
if (jj == p)
|
||||
{
|
||||
p = j;
|
||||
}
|
||||
else if (j != jj)
|
||||
{
|
||||
SWAP(j, jj);
|
||||
}
|
||||
|
||||
jj -= size;
|
||||
}
|
||||
j -= size;
|
||||
}
|
||||
|
||||
if (i >= j)
|
||||
break;
|
||||
|
||||
SWAP(i, j);
|
||||
i += size;
|
||||
j -= size;
|
||||
}
|
||||
|
||||
if (p < i)
|
||||
i -= size;
|
||||
|
||||
if (p != i)
|
||||
{
|
||||
SWAP(p, i);
|
||||
}
|
||||
|
||||
ptrdiff_t lessthan = i - ii;
|
||||
size_t k = min(lessthan, ii - left);
|
||||
|
||||
if (k)
|
||||
vecswapf(left, i - k, k);
|
||||
|
||||
ptrdiff_t morethan = jj - i;
|
||||
k = min(morethan, right - jj);
|
||||
|
||||
if (k)
|
||||
vecswapf(i + size, limit - k, k);
|
||||
|
||||
if (lessthan > morethan)
|
||||
{
|
||||
if (lessthan > 1)
|
||||
{
|
||||
sp[0] = left;
|
||||
sp[1] = left + lessthan;
|
||||
sp += 2; // increment stack pointer
|
||||
}
|
||||
|
||||
if (morethan <= 1)
|
||||
goto pop;
|
||||
|
||||
left = limit - morethan;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (morethan > 1)
|
||||
{
|
||||
sp[0] = limit - morethan;
|
||||
sp[1] = limit;
|
||||
sp += 2; // increment stack pointer
|
||||
}
|
||||
|
||||
if (lessthan <= 1)
|
||||
goto pop;
|
||||
|
||||
limit = left + lessthan;
|
||||
}
|
||||
|
||||
}
|
||||
else // else subfile is small, use insertion sort
|
||||
{
|
||||
for (i = left + size; i < limit; i += size)
|
||||
{
|
||||
for (j = i; j != left && COMP(j - size, j) > 0; j -= size)
|
||||
{
|
||||
SWAP(j - size, j);
|
||||
}
|
||||
}
|
||||
pop:
|
||||
if (sp != stack) // if any entries on stack
|
||||
{
|
||||
sp -= 2; // pop the left and limit
|
||||
left = sp[0];
|
||||
limit = sp[1];
|
||||
}
|
||||
else // else stack empty, done
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
7
src/qs22j.h
Normal file
7
src/qs22j.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef __QS22J__
|
||||
#define __QS22J__
|
||||
|
||||
void qs22j(void *base, size_t nmemb, size_t size,
|
||||
int (*compar)(const void *, const void *));
|
||||
|
||||
#endif
|
||||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include "k_terrain.h"
|
||||
|
||||
#include "qs22j.h"
|
||||
|
||||
seg_t *curline;
|
||||
side_t *sidedef;
|
||||
line_t *linedef;
|
||||
|
|
@ -759,7 +761,7 @@ void R_SortPolyObjects(subsector_t *sub)
|
|||
// 03/10/06: only bother if there are actually polys to sort
|
||||
if (numpolys >= 2)
|
||||
{
|
||||
qsort(po_ptrs, numpolys, sizeof(polyobj_t *),
|
||||
qs22j(po_ptrs, numpolys, sizeof(polyobj_t *),
|
||||
R_PolyobjCompare);
|
||||
}
|
||||
}
|
||||
|
|
@ -862,7 +864,7 @@ static void R_AddPolyObjects(subsector_t *sub)
|
|||
// render polyobjects
|
||||
for (i = 0; i < numpolys; ++i)
|
||||
{
|
||||
qsort(po_ptrs[i]->segs, po_ptrs[i]->segCount, sizeof(seg_t *), R_PolysegCompare);
|
||||
qs22j(po_ptrs[i]->segs, po_ptrs[i]->segCount, sizeof(seg_t *), R_PolysegCompare);
|
||||
for (j = 0; j < po_ptrs[i]->segCount; ++j)
|
||||
R_AddLine(po_ptrs[i]->segs[j]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue