/* copyright 2007 by Robert Dodier
 * I release this file under the terms of the GNU General Public License.
 */

wilcoxon (X, C) := block ([X1, X0, X10, R, n1, n0, Rsum, W],

    X1 : X [C = 1, 1],
    X0 : X [C = 0, 1],
    n1 : nrows (X1),
    n0 : nrows (X0),
    if n1 = 0 or n0 = 0
        then 1/2
        else
           (X10 : append (elements (X1), elements (X0)),
            R : ranks (X10),
            Rsum : sum (R[i], i, 1, n1),
            W : (Rsum - n1 * (n1 + 1) / 2) / (n1 * n0)));

load ("combinatorics");

ranks_no_rank_averaging (L) := perm_inverse (ordering (L));

ordering (L, [P]) :=
   (P: if P = [] then 'orderlessp else P[1],
    map (second, sort (makelist ([L[i], i], i, 1, length (L)), P)));

ranks (L) := block ([order: ordering (L), sorted, %ranks],
    %ranks: perm_inverse (order),
    sorted: permute (order, L),
    runs: find_runs_nontrivial (sorted),
    for e in runs do block ([avg_rank],
        avg_rank : (1/second(e)) * sum (%ranks [order[i]], i, first(e), first(e) + second(e) - 1),
        for i : first(e) thru first(e) + second(e) - 1 do %ranks [order[i]] : avg_rank),
    %ranks);

load ("descriptive");

find_runs_nontrivial (x) :=
    if x = [] then []
        else block ([runs: find_runs (x), by_twos],
                    /* rearrange runs(...) to list of pairs as expected in this function */
                    map (lambda ([a, b], [a, b]), cons (1, 1 + accumulate ("+", rest (runs@lengths, -1))), runs@lengths),
                    sublist (%%, lambda ([e], second (e) > 1)));
