Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
mpim-sw
cdo
Commits
b39a9f55
Commit
b39a9f55
authored
Aug 04, 2015
by
Uwe Schulzweida
Browse files
kdtreelib: replaced qsortR by libc:qsort
parent
009fe711
Changes
7
Hide whitespace changes
Inline
Side-by-side
.gitattributes
View file @
b39a9f55
...
...
@@ -591,7 +591,6 @@ src/kdtreelib/kdtree_spherical.c -text
src/kdtreelib/pmergesort.c -text
src/kdtreelib/pqueue.c -text
src/kdtreelib/pqueue.h -text
src/kdtreelib/qsort.c -text
src/kvlist.c -text
src/kvlist.h -text
src/list.c -text
...
...
src/Makefile.am
View file @
b39a9f55
...
...
@@ -141,8 +141,7 @@ libcdo_la_SOURCES += \
kdtreelib/kdtree_spherical.c
\
kdtreelib/pmergesort.c
\
kdtreelib/pqueue.c
\
kdtreelib/pqueue.h
\
kdtreelib/qsort.c
kdtreelib/pqueue.h
libcdo_la_SOURCES
+=
\
clipping/clipping.c
\
clipping/clipping.h
\
...
...
src/Makefile.in
View file @
b39a9f55
...
...
@@ -164,8 +164,8 @@ am_libcdo_la_OBJECTS = libcdo_la-cdo_pthread.lo libcdo_la-cdo_vlist.lo \
kdtreelib/libcdo_la-kdtree_common.lo \
kdtreelib/libcdo_la-kdtree_spherical.lo \
kdtreelib/libcdo_la-pmergesort.lo \
kdtreelib/libcdo_la-pqueue.lo
kdtreelib
/libcdo_la-
qsort
.lo \
clipping/libcdo_la-clipping.lo
clipping/libcdo_la-area.lo \
kdtreelib/libcdo_la-pqueue.lo
clipping
/libcdo_la-
clipping
.lo \
clipping/libcdo_la-area.lo \
clipping/libcdo_la-ensure_array_size.lo \
clipping/libcdo_la-grid_cell.lo \
clipping/libcdo_la-intersection.lo clipping/libcdo_la-utils.lo
...
...
@@ -605,8 +605,8 @@ libcdo_la_SOURCES = cdo_int.h compare.h cdo_pthread.c cdo_vlist.c \
util.h zaxis.c kdtreelib/kdtree.h kdtreelib/kdtree_cartesian.c \
kdtreelib/kdtree_common.c kdtreelib/kdtree_spherical.c \
kdtreelib/pmergesort.c kdtreelib/pqueue.c kdtreelib/pqueue.h \
kdtreelib/qsort.c
clipping/clipping.c clipping/clipping.h \
clipping/area.c
clipping/area.h clipping/ensure_array_size.c \
clipping/clipping.c clipping/clipping.h
clipping/area.c
\
clipping/area.h clipping/ensure_array_size.c \
clipping/ensure_array_size.h clipping/geometry.h \
clipping/grid.h clipping/points.h clipping/dep_list.h \
clipping/grid_cell.c clipping/grid_cell.h \
...
...
@@ -739,8 +739,6 @@ kdtreelib/libcdo_la-pmergesort.lo: kdtreelib/$(am__dirstamp) \
kdtreelib/$(DEPDIR)/$(am__dirstamp)
kdtreelib/libcdo_la-pqueue.lo: kdtreelib/$(am__dirstamp) \
kdtreelib/$(DEPDIR)/$(am__dirstamp)
kdtreelib/libcdo_la-qsort.lo: kdtreelib/$(am__dirstamp) \
kdtreelib/$(DEPDIR)/$(am__dirstamp)
clipping/$(am__dirstamp):
@$(MKDIR_P) clipping
@: > clipping/$(am__dirstamp)
...
...
@@ -1120,7 +1118,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@kdtreelib/$(DEPDIR)/libcdo_la-kdtree_spherical.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@kdtreelib/$(DEPDIR)/libcdo_la-pmergesort.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@kdtreelib/$(DEPDIR)/libcdo_la-pqueue.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@kdtreelib/$(DEPDIR)/libcdo_la-qsort.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
...
...
@@ -1734,13 +1731,6 @@ kdtreelib/libcdo_la-pqueue.lo: kdtreelib/pqueue.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o kdtreelib/libcdo_la-pqueue.lo `test -f 'kdtreelib/pqueue.c' || echo '$(srcdir)/'`kdtreelib/pqueue.c
kdtreelib/libcdo_la-qsort.lo: kdtreelib/qsort.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT kdtreelib/libcdo_la-qsort.lo -MD -MP -MF kdtreelib/$(DEPDIR)/libcdo_la-qsort.Tpo -c -o kdtreelib/libcdo_la-qsort.lo `test -f 'kdtreelib/qsort.c' || echo '$(srcdir)/'`kdtreelib/qsort.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) kdtreelib/$(DEPDIR)/libcdo_la-qsort.Tpo kdtreelib/$(DEPDIR)/libcdo_la-qsort.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kdtreelib/qsort.c' object='kdtreelib/libcdo_la-qsort.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o kdtreelib/libcdo_la-qsort.lo `test -f 'kdtreelib/qsort.c' || echo '$(srcdir)/'`kdtreelib/qsort.c
clipping/libcdo_la-clipping.lo: clipping/clipping.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clipping/libcdo_la-clipping.lo -MD -MP -MF clipping/$(DEPDIR)/libcdo_la-clipping.Tpo -c -o clipping/libcdo_la-clipping.lo `test -f 'clipping/clipping.c' || echo '$(srcdir)/'`clipping/clipping.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) clipping/$(DEPDIR)/libcdo_la-clipping.Tpo clipping/$(DEPDIR)/libcdo_la-clipping.Plo
...
...
src/kdtreelib/kdtree.h
View file @
b39a9f55
...
...
@@ -10,6 +10,7 @@
changed *min to min[KD_MAX_DIM]
changed *max to max[KD_MAX_DIM]
_compPoints: compare index if points[axis] are equal
replace qsortR by libc:qsort (speedup 25%)
*/
#ifndef _KDTREE_H_
#define _KDTREE_H_
...
...
src/kdtreelib/kdtree_common.c
View file @
b39a9f55
...
...
@@ -8,8 +8,8 @@
extern
int
pmergesort
(
void
*
base
,
size_t
nmemb
,
size_t
size
,
int
(
*
compar
)
(
const
void
*
,
const
void
*
,
int
axis
),
int
axis
,
int
max_threads
);
int
(
*
compar
)
(
const
void
*
,
const
void
*
),
int
max_threads
);
/* ********************************************************************
...
...
@@ -86,23 +86,7 @@ kd_printTree(struct kdNode *node)
Functions for building and destroying trees
******************************************************************** */
static
int
_compPoints
(
const
void
*
p1
,
const
void
*
p2
,
int
axis
)
{
struct
kd_point
*
a
=
(
struct
kd_point
*
)
p1
;
struct
kd_point
*
b
=
(
struct
kd_point
*
)
p2
;
if
(
a
->
point
[
axis
]
>
b
->
point
[
axis
])
return
1
;
else
if
(
a
->
point
[
axis
]
<
b
->
point
[
axis
])
return
-
1
;
else
{
if
(
a
->
index
>
b
->
index
)
return
1
;
else
if
(
a
->
index
<
b
->
index
)
return
-
1
;
return
0
;
}
}
/*
static
int
_compPoints0
(
const
void
*
p1
,
const
void
*
p2
)
{
...
...
@@ -153,7 +137,7 @@ _compPoints2(const void *p1, const void *p2)
return
0
;
}
}
*/
void
*
kd_doBuildTree
(
void
*
threadarg
)
{
...
...
@@ -194,16 +178,12 @@ kd_doBuildTree(void *threadarg)
* If this iteration is allowed to start more threads, we first
* use them to parallelize the sorting
*/
/*
if ( max_threads == 1 )
{
if ( sortaxis == 0 ) qsort(points, nPoints, sizeof(struct kd_point), _compPoints0);
else if ( sortaxis == 1 ) qsort(points, nPoints, sizeof(struct kd_point), _compPoints1);
else if ( sortaxis == 2 ) qsort(points, nPoints, sizeof(struct kd_point), _compPoints2);
}
else
*/
pmergesort
(
points
,
nPoints
,
sizeof
(
struct
kd_point
),
_compPoints
,
sortaxis
,
max_threads
);
int
(
*
qcomp
)
(
const
void
*
,
const
void
*
);
if
(
sortaxis
==
0
)
qcomp
=
_compPoints0
;
else
if
(
sortaxis
==
1
)
qcomp
=
_compPoints1
;
else
if
(
sortaxis
==
2
)
qcomp
=
_compPoints2
;
pmergesort
(
points
,
nPoints
,
sizeof
(
struct
kd_point
),
qcomp
,
max_threads
);
pivot
=
nPoints
/
2
;
if
((
node
=
kd_allocNode
(
points
,
pivot
,
min
,
max
,
sortaxis
,
dim
))
==
NULL
)
return
NULL
;
...
...
src/kdtreelib/pmergesort.c
View file @
b39a9f55
...
...
@@ -10,30 +10,25 @@ typedef struct param_t {
size_t
first
;
size_t
nmemb
;
size_t
size
;
int
(
*
cmp
)
(
const
void
*
,
const
void
*
,
int
axis
);
int
axis
;
int
(
*
cmp
)
(
const
void
*
,
const
void
*
);
int
max_threads
;
}
param_t
;
extern
void
qsortR
(
const
void
*
base0
,
size_t
n
,
size_t
size
,
int
(
*
compar
)
(
const
void
*
,
const
void
*
,
int
axis
),
int
axis
);
void
pm_buildparams
(
struct
param_t
*
p
,
void
*
a
,
void
*
b
,
size_t
first
,
size_t
nmemb
,
size_t
size
,
int
(
*
cmp
)
(
const
void
*
,
const
void
*
,
int
),
int
axis
,
int
max_threads
);
int
(
*
cmp
)
(
const
void
*
,
const
void
*
),
int
max_threads
);
int
pmergesort
(
void
*
base
,
size_t
nmemb
,
size_t
size
,
int
(
*
compar
)
(
const
void
*
,
const
void
*
,
int
),
int
axis
,
int
max_threads
);
int
(
*
compar
)
(
const
void
*
,
const
void
*
),
int
max_threads
);
void
*
mergesort_t
(
void
*
args
);
int
pmergesort
(
void
*
base
,
size_t
nmemb
,
size_t
size
,
int
(
*
compar
)
(
const
void
*
,
const
void
*
,
int
),
int
axis
,
int
max_threads
)
int
(
*
compar
)
(
const
void
*
,
const
void
*
),
int
max_threads
)
{
void
*
tmp
;
param_t
args
;
...
...
@@ -48,7 +43,6 @@ pmergesort(void *base, size_t nmemb, size_t size,
args
.
nmemb
=
nmemb
;
args
.
size
=
size
;
args
.
cmp
=
compar
;
args
.
axis
=
axis
;
args
.
max_threads
=
max_threads
;
mergesort_t
(
&
args
);
...
...
@@ -60,8 +54,8 @@ pmergesort(void *base, size_t nmemb, size_t size,
void
pm_buildparams
(
struct
param_t
*
p
,
void
*
a
,
void
*
b
,
size_t
first
,
size_t
nmemb
,
size_t
size
,
int
(
*
cmp
)
(
const
void
*
,
const
void
*
,
int
),
int
axis
,
int
max_threads
)
int
(
*
cmp
)
(
const
void
*
,
const
void
*
),
int
max_threads
)
{
p
->
a
=
a
;
...
...
@@ -70,7 +64,6 @@ pm_buildparams(struct param_t *p, void *a, void *b, size_t first,
p
->
nmemb
=
nmemb
;
p
->
size
=
size
;
p
->
cmp
=
cmp
;
p
->
axis
=
axis
;
p
->
max_threads
=
max_threads
;
}
...
...
@@ -88,13 +81,13 @@ mergesort_t(void *args)
* Reached maximum number of threads allocated to this
* branch. Proceed with sequential sort of this chunk.
*/
qsort
R
(
mya
->
a
+
mya
->
first
*
mya
->
size
,
mya
->
nmemb
,
mya
->
size
,
mya
->
cmp
,
mya
->
axis
);
qsort
(
mya
->
a
+
mya
->
first
*
mya
->
size
,
mya
->
nmemb
,
mya
->
size
,
mya
->
cmp
);
}
else
{
/*
* Start two new threads, each sorting half of array a
*/
pm_buildparams
(
&
larg
,
mya
->
a
,
mya
->
b
,
mya
->
first
,
mya
->
nmemb
/
2
,
mya
->
size
,
mya
->
cmp
,
mya
->
axis
,
mya
->
max_threads
/
2
);
mya
->
size
,
mya
->
cmp
,
mya
->
max_threads
/
2
);
/*
* Recursively sort the left half
*/
...
...
@@ -105,7 +98,7 @@ mergesort_t(void *args)
pm_buildparams
(
&
rarg
,
mya
->
a
,
mya
->
b
,
mya
->
first
+
mya
->
nmemb
/
2
,
mya
->
nmemb
-
mya
->
nmemb
/
2
,
mya
->
size
,
mya
->
cmp
,
mya
->
axis
,
mya
->
max_threads
/
2
);
mya
->
cmp
,
mya
->
max_threads
/
2
);
/*
* Recursively sort the right half
*/
...
...
@@ -144,7 +137,7 @@ mergesort_t(void *args)
* element
*/
else
if
(
mya
->
cmp
(
mya
->
a
+
li
*
mya
->
size
,
mya
->
a
+
ri
*
mya
->
size
,
mya
->
axis
)
<
1
)
{
mya
->
a
+
ri
*
mya
->
size
)
<
1
)
{
memcpy
(
mya
->
b
+
i
*
mya
->
size
,
mya
->
a
+
li
*
mya
->
size
,
mya
->
size
);
li
++
;
...
...
src/kdtreelib/qsort.c
deleted
100644 → 0
View file @
009fe711
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details (qsort.c
is used to build libc.a and as such is covered by the LGPL -- Joerg
Dietrich 2008)*/
#include
<stdlib.h>
/*-
* Copyright (c) 1980, 1983 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
* qsort.c:
* Our own version of the system qsort routine which is faster by an average
* of 25%, with lows and highs of 10% and 50%.
* The THRESHold below is the insertion sort threshold, and has been adjusted
* for records of size 48 bytes.
* The MTHREShold is where we stop finding a better median.
*/
#define THRESH 4
/* threshold for insertion */
#define MTHRESH 6
/* threshold for median */
static
int
(
*
qcmp
)
(
const
void
*
,
const
void
*
,
int
axis
);
/* the comparison routine */
static
int
qsz
;
/* size of each record */
static
int
thresh
;
/* THRESHold in chars */
static
int
mthresh
;
/* MTHRESHold in chars */
void
qsortR
(
const
void
*
base0
,
size_t
n
,
size_t
size
,
int
(
*
compar
)
(
const
void
*
,
const
void
*
,
int
),
int
axis
);
/*
* qst:
* Do a quicksort
* First, find the median element, and put that one in the first place as the
* discriminator. (This "median" is just the median of the first, last and
* middle elements). (Using this median instead of the first element is a big
* win). Then, the usual partitioning/swapping, followed by moving the
* discriminator into the right place. Then, figure out the sizes of the two
* partions, do the smaller one recursively and the larger one via a repeat of
* this code. Stopping when there are less than THRESH elements in a partition
* and cleaning up with an insertion sort (in our caller) is a huge win.
* All data swaps are done in-line, which is space-losing but time-saving.
* (And there are only three places where this is done).
*/
static
void
qst
(
char
*
base
,
char
*
max
,
int
axis
)
{
char
c
,
*
i
,
*
j
,
*
jj
;
int
ii
;
char
*
mid
,
*
tmp
;
int
lo
,
hi
;
/*
* At the top here, lo is the number of characters of elements in the
* current partition. (Which should be max - base).
* Find the median of the first, last, and middle element and make
* that the middle element. Set j to largest of first and middle.
* If max is larger than that guy, then it's that guy, else compare
* max with loser of first and take larger. Things are set up to
* prefer the middle, then the first in case of ties.
*/
lo
=
max
-
base
;
/* number of elements as chars */
do
{
mid
=
i
=
base
+
qsz
*
((
lo
/
qsz
)
>>
1
);
if
(
lo
>=
mthresh
)
{
j
=
(
qcmp
((
jj
=
base
),
i
,
axis
)
>
0
?
jj
:
i
);
if
(
qcmp
(
j
,
(
tmp
=
max
-
qsz
),
axis
)
>
0
)
{
/*
* switch to first loser
*/
j
=
(
j
==
jj
?
i
:
jj
);
if
(
qcmp
(
j
,
tmp
,
axis
)
<
0
)
j
=
tmp
;
}
if
(
j
!=
i
)
{
ii
=
qsz
;
do
{
c
=
*
i
;
*
i
++
=
*
j
;
*
j
++
=
c
;
}
while
(
--
ii
);
}
}
/*
* Semi-standard quicksort partitioning/swapping
*/
for
(
i
=
base
,
j
=
max
-
qsz
;;)
{
while
(
i
<
mid
&&
qcmp
(
i
,
mid
,
axis
)
<=
0
)
i
+=
qsz
;
while
(
j
>
mid
)
{
if
(
qcmp
(
mid
,
j
,
axis
)
<=
0
)
{
j
-=
qsz
;
continue
;
}
tmp
=
i
+
qsz
;
/* value of i after swap */
if
(
i
==
mid
)
{
/*
* j <-> mid, new mid is j
*/
mid
=
jj
=
j
;
}
else
{
/*
* i <-> j
*/
jj
=
j
;
j
-=
qsz
;
}
goto
swap
;
}
if
(
i
==
mid
)
{
break
;
}
else
{
/*
* i <-> mid, new mid is i
*/
jj
=
mid
;
tmp
=
mid
=
i
;
/* value of i after swap */
j
-=
qsz
;
}
swap:
ii
=
qsz
;
do
{
c
=
*
i
;
*
i
++
=
*
jj
;
*
jj
++
=
c
;
}
while
(
--
ii
);
i
=
tmp
;
}
/*
* Look at sizes of the two partitions, do the smaller
* one first by recursion, then do the larger one by
* making sure lo is its size, base and max are update
* correctly, and branching back. But only repeat
* (recursively or by branching) if the partition is
* of at least size THRESH.
*/
i
=
(
j
=
mid
)
+
qsz
;
if
((
lo
=
j
-
base
)
<=
(
hi
=
max
-
i
))
{
if
(
lo
>=
thresh
)
qst
(
base
,
j
,
axis
);
base
=
i
;
lo
=
hi
;
}
else
{
if
(
hi
>=
thresh
)
qst
(
i
,
max
,
axis
);
max
=
j
;
}
}
while
(
lo
>=
thresh
);
}
/*
* qsort:
* First, set up some global parameters for qst to share. Then, quicksort
* with qst(), and then a cleanup insertion sort ourselves. Sound simple?
* It's not...
*/
void
qsortR
(
const
void
*
base0
,
size_t
n
,
size_t
size
,
int
(
*
compar
)
(
const
void
*
,
const
void
*
,
int
axis
),
int
axis
)
{
char
*
base
=
(
char
*
)
base0
;
char
c
,
*
i
,
*
j
,
*
lo
,
*
hi
;
char
*
min
,
*
max
;
if
(
n
<=
1
)
return
;
qsz
=
size
;
qcmp
=
compar
;
thresh
=
qsz
*
THRESH
;
mthresh
=
qsz
*
MTHRESH
;
max
=
base
+
n
*
qsz
;
if
(
n
>=
THRESH
)
{
qst
(
base
,
max
,
axis
);
hi
=
base
+
thresh
;
}
else
{
hi
=
max
;
}
/*
* First put smallest element, which must be in the first THRESH, in
* the first position as a sentinel. This is done just by searching
* the first THRESH elements (or the first n if n < THRESH), finding
* the min, and swapping it into the first position.
*/
for
(
j
=
lo
=
base
;
(
lo
+=
qsz
)
<
hi
;)
if
(
qcmp
(
j
,
lo
,
axis
)
>
0
)
j
=
lo
;
if
(
j
!=
base
)
{
/*
* swap j into place
*/
for
(
i
=
base
,
hi
=
base
+
qsz
;
i
<
hi
;)
{
c
=
*
j
;
*
j
++
=
*
i
;
*
i
++
=
c
;
}
}
/*
* With our sentinel in place, we now run the following hyper-fast
* insertion sort. For each remaining element, min, from [1] to [n-1],
* set hi to the index of the element AFTER which this one goes.
* Then, do the standard insertion sort shift on a character at a time
* basis for each element in the frob.
*/
for
(
min
=
base
;
(
hi
=
min
+=
qsz
)
<
max
;)
{
while
(
qcmp
(
hi
-=
qsz
,
min
,
axis
)
>
0
)
/*
* void
*/
;
if
((
hi
+=
qsz
)
!=
min
)
{
for
(
lo
=
min
+
qsz
;
--
lo
>=
min
;)
{
c
=
*
lo
;
for
(
i
=
j
=
lo
;
(
j
-=
qsz
)
>=
hi
;
i
=
j
)
*
i
=
*
j
;
*
i
=
c
;
}
}
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment