Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions inst/include/S4Vectors_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,18 @@ void get_matches_of_ordered_int_quads(
int out_shift
);

int sort_void_array(
int *base,
int base_len,
const void *x,
size_t elem_size,
int desc,
int use_double_compar,
int use_radix,
unsigned short int *rxbuf1,
int *rxbuf2
);

/*
* Hash table management.
* (see hash_utils.c)
Expand Down
5 changes: 5 additions & 0 deletions inst/include/_S4Vectors_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ DEFINE_NOVALUE_CCALLABLE_STUB(get_matches_of_ordered_int_quads,
( a1, b1, c1, d1, o1, nelt1, a2, b2, c2, d2, o2, nelt2, nomatch, out, out_shift)
)

DEFINE_CCALLABLE_STUB(int, sort_void_array,
(int *base, int base_len, const void *x, size_t elem_size, int desc, int use_double_compar, int use_radix, unsigned short int *rxbuf1, int *rxbuf2),
( base, base_len, x, elem_size, desc, use_double_compar, use_radix, rxbuf1, rxbuf2)
)

/*
* Stubs for callables defined in hash_utils.c
*/
Expand Down
1 change: 1 addition & 0 deletions src/R_init_S4Vectors.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ void R_init_S4Vectors(DllInfo *info)
REGISTER_CCALLABLE(_get_matches_of_ordered_int_pairs);
REGISTER_CCALLABLE(_get_order_of_int_quads);
REGISTER_CCALLABLE(_get_matches_of_ordered_int_quads);
REGISTER_CCALLABLE(_sort_void_array);

/* hash_utils.c */
REGISTER_CCALLABLE(_new_htab);
Expand Down
12 changes: 12 additions & 0 deletions src/S4Vectors.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,18 @@ void _get_matches_of_ordered_int_quads(
int out_shift
);

int _sort_void_array(
int *base,
int base_len,
const void *x,
size_t elem_size,
int desc,
int use_double_compar,
int use_radix,
unsigned short int *rxbuf1,
int *rxbuf2
);


/* hash_utils.c */

Expand Down
92 changes: 92 additions & 0 deletions src/sort_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

static const int *aa, *bb, *cc, *dd;
static int aa_desc, bb_desc, cc_desc, dd_desc;
static size_t byte_elem_size;
static const unsigned char *global_byte_array;

#define COMPARE_TARGET_INTS(target, i1, i2, desc) \
((desc) ? (target)[(i2)] - (target)[(i1)] \
Expand Down Expand Up @@ -86,13 +88,46 @@ static int compar4_stable(const void *p1, const void *p2)
return i1 - i2;
}

static int comparbyte_stable(const void *p1, const void *p2){
int i1, i2, ret;
i1 = *((const int *) p1);
i2 = *((const int *) p2);
ret = memcmp(&(global_byte_array[i1*byte_elem_size]), &(global_byte_array[i2*byte_elem_size]), byte_elem_size);
if(aa_desc) ret *= -1;
return ret == 0 ? i1 - i2 : ret;
}

static int compardouble_stable(const void *p1, const void *p2){
// can't use memcmp for doubles unfortunately
int i1, i2, ret;
i1 = *((const int *) p1);
i2 = *((const int *) p2);
double v1 = ((double*)global_byte_array)[i1];
double v2 = ((double*)global_byte_array)[i2];
ret = (v1 > v2) - (v1 < v2);
if(aa_desc) ret *= -1;
return ret == 0 ? i1 - i2 : ret;
}

static void qsort1(int *base, int base_len, const int *a, int a_desc)
{
aa = a;
aa_desc = a_desc;
qsort(base, base_len, sizeof(int), compar1_stable);
}

static void qsort_void(int *base, int base_len, const void *a, size_t a_size,
int a_desc, int use_double_compar){
// have to cast to bytes so we can index
global_byte_array = (const unsigned char*)a;
aa_desc = a_desc;
byte_elem_size = a_size;
if(!use_double_compar)
qsort(base, base_len, sizeof(int), comparbyte_stable);
else
qsort(base, base_len, sizeof(int), compardouble_stable);
}

static void qsort2(int *base, int base_len,
const int *a, const int *b,
int a_desc, int b_desc)
Expand Down Expand Up @@ -1350,3 +1385,60 @@ void _get_matches_of_ordered_int_quads(
return;
}

/****************************************************************************
* Getting the order of a void* array using memcmp
*
*/

/* base: 0-based indices into 'x'.
rxbuf1, rxbuf2: NULL or user-allocated buffers of length 'base_len'.
Returns 0 if nothing to sort, that is, if 'base' is already sorted with
respect to 'x'. Otherwise returns 1, or a negative value if an error
occurred. Has a dedicated switch for sorting float/double...it's clunky,
but I couldn't think of a better way. Primary use-case is XRaw anyway,
so it shouldn't be a huge deal. */
int _sort_void_array(int *base, int base_len,
const void *x, size_t elem_size,
int desc, int use_double_compar,
int use_radix, unsigned short int *rxbuf1, int *rxbuf2)
{
// will add this in eventually, not critical for functionality
// Below section is copied from _sort_int_array, will need to be adapted
// Until this is incorporated, use_radix, rxbuf1, and rxbuf2 are not used
/*
int qsort_cutoff, ret, auto_rxbuf1, auto_rxbuf2;

rxtargets[0] = x;
rxdescs[0] = desc;

qsort_cutoff = (use_radix && can_use_rxsort()) ? 1024 : base_len;
ret = lucky_sort_targets(base, base_len, rxtargets, rxdescs, 1, qsort_cutoff);
if (ret != 0)
return ret != 1;

auto_rxbuf1 = rxbuf1 == NULL;
if (auto_rxbuf1) {
rxbuf1 = alloc_rxbuf1(base_len);
if (rxbuf1 == NULL)
return -1;
}
auto_rxbuf2 = rxbuf2 == NULL;
if (auto_rxbuf2) {
rxbuf2 = alloc_rxbuf2(base_len, rxbuf1, auto_rxbuf1);
if (rxbuf2 == NULL)
return -2;
}

last_rxlevel = 1;
base_uidx_buf = rxbuf1;
rxsort_rec(base, base_len, rxbuf2, 0, 0);

if (auto_rxbuf2)
free(rxbuf2);
if (auto_rxbuf1)
free(rxbuf1);
*/

qsort_void(base, base_len, x, elem_size, desc, use_double_compar);
return 1;
}