/* Sort a Pure list using the C qsort() function. 2008-06-25 AG */ /* Another example using the runtime API. It implements an external function 'sort' which can be loaded inside the Pure interpreter. The function, to be invoked as 'sort p xs', calls the qsort() routine from the C library to sort a Pure list xs using a given Pure predicate p, which compares two elements x and y and returns a truth value indicating whether x is less than y. The example illustrates how we can program a C function to be called from Pure which in turn calls other Pure functions, and takes generic pure_expr* values as arguments and returns them as results. */ /* To compile (Linux): 'gcc -shared -o sort.so sort.c -lpure' (add -fPIC on 64 bit systems). This will create a dynamic library ready to be loaded by the Pure interpreter. (On OSX and Windows, replace .so with .dylib or .dll, respectively. On OSX, you also have to replace -shared with -dynamiclib. On Windows you might wish to add the '-Wl,--enable-auto-import' linker option.) Now start the interpreter and enter the following to "dlopen" sort.so and declare the sort function: > using "lib:sort"; > extern expr* sort(expr* p, expr *xs); The sort function is now ready to be called as 'sort p xs', e.g.: > sort (<) (1..10); [1,2,3,4,5,6,7,8,9,10] > sort (>) (1..10); [10,9,8,7,6,5,4,3,2,1] Have some fun with random lists, comparing our sort function with the one from hello.pure. (The rand function is also declared in hello.pure; it is just the rand() function from the C library.) > run hello.pure Hello, world! > let xs = [rand; i = 1..100000]; > stats > #sort (<) xs; 100000 1.05s > #qsort (<) xs; 100000 14.05s The above results are for my Athlon 2500+. YMMV, but most likely you'll get similar results indicating that the C implementation is much faster. That's because the quicksort algorithm in hello.pure juggles around with lists, whereas the C quicksort routine uses vectors and sorts the elements in-place. */ #include #include /* Set up a C callback which in turn invokes a Pure predicate to perform the comparison of list elements. */ static pure_expr* cmp_p; static int cmp(const void *xp, const void *yp) { pure_expr *x = *(pure_expr**)xp, *y = *(pure_expr**)yp; /* We use pure_appl to invoke the Pure predicate stored in cmp_p on the list elements x and y passed by the qsort() routine. */ pure_expr *p = pure_appl(cmp_p, 2, x, y); int res = pure_is_int(p, &res) && res; /* x