diff --git a/src/builtin_functions.c b/src/builtin_functions.c index cc15c3a9ad5fcd97d1fc393eb9b995f891627283..ee107d21afe0e0d645e8b30fee66f31f7a74aee5 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: builtin_functions.c,v 1.69 1998/02/12 01:25:25 mirar Exp $"); +RCSID("$Id: builtin_functions.c,v 1.70 1998/02/12 14:11:59 grubba Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -1571,6 +1571,108 @@ void f_glob(INT32 args) } } +/* longest_ordered_sequence */ + +static int find_gt(struct array *a, int i, int *stack, int top) +{ + struct svalue *x = a->item + i; + int l,h; + + if (!top || !is_lt(x, a->item + stack[top - 1])) return top; + + l = 0; + h = top; + + while (l < h) { + int middle = (l + h)/2; + if (!is_gt(a->item + stack[middle], x)) { + l = middle+1; + } else { + h = middle; + } + } + return l; +} + +static struct array *longest_ordered_sequence(struct array *a) +{ + int *stack; + int *links; + int i,j,top=0,l=0,ltop=-1; + struct array *res; + ONERROR tmp; + ONERROR tmp2; + + stack = malloc(sizeof(int)*a->size); + links = malloc(sizeof(int)*a->size); + + if (!stack || !links) + { + if (stack) free(stack); + if (links) free(links); + return 0; + } + + /* is_gt(), is_lt() and low_allocate_array() can generate errors. */ + + SET_ONERROR(tmp, free, stack); + SET_ONERROR(tmp2, free, links); + + for (i=0; i<a->size; i++) { + int pos; + + pos = find_gt(a, i, stack, top); + + if (pos == top) { + top++; + ltop = i; + } + if (pos != 0) + links[i] = stack[pos-1]; + else + links[i] = -1; + stack[pos] = i; + + fprintf(stderr, "%d: link:%d ltop:%d pos:%d top:%d\n", + i, links[i], ltop, pos, top); + } + + /* FIXME(?) memory unfreed upon error here */ + res = low_allocate_array(top, 0); + while (ltop != -1) + { + res->item[--top].u.integer = ltop; + ltop = links[ltop]; + } + + UNSET_ONERROR(tmp2); + UNSET_ONERROR(tmp); + + free(stack); + free(links); + return res; +} + +static void f_longest_ordered_sequence(INT32 args) +{ + struct array *a = NULL; + + get_all_args("Array.longest_ordered_sequence", args, "%a", &a); + + /* THREADS_ALLOW(); */ + + a = longest_ordered_sequence(a); + + /* THREADS_DISALLOW(); */ + + if (!a) { + error("Array.longest_ordered_sequence():Out of memory"); + } + + pop_n_elems(args); + push_array(a); +} + /**** diff ************************************************************/ static struct array* diff_compare_table(struct array *a,struct array *b) @@ -2193,6 +2295,7 @@ void init_builtin_efuns(void) add_function("diff",f_diff,"function(array,array:array(array))",OPT_TRY_OPTIMIZE); add_function("diff_longest_sequence",f_diff_longest_sequence,"function(array,array:array(int))",OPT_TRY_OPTIMIZE); add_function("diff_compare_table",f_diff_compare_table,"function(array,array:array(array))",OPT_TRY_OPTIMIZE); + add_function("longest_ordered_sequence",f_longest_ordered_sequence,"function(array:array(int))",0); add_function("sort",f_sort,"function(array(mixed),array(mixed)...:array(mixed))",OPT_SIDE_EFFECT); }