mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-02-28 19:16:09 +08:00
332 lines
8.6 KiB
C++
332 lines
8.6 KiB
C++
#include "opennurbs.h"
|
|
|
|
#if !defined(ON_COMPILING_OPENNURBS)
|
|
// This check is included in all opennurbs source .c and .cpp files to insure
|
|
// ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled.
|
|
// When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined
|
|
// and the opennurbs .h files alter what is declared and how it is declared.
|
|
#error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs
|
|
#endif
|
|
|
|
/*
|
|
If the speed of ON_qsort() functions on arrays that
|
|
are nearly sorted is as good as heap sort, then define
|
|
ON__QSORT_FASTER_THAN_HSORT.
|
|
*/
|
|
|
|
#define ON_COMPILING_OPENNURBS_SORT_CPP
|
|
|
|
#if defined(ON_RUNTIME_WIN) && defined(ON_COMPILER_MSC)
|
|
|
|
#pragma optimize("t", on)
|
|
|
|
// have a reliable thread safe CRT qsort.
|
|
#define ON__HAVE_RELIABLE_SYSTEM_QSORT
|
|
#define ON__QSORT_FASTER_THAN_HSORT
|
|
|
|
#elif defined(_GNU_SOURCE)
|
|
|
|
// have a reliable thread safe CRT qsort.
|
|
#define ON__HAVE_RELIABLE_SYSTEM_QSORT
|
|
#define ON__QSORT_FASTER_THAN_HSORT
|
|
|
|
#endif
|
|
|
|
#if defined(ON_RUNTIME_WIN) && defined(ON_COMPILER_MSC)
|
|
|
|
// have a reliable thread safe CRT qsort with context that is
|
|
// faster than the functions below.
|
|
#define ON__HAVE_RELIABLE_SYSTEM_CONTEXT_QSORT
|
|
#define ON__QSORT_FASTER_THAN_HSORT
|
|
|
|
#elif defined(ON_COMPILER_CLANG)
|
|
|
|
#define ON__HAVE_RELIABLE_SYSTEM_CONTEXT_QSORT
|
|
#define ON__QSORT_FASTER_THAN_HSORT
|
|
|
|
#elif defined(_GNU_SOURCE)
|
|
|
|
#define ON__HAVE_RELIABLE_SYSTEM_CONTEXT_QSORT
|
|
#define ON__QSORT_FASTER_THAN_HSORT
|
|
|
|
#endif
|
|
|
|
#define work_size 64
|
|
|
|
void
|
|
ON_qsort( void *base, size_t nel, size_t width, int (*compar)(void*,const void *, const void *),void* context)
|
|
{
|
|
#if defined(ON__HAVE_RELIABLE_SYSTEM_CONTEXT_QSORT)
|
|
// The call here must be a thread safe system qsort
|
|
// that is faster than the alternative code in this function.
|
|
// In particular, if it uses a random number generator to
|
|
// find pivots, that calculation must be thread safe.
|
|
#if defined(ON_COMPILER_MSC)
|
|
qsort_s(base,nel,width,compar,context);
|
|
#elif defined(ON_RUNTIME_ANDROID) || defined(ON_RUNTIME_LINUX) || defined(ON_RUNTIME_WASM)
|
|
ON_hsort(base, nel, width, compar, context);
|
|
#elif defined(ON_COMPILER_CLANG)
|
|
qsort_r(base,nel,width,context,compar);
|
|
#elif defined(_GNU_SOURCE)
|
|
qsort_r(base,nel,width,context,compar);
|
|
#endif
|
|
#else
|
|
ON_hsort(base, nel, width, compar, context);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
ON_qsort( void *base, size_t nel, size_t width, int (*compar)(const void *, const void *))
|
|
{
|
|
#if defined(ON__HAVE_RELIABLE_SYSTEM_QSORT)
|
|
// The call here must be a thread safe system qsort
|
|
// that is faster than the alternative code in this function.
|
|
// In particular, if it uses a random number generator to
|
|
// find pivots, that calculation must be thread safe.
|
|
qsort(base,nel,width,compar);
|
|
#else
|
|
ON_hsort(base, nel, width, compar);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
ON_hsort(void *base, size_t nel, size_t width, int (*compar)(const void*,const void*))
|
|
{
|
|
size_t
|
|
i_end,k;
|
|
unsigned char
|
|
work_memory[work_size], *e_tmp, *e_end;
|
|
|
|
if (nel < 2) return;
|
|
k = nel >> 1;
|
|
i_end = nel-1;
|
|
e_end = ((unsigned char*)base) + i_end*width;
|
|
e_tmp = (width > work_size) ? (unsigned char*)onmalloc(width) : work_memory;
|
|
for (;;) {
|
|
if (k) {
|
|
--k;
|
|
memcpy(e_tmp,((unsigned char*)base)+k*width,width); /* e_tmp = e[k]; */
|
|
}
|
|
else {
|
|
memcpy(e_tmp,e_end,width); /* e_tmp = e[i_end]; */
|
|
memcpy(e_end,base,width); /* e[i_end] = e[0]; */
|
|
if (!(--i_end)) {
|
|
memcpy(base,e_tmp,width); /* e[0] = e_tmp; */
|
|
break;
|
|
}
|
|
e_end -= width;
|
|
}
|
|
{ size_t i, j;
|
|
unsigned char *e_i, *e_j;
|
|
i = k;
|
|
j = (k<<1) + 1;
|
|
e_i = ((unsigned char*)base) + i*width;
|
|
while (j <= i_end) {
|
|
e_j = ((unsigned char*)base) + j*width;
|
|
if (j < i_end && compar(e_j,e_j+width)<0 /*e[j] < e[j + 1] */)
|
|
{j++; e_j += width;}
|
|
if (compar(e_tmp,e_j)<0 /* e_tmp < e[j] */) {
|
|
memcpy(e_i,e_j,width); /* e[i] = e[j]; */
|
|
i = j;
|
|
e_i = e_j;
|
|
j = (j<<1) + 1;
|
|
} else j = i_end + 1;
|
|
}
|
|
memcpy(e_i,e_tmp,width); /* e[i] = e_tmp; */
|
|
}
|
|
}
|
|
if (width > work_size) onfree(e_tmp);
|
|
}
|
|
|
|
void
|
|
ON_hsort(void *base, size_t nel, size_t width, int (*compar)(void*,const void*,const void*), void* context)
|
|
{
|
|
size_t
|
|
i_end,k;
|
|
unsigned char
|
|
work_memory[work_size], *e_tmp, *e_end;
|
|
|
|
if (nel < 2) return;
|
|
k = nel >> 1;
|
|
i_end = nel-1;
|
|
e_end = ((unsigned char*)base) + i_end*width;
|
|
e_tmp = (width > work_size) ? (unsigned char*)onmalloc(width) : work_memory;
|
|
for (;;) {
|
|
if (k) {
|
|
--k;
|
|
memcpy(e_tmp,((unsigned char*)base)+k*width,width); /* e_tmp = e[k]; */
|
|
}
|
|
else {
|
|
memcpy(e_tmp,e_end,width); /* e_tmp = e[i_end]; */
|
|
memcpy(e_end,base,width); /* e[i_end] = e[0]; */
|
|
if (!(--i_end)) {
|
|
memcpy(base,e_tmp,width); /* e[0] = e_tmp; */
|
|
break;
|
|
}
|
|
e_end -= width;
|
|
}
|
|
{ size_t i, j;
|
|
unsigned char *e_i, *e_j;
|
|
i = k;
|
|
j = (k<<1) + 1;
|
|
e_i = ((unsigned char*)base) + i*width;
|
|
while (j <= i_end) {
|
|
e_j = ((unsigned char*)base) + j*width;
|
|
if (j < i_end && compar(context,e_j,e_j+width)<0 /*e[j] < e[j + 1] */)
|
|
{j++; e_j += width;}
|
|
if (compar(context,e_tmp,e_j)<0 /* e_tmp < e[j] */) {
|
|
memcpy(e_i,e_j,width); /* e[i] = e[j]; */
|
|
i = j;
|
|
e_i = e_j;
|
|
j = (j<<1) + 1;
|
|
} else j = i_end + 1;
|
|
}
|
|
memcpy(e_i,e_tmp,width); /* e[i] = e_tmp; */
|
|
}
|
|
}
|
|
if (width > work_size) onfree(e_tmp);
|
|
}
|
|
|
|
#undef work_size
|
|
|
|
#define ON_COMPILING_OPENNURBS_QSORT_FUNCTIONS
|
|
#define ON_COMPILING_OPENNURBS_HSORT_FUNCTIONS
|
|
#define ON_SORT_TEMPLATE_STATIC_FUNCTION
|
|
|
|
#define ON_SORT_TEMPLATE_TYPE double
|
|
#define ON_QSORT_FNAME ON_qsort_double
|
|
#define ON_HSORT_FNAME ON_hsort_double
|
|
#include "opennurbs_qsort_template.h"
|
|
#include "opennurbs_hsort_template.h"
|
|
#undef ON_SORT_TEMPLATE_TYPE
|
|
#undef ON_QSORT_FNAME
|
|
#undef ON_HSORT_FNAME
|
|
|
|
#define ON_SORT_TEMPLATE_TYPE double
|
|
#define ON_QSORT_FNAME ON_qsort_double_decreasing
|
|
#define ON_QSORT_GT(A,B) *A < *B
|
|
#define ON_QSORT_LE(A,B) *A >= *B
|
|
#define ON_QSORT_EQ(A,B) *A == *B
|
|
#undef ON_QSORT_SHORT_SORT_FNAME
|
|
#define ON_QSORT_SHORT_SORT_FNAME ON__shortsort_double_decreasing
|
|
#include "opennurbs_qsort_template.h"
|
|
#undef ON_SORT_TEMPLATE_TYPE
|
|
#undef ON_QSORT_FNAME
|
|
|
|
void ON_SortDoubleArray(
|
|
ON::sort_algorithm sort_algorithm,
|
|
double* a,
|
|
size_t nel
|
|
)
|
|
{
|
|
if ( ON::sort_algorithm::heap_sort == sort_algorithm )
|
|
ON_hsort_double(a,nel);
|
|
else
|
|
ON_qsort_double(a,nel);
|
|
}
|
|
|
|
void ON_SortDoubleArrayIncreasing(
|
|
double* a,
|
|
size_t nel
|
|
)
|
|
{
|
|
ON_qsort_double(a, nel);
|
|
}
|
|
|
|
ON_DECL
|
|
void ON_SortDoubleArrayDecreasing(
|
|
double* a,
|
|
size_t nel
|
|
)
|
|
{
|
|
ON_qsort_double_decreasing(a, nel);
|
|
}
|
|
|
|
#define ON_SORT_TEMPLATE_TYPE float
|
|
#define ON_QSORT_FNAME ON_qsort_float
|
|
#define ON_HSORT_FNAME ON_hsort_float
|
|
#include "opennurbs_qsort_template.h"
|
|
#include "opennurbs_hsort_template.h"
|
|
#undef ON_SORT_TEMPLATE_TYPE
|
|
#undef ON_QSORT_FNAME
|
|
#undef ON_HSORT_FNAME
|
|
|
|
void ON_SortFloatArray(
|
|
ON::sort_algorithm sort_algorithm,
|
|
float* a,
|
|
size_t nel
|
|
)
|
|
{
|
|
if ( ON::sort_algorithm::heap_sort == sort_algorithm )
|
|
ON_hsort_float(a,nel);
|
|
else
|
|
ON_qsort_float(a,nel);
|
|
}
|
|
|
|
|
|
#define ON_SORT_TEMPLATE_TYPE int
|
|
#define ON_QSORT_FNAME ON_qsort_int
|
|
#define ON_HSORT_FNAME ON_hsort_int
|
|
#include "opennurbs_qsort_template.h"
|
|
#include "opennurbs_hsort_template.h"
|
|
#undef ON_SORT_TEMPLATE_TYPE
|
|
#undef ON_QSORT_FNAME
|
|
#undef ON_HSORT_FNAME
|
|
|
|
void ON_SortIntArray(
|
|
ON::sort_algorithm sort_algorithm,
|
|
int* a,
|
|
size_t nel
|
|
)
|
|
{
|
|
if ( ON::sort_algorithm::heap_sort == sort_algorithm )
|
|
ON_hsort_int(a,nel);
|
|
else
|
|
ON_qsort_int(a,nel);
|
|
}
|
|
|
|
|
|
#define ON_SORT_TEMPLATE_TYPE unsigned int
|
|
#define ON_QSORT_FNAME ON_qsort_uint
|
|
#define ON_HSORT_FNAME ON_hsort_uint
|
|
#include "opennurbs_qsort_template.h"
|
|
#include "opennurbs_hsort_template.h"
|
|
#undef ON_SORT_TEMPLATE_TYPE
|
|
#undef ON_QSORT_FNAME
|
|
#undef ON_HSORT_FNAME
|
|
|
|
void ON_SortUnsignedIntArray(
|
|
ON::sort_algorithm sort_algorithm,
|
|
unsigned int* a,
|
|
size_t nel
|
|
)
|
|
{
|
|
if ( ON::sort_algorithm::heap_sort == sort_algorithm )
|
|
ON_hsort_uint(a,nel);
|
|
else
|
|
ON_qsort_uint(a,nel);
|
|
}
|
|
|
|
|
|
#define ON_SORT_TEMPLATE_TYPE ON__UINT64
|
|
#define ON_QSORT_FNAME ON_qsort_uint64
|
|
#define ON_HSORT_FNAME ON_hsort_uint64
|
|
#include "opennurbs_qsort_template.h"
|
|
#include "opennurbs_hsort_template.h"
|
|
#undef ON_SORT_TEMPLATE_TYPE
|
|
#undef ON_QSORT_FNAME
|
|
#undef ON_HSORT_FNAME
|
|
|
|
void ON_SortUINT64Array(
|
|
ON::sort_algorithm sort_algorithm,
|
|
ON__UINT64* a,
|
|
size_t nel
|
|
)
|
|
{
|
|
if ( ON::sort_algorithm::heap_sort == sort_algorithm )
|
|
ON_hsort_uint64(a,nel);
|
|
else
|
|
ON_qsort_uint64(a,nel);
|
|
}
|
|
|