/* sortdata - Sorting, ordering and ranking functions. Uses C qsort. */
/* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
/* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
/* You may give out copies of this software; for conditions see the */
/* file COPYING included with this distribution. */
#include "xlisp.h"
#include "xlstat.h"
/* forward declarations */
LOCAL LVAL lsort(V);
LOCAL int tiebreak P2H(LVAL *, LVAL *);
/* tiebreaker routine */
LOCAL int tiebreak P2C(LVAL *, px, LVAL *, py)
{
int ix = getfixnum(px[1]);
int iy = getfixnum(py[1]);
if (ix < iy) return(-1);
else return(1);
}
/* comparison routine for qsort */
#ifdef ANSI
LOCAL int lcomp(const void *px, const void *py)
#else
LOCAL int lcomp(px, py)
ALLOCTYPE *px, *py;
#endif /* ANSI */
{
LVAL x, y;
FIXTYPE ix, iy;
double fx, fy;
x = *((LVAL *) px);
y = *((LVAL *) py);
if (fixp(x) && fixp(y)) {
ix = getfixnum(x);
iy = getfixnum(y);
if (ix < iy) return(-1);
else if (ix > iy) return(1);
else return tiebreak((LVAL *) px, (LVAL *) py);
}
else if (realp(x) && realp(y)) {
fx = makefloat(x);
fy = makefloat(y);
if (fx < fy) return(-1);
else if (fx > fy) return(1);
else return tiebreak((LVAL *) px, (LVAL *) py);
}
else if (stringp(x) && stringp(y)) {
ix = strcmp(getstring(x), getstring(y));
return ix ? ix : tiebreak((LVAL *) px, (LVAL *) py);
}
else xlfail("can't compare these");
return 0; /* not reached */
}
/* for defining SORT-DATA with SORT function */
LVAL xssortcmp(V)
{
LVAL x, y;
x = xlgetarg();
y = xlgetarg();
xllastarg();
if (fixp(x) && fixp(y))
return (getfixnum(x) > getfixnum(y)) ? NIL : s_true;
else if (realp(x) && realp(y))
return (makefloat(x) > makefloat(y)) ? NIL : s_true;
else if (stringp(x) && stringp(y))
return (strcmp(getstring(x), getstring(y)) > 0) ? NIL : s_true;
else {
xlfail("can't compare these");
return 0; /* not reached */
}
}
/* for defining ORDER with SORT function */
LVAL xsordercmp(V)
{
LVAL x, y;
x = car(xlgacons());
y = car(xlgacons());
xllastarg();
if (fixp(x) && fixp(y))
return (getfixnum(x) > getfixnum(y)) ? NIL : s_true;
else if (realp(x) && realp(y))
return (makefloat(x) > makefloat(y)) ? NIL : s_true;
else if (stringp(x) && stringp(y))
return (strcmp(getstring(x), getstring(y)) > 0) ? NIL : s_true;
else {
xlfail("can't compare these");
return 0; /* not reached */
}
}
/* internal sort and order routine. Returns list of list of sorted values */
/* and corresponding indices into original sequence (result of ORDER). */
LOCAL LVAL lsort(V)
{
LVAL x, sortx, result, nextx, nexti,
result_x, result_i;
int i, n;
/* protect some pointers */
xlstkcheck(5);
xlsave(x);
xlsave(sortx);
xlsave(result);
xlsave(result_x);
xlsave(result_i);
x = xlgetarg();
x = elementseq(x);
x = coerce_to_list(x);
xllastarg();
n = llength(x);
/* copy x and indices to sortx */
sortx = newvector(2 * n);
for (i = 0, nextx = x; i < n; i++, nextx = cdr(nextx)) {
setelement(sortx, 2 * i, car(nextx));
setelement(sortx, 2 * i + 1, cvfixnum((FIXTYPE) i));
}
/* sort the data and get the indices */
qsort(&getelement(sortx, 0), n, 2 * sizeof(LVAL), lcomp);
/* copy the arrays to lists */
result_x = mklist(n, NIL);
result_i = mklist(n, NIL);
for (i = 0, nextx = result_x, nexti = result_i; i < n;
i++, nextx = cdr(nextx), nexti = cdr(nexti)) {
rplaca(nextx, getelement(sortx, 2 * i));
rplaca(nexti, getelement(sortx, 2 * i + 1));
}
result = list2(result_x, result_i);
/* restore the stack frame */
xlpopn(5);
return(result);
}
/* Built in SORT-DATA function */
LVAL xssortdata(V) { return(car(lsort())); }
/* Built in ORDER function */
LVAL xsorder(V) { return(car(cdr(lsort()))); }
/* Built in RANK function */
LVAL xsrank(V)
{
LVAL x, result;
/* create a new stack frame */
xlstkcheck(2);
xlsave(x);
xlsave(result);
x = peekarg(0);
result = xsorder();
result = xlcallsubr1(xsorder, result);
result = makecompound(x, result);
/* restore the stack frame */
xlpopn(2);
return(result);
}
syntax highlighted by Code2HTML, v. 0.9.1