diff --git a/alglib/apps/mk/sort_compare.mk b/alglib/apps/mk/sort_compare.mk
new file mode 100644
index 0000000000000000000000000000000000000000..439a23a8038b883a09228adcc54a27f1027f4443
--- /dev/null
+++ b/alglib/apps/mk/sort_compare.mk
@@ -0,0 +1 @@
+apps_targets += sort_compare
diff --git a/alglib/apps/postfix_eval b/alglib/apps/postfix_eval
deleted file mode 100755
index 10807eeb365dab9a190a5da89309f041f67d2e3f..0000000000000000000000000000000000000000
Binary files a/alglib/apps/postfix_eval and /dev/null differ
diff --git a/alglib/apps/sort_compare.c b/alglib/apps/sort_compare.c
new file mode 100644
index 0000000000000000000000000000000000000000..ddc0edeb46b778c0ee09c533b983a1bcad4e5e30
--- /dev/null
+++ b/alglib/apps/sort_compare.c
@@ -0,0 +1,586 @@
+/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */
+
+/**
+ * \file apps/sort_compare.c
+ *
+ * \brief An application to compare different sorting algorithms.
+ *
+ * \author Your Name
+ *
+ * \copyright 2015 University of Piemonte Orientale, Computer Science Institute
+ *
+ * This file is part of UPOalglib.
+ *
+ * UPOalglib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * UPOalglib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with UPOalglib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <upo/error.h>
+#include <upo/sort.h>
+#include <upo/hires_timer.h>
+
+
+#define DEFAULT_OPT_ARRAY_SIZE (size_t) 1000
+#define DEFAULT_OPT_NUM_RUNS (size_t) 1
+#define DEFAULT_OPT_RNG_SEED (unsigned int) time(NULL)
+#define DEFAULT_OPT_SORT_SPECIAL 0
+#define DEFAULT_OPT_VERBOSE 0
+#define NUM_SORTING_ALGORITHMS (size_t) 4
+
+
+/** \brief Defines the sorting algorithm category type as an enumerated type. */
+typedef enum {
+            unknown_sort_algorithm = -1,
+            insertion_sort_algorithm,
+            merge_sort_algorithm,
+            quick_sort_algorithm,
+            stdc_sort_algorithm
+        } sorting_algorithm_t;
+
+/** \brief Defines the item type as a key-value pair type. */
+typedef struct {
+            int key;
+            double value;
+        } item_t;
+
+
+/** \brief Generates a random number uniformly distributed in [0,1) */
+static double runif01();
+
+/** \brief Generates a random array of size \a n */
+static item_t* make_random_array(size_t n);
+
+/** \brief Comparison function for elements of type \a item_t to sort in ascending order. */
+static int item_comparator(const void *a, const void *b);
+
+/** \brief Comparison function for elements of type \a item_t to sort in descending order. */
+static int rev_item_comparator(const void *a, const void *b);
+
+/** \brief Sorts the given array \a items of size \a by means of the sorting algorithm \a alg */
+static double sort(sorting_algorithm_t alg, item_t *items, size_t n);
+
+/** \brief Compares sorting algorithms. */
+static void compare_algorithms(sorting_algorithm_t algs[], size_t num_algs, size_t n, unsigned int seed, size_t num_runs, int sort_special, int verbose);
+
+/** \brief Extracts the sorting algorithm name from the given string. */
+static sorting_algorithm_t parse_sorting_algorithm(const char *str);
+
+/** \brief Prints the sorting algorithm name to the given output stream. */
+static void print_sorting_algorithm(FILE *fp, sorting_algorithm_t alg);
+
+/** \brief Prints the given array to standard output. */
+static void print_array(const item_t *items, size_t n);
+
+/** \brief Displays a help message. */
+static void usage(const char *progname);
+
+
+double runif01()
+{
+    return rand()/(RAND_MAX+1.0);
+}
+
+item_t* make_random_array(size_t n)
+{
+    size_t i;
+    item_t *a;
+
+    a = malloc(n*sizeof(item_t));
+    if (a == NULL)
+    {
+        upo_throw_sys_error("Unable to allocate memory for random array");
+    }
+
+    for (i = 0; i < n; ++i)
+    {
+        item_t item;
+        item.key = rand();
+        item.value = runif01();
+        a[i] = item;
+    }
+
+    return a;
+}
+
+int item_comparator(const void *a, const void *b)
+{
+    const item_t *aa = a;
+    const item_t *bb = b;
+
+    assert( a != NULL );
+    assert( b != NULL );
+
+    return (aa->key > bb->key) - (aa->key < bb->key);
+}
+
+int rev_item_comparator(const void *a, const void *b)
+{
+    const item_t *aa = a;
+    const item_t *bb = b;
+
+    assert( a != NULL );
+    assert( b != NULL );
+
+    return (aa->key < bb->key) - (aa->key > bb->key);
+}
+
+double sort(sorting_algorithm_t alg, item_t *items, size_t n)
+{
+    upo_hires_timer_t timer;
+    double runtime = 0;
+
+    assert( items != NULL );
+
+    timer = upo_hires_timer_create();
+    upo_hires_timer_start(timer);
+    switch (alg)
+    {
+        case insertion_sort_algorithm:
+            upo_insertion_sort(items, n, sizeof(item_t), item_comparator);
+            break;
+        case merge_sort_algorithm:
+            upo_merge_sort(items, n, sizeof(item_t), item_comparator);
+            break;
+        case quick_sort_algorithm:
+            upo_quick_sort(items, n, sizeof(item_t), item_comparator);
+            break;
+        case stdc_sort_algorithm:
+            qsort(items, n, sizeof(item_t), item_comparator);
+            break;
+        case unknown_sort_algorithm:
+            return -1;
+            break;
+    }
+    upo_hires_timer_stop(timer);
+
+    runtime = upo_hires_timer_elapsed(timer);
+
+    upo_hires_timer_destroy(timer);
+
+    return runtime;
+}
+
+void compare_algorithms(sorting_algorithm_t algs[], size_t num_algs, size_t n, unsigned int seed, size_t num_runs, int sort_special, int verbose)
+{
+    double *tot_runtimes = NULL;
+    size_t r;
+    size_t k;
+
+    srand(seed);
+
+    /* Allocates memory for the array that will accumulate the runtimes */
+    tot_runtimes = malloc(num_algs*sizeof(double));
+    if (tot_runtimes == NULL)
+    {
+        upo_throw_sys_error("Unable to allocate memory for the total runtimes");
+    }
+    memset(tot_runtimes, 0, num_algs*sizeof(long));
+
+    for (r = 0; r < num_runs; ++r)
+    {
+        item_t *array = NULL;
+        item_t *asc_sorted_array = NULL;
+        item_t *des_sorted_array = NULL;
+        item_t *work_array = NULL;
+        size_t i;
+
+        if (verbose)
+        {
+            printf("RUN #%lu\n", r+1);
+        }
+        else
+        {
+            printf("RUN #%lu", r+1);
+            fflush(stdout);
+        }
+
+        /* Creates a random array */
+        array = make_random_array(n);
+        if (verbose)
+        {
+            printf("Input array: ");
+            print_array(array, n);
+            putchar('\n');
+        }
+
+        if (sort_special)
+        {
+            /* Clones the random array to create an ascending sorted version of the original array */
+            asc_sorted_array = malloc(n*sizeof(item_t));
+            if (asc_sorted_array == NULL)
+            {
+                upo_throw_sys_error("Unable to allocate memory for the ascending sorted array");
+            }
+            memcpy(asc_sorted_array, array, n*sizeof(item_t));
+            qsort(asc_sorted_array, n, sizeof(item_t), item_comparator);
+
+            /* Clones the random array to create a descending sorted version of the original array */
+            des_sorted_array = malloc(n*sizeof(item_t));
+            if (des_sorted_array == NULL)
+            {
+                upo_throw_sys_error("Unable to allocate memory for the descending sorted array");
+            }
+            memcpy(des_sorted_array, array, n*sizeof(item_t));
+            qsort(des_sorted_array, n, sizeof(item_t), rev_item_comparator);
+        }
+
+        /* Clones the random array to use as an argument to the sorting function */
+        work_array = malloc(n*sizeof(item_t));
+        if (work_array == NULL)
+        {
+            upo_throw_sys_error("Unable to allocate memory for the work array");
+        }
+
+        for (i = 0; i < num_algs; ++i)
+        {
+            double runtime = 0;
+
+            sorting_algorithm_t alg = algs[i];
+
+            if (!verbose)
+            {
+                printf(".");
+                fflush(stdout);
+            }
+
+            /* Sort the randon array */
+            memcpy(work_array, array, n*sizeof(item_t));
+            runtime = sort(alg, work_array, n);
+            if (verbose)
+            {
+                print_sorting_algorithm(stdout, alg);
+                printf(" -> runtime to sort original array: %f sec\n", runtime);
+            }
+            if (sort_special)
+            {
+                /* Sort the already sorted array */
+                memcpy(work_array, asc_sorted_array, n*sizeof(item_t));
+                runtime += sort(alg, work_array, n);
+                if (verbose)
+                {
+                    print_sorting_algorithm(stdout, alg);
+                    printf(" -> runtime to sort sorted array: %f sec\n", runtime);
+                }
+                /* Sort the already reversely sorted array */
+                memcpy(work_array, des_sorted_array, n*sizeof(item_t));
+                runtime += sort(alg, work_array, n);
+                if (verbose)
+                {
+                    print_sorting_algorithm(stdout, alg);
+                    printf(" -> runtime to sort reverse array: %f sec\n", runtime);
+                }
+            }
+
+            if (verbose)
+            {
+                print_sorting_algorithm(stdout, alg);
+                printf(" -> sorted array: ");
+                print_array(work_array, n);
+                putchar('\n');
+            }
+
+            tot_runtimes[i] += runtime;
+        }
+
+        printf("\n");
+
+        free(work_array);
+        if (sort_special)
+        {
+            free(des_sorted_array);
+            free(asc_sorted_array);
+        }
+        free(array);
+    }
+
+    printf("SUMMARY\n");
+    for (k = 0; k < num_algs; ++k)
+    {
+        size_t i;
+
+        print_sorting_algorithm(stdout, algs[k]);
+        printf("-> Average runtime: %f\n", tot_runtimes[k]/((double) num_runs));
+        if (num_algs > 1)
+        {
+            for (i = 0; i < num_algs; ++i)
+            {
+                double ratio = tot_runtimes[i]/((double) tot_runtimes[k]);
+
+                if (i == k)
+                {
+                    continue;
+                }
+
+                printf("... vs. ");
+                print_sorting_algorithm(stdout, algs[i]);
+                if (ratio >= 1)
+                {
+                    printf(" -> %f %s\n", ratio, "faster"); /* i.e., tot_runtimes[k] = tot_runtimes[i]/ratio */
+                }
+                else
+                {
+                    printf(" -> %f %s\n", 1.0/ratio, "slower"); /* i.e., tot_runtimes[k] = tot_runtimes[i]*ratio */
+                }
+            }
+        }
+    }
+
+    free(tot_runtimes);
+}
+
+sorting_algorithm_t parse_sorting_algorithm(const char *str)
+{
+    assert( str != NULL );
+
+    if (!strcmp("insertion", str))
+    {
+        return insertion_sort_algorithm;
+    }
+    if (!strcmp("merge", str))
+    {
+        return merge_sort_algorithm;
+    }
+    if (!strcmp("quick", str))
+    {
+        return quick_sort_algorithm;
+    }
+    if (!strcmp("stdc", str))
+    {
+        return stdc_sort_algorithm;
+    }
+
+    return unknown_sort_algorithm;
+}
+
+void print_sorting_algorithm(FILE *fp, sorting_algorithm_t alg)
+{
+    assert( fp != NULL );
+
+    switch (alg)
+    {
+        case insertion_sort_algorithm:
+            fprintf(fp, "Insertion sort");
+            break;
+        case merge_sort_algorithm:
+            fprintf(fp, "Merge sort");
+            break;
+        case quick_sort_algorithm:
+            fprintf(fp, "Quick sort");
+            break;
+        case stdc_sort_algorithm:
+            fprintf(fp, "Standard C sort");
+            break;
+        case unknown_sort_algorithm:
+            fprintf(fp, "Unknown sort");
+            break;
+    }
+}
+
+void print_array(const item_t *items, size_t n)
+{
+    size_t i;
+
+    assert( items != NULL );
+
+    putchar('[');
+    for (i = 0; i < n; ++i)
+    {
+        if (i > 0)
+        {
+            putchar(',');
+        }
+        printf("(%d,%f)", items[i].key, items[i].value);
+    }
+    putchar(']');
+}
+
+void usage(const char *progname)
+{
+    fprintf(stderr, "Usage: %s <options>\n", progname);
+    fprintf(stderr, "Options:\n");
+    fprintf(stderr, "-a <value>: Specifies the sorting algorithm to use.\n"
+                    "            Possible values are:\n"
+                    "            - insertion: insertion sort\n"
+                    "            - merge: merge sort\n"
+                    "            - quick: quick sort\n"
+                    "            - stdc: standard C's sort\n"
+                    "            Repeats this option as many times as is the number of algorithms to use.\n");
+    fprintf(stderr, "-h: Displays this message.\n");
+    fprintf(stderr, "-n <value>: Specifies the size of the array to sort.\n"
+                    "            [default: %lu]\n", DEFAULT_OPT_ARRAY_SIZE);
+    fprintf(stderr, "-r <value>: Specifies the number of times the comparison must be repeated.\n"
+                    "            [default: %lu]\n", DEFAULT_OPT_NUM_RUNS);
+    fprintf(stderr, "-s <value>: Specifies the seed for the random number generator.\n"
+                    "            [default: <current time>]\n");
+    fprintf(stderr, "-v: Enables output verbosity.\n"
+                    "    [default: <%s>]\n", (DEFAULT_OPT_VERBOSE ? "enabled" : "disabled"));
+    fprintf(stderr, "-x: For each random array, also sorts its corresponding sorted versions (including the\n"
+                    "    ones sorted both in increasing and decreasing order).\n"
+                    "    [default: <%s>]\n", (DEFAULT_OPT_SORT_SPECIAL ? "enabled" : "disabled"));
+}
+
+
+int main(int argc, char *argv[])
+{
+    sorting_algorithm_t *opt_algs = NULL;
+    size_t opt_n = DEFAULT_OPT_ARRAY_SIZE;
+    size_t opt_num_runs = DEFAULT_OPT_NUM_RUNS;
+    unsigned int opt_seed = DEFAULT_OPT_RNG_SEED;
+    int opt_verbose = DEFAULT_OPT_VERBOSE;
+    int opt_help = 0;
+    int opt_sort_special = DEFAULT_OPT_SORT_SPECIAL;
+    size_t num_algs = 0;
+    int chosen_algs[NUM_SORTING_ALGORITHMS];
+    int arg;
+    size_t i;
+    size_t j;
+
+    memset(chosen_algs, 0, NUM_SORTING_ALGORITHMS*sizeof(int));
+
+    for (arg = 1; arg < argc; ++arg)
+    {
+        if (!strcmp("-a", argv[arg]))
+        {
+            sorting_algorithm_t alg;
+
+            ++arg;
+            if (arg >= argc)
+            {
+                fprintf(stderr, "ERROR: expected algorithm name.\n");
+                usage(argv[0]);
+                return EXIT_FAILURE;
+            }
+
+            alg = parse_sorting_algorithm(argv[arg]);
+            if (alg == unknown_sort_algorithm)
+            {
+                fprintf(stderr, "ERROR: unknown algorithm name '%s'.\n", argv[arg]);
+                usage(argv[0]);
+                return EXIT_FAILURE;
+            }
+            if (chosen_algs[(int) alg] == 0)
+            {
+                chosen_algs[(int) alg] = 1;
+                ++num_algs;
+            }
+        }
+        else if (!strcmp("-h", argv[arg]))
+        {
+            opt_help = 1;
+        }
+        else if (!strcmp("-n", argv[arg]))
+        {
+            ++arg;
+            if (arg >= argc)
+            {
+                fprintf(stderr, "ERROR: expected array size.\n");
+                usage(argv[0]);
+                return EXIT_FAILURE;
+            }
+            opt_n = atol(argv[arg]);
+        }
+        else if (!strcmp("-r", argv[arg]))
+        {
+            ++arg;
+            if (arg >= argc)
+            {
+                fprintf(stderr, "ERROR: expected number of runs.\n");
+                usage(argv[0]);
+                return EXIT_FAILURE;
+            }
+            opt_num_runs = atol(argv[arg]);
+        }
+        else if (!strcmp("-s", argv[arg]))
+        {
+            ++arg;
+            if (arg >= argc)
+            {
+                fprintf(stderr, "ERROR: expected seed for random number generator.\n");
+                usage(argv[0]);
+                return EXIT_FAILURE;
+            }
+            opt_seed = atoi(argv[arg]);
+        }
+        else if (!strcmp("-v", argv[arg]))
+        {
+            opt_verbose = 1;
+        }
+        else if (!strcmp("-x", argv[arg]))
+        {
+            opt_sort_special = 1;
+        }
+    }
+
+    if (opt_help)
+    {
+        usage(argv[0]);
+        return EXIT_SUCCESS;
+    }
+
+    if (opt_verbose)
+    {
+        printf("Options:\n");
+        printf("* Array size: %lu\n", opt_n);
+        printf("* Number of runs: %lu\n", opt_num_runs);
+        printf("* Seed for random number generation: %u\n", opt_seed);
+        printf("* Sorts special instances: %d\n", opt_sort_special);
+        printf("* Algorithms:\n");
+        j = 0;
+        for (i = 0; i < NUM_SORTING_ALGORITHMS; ++i)
+        {
+            if (j > 0)
+            {
+                printf(", ");
+            }
+            if (chosen_algs[i] == 1)
+            {
+                print_sorting_algorithm(stdout, i);
+                ++j;
+            }
+        }
+    }
+
+    if (num_algs == 0)
+    {
+        fprintf(stderr, "ERROR: at least one sorting algorithm must be specified.\n");
+        usage(argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    opt_algs = malloc(num_algs*sizeof(sorting_algorithm_t));
+    if (opt_algs == NULL)
+    {
+        upo_throw_sys_error("Unable to allocate memory for sorting algorithms");
+    }
+
+    j = 0;
+    for (i = 0; i < NUM_SORTING_ALGORITHMS; ++i)
+    {
+        if (chosen_algs[i] == 1)
+        {
+            opt_algs[j++] = (sorting_algorithm_t) i;
+        }
+    }
+
+    compare_algorithms(opt_algs, num_algs, opt_n, opt_seed, opt_num_runs, opt_sort_special, opt_verbose);
+
+    free(opt_algs);
+
+    return EXIT_SUCCESS;
+}
diff --git a/alglib/apps/use_timer b/alglib/apps/use_timer
deleted file mode 100755
index 44d9493fca8b550e86719e624198da3485e5be0b..0000000000000000000000000000000000000000
Binary files a/alglib/apps/use_timer and /dev/null differ
diff --git a/alglib/bin/libupoalglib_s.a b/alglib/bin/libupoalglib_s.a
deleted file mode 100644
index 78cd1b307acb504525df34bb59e3bf16afe0103c..0000000000000000000000000000000000000000
Binary files a/alglib/bin/libupoalglib_s.a and /dev/null differ
diff --git a/alglib/include/upo/sort.h b/alglib/include/upo/sort.h
new file mode 100644
index 0000000000000000000000000000000000000000..4bc2841925b1e07346397a1f7760680b0b850552
--- /dev/null
+++ b/alglib/include/upo/sort.h
@@ -0,0 +1,95 @@
+/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */
+
+/**
+ * \file upo/sort.h
+ *
+ * \brief Sorting algorithms.
+ *
+ * \author Your Name
+ *
+ * \copyright 2015 University of Piemonte Orientale, Computer Science Institute
+ *
+ *  This file is part of UPOalglib.
+ *
+ *  UPOalglib is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  UPOalglib is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with UPOalglib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UPO_SORT_H
+#define UPO_SORT_H
+
+
+#include <stddef.h>
+
+
+/** \brief Type definition for comparison functions used to compare two elements */
+typedef int (*upo_sort_comparator_t)(const void*, const void*);
+
+
+/**
+ * \brief Sorts the given array according to the insertion sort algorithm.
+ *
+ * \param base Pointer to the start of the input array.
+ * \param n Number of elements in the input array.
+ * \param size The size (in bytes) of each element of the array.
+ * \param cmp Pointer to the comparison function used to sort the array in
+ *  ascending order.
+ *  The comparison function is called with two arguments that point to the
+ *  objects being compared and must return an interger less than, equal to, or
+ *  greater than zero if the first argument is considered to be respectively
+ *  less than, equal to, or greater than the second.
+ *
+ * Insertion sort uses \f$\sim n^2/4\f$ compares and \f$\sim n^2/4\f$ exchanges
+ * to sort a randomly ordered array with distinct keys, on the average.
+ * The worst case is \f$\sim n^2/2\f$ compares and \f$\sim n^2/2\f$ exchanges,
+ * and the best case is \f$n-1\f$ compares and \f$0\f$ exchanges.
+ * The time complexity of insertion sort is \f$\Theta(n^2)\f$ in the worst case.
+ */
+void upo_insertion_sort(void *base, size_t n, size_t size, upo_sort_comparator_t cmp);
+
+/**
+ * \brief Sorts the given array according to the merge sort algorithm.
+ *
+ * \param base Pointer to the start of the input array.
+ * \param n Number of elements in the input array.
+ * \param size The size (in bytes) of each element of the array.
+ * \param cmp Pointer to the comparison function used to sort the array in
+ *  ascending order.
+ *  The comparison function is called with two arguments that point to the
+ *  objects being compared and must return an interger less than, equal to, or
+ *  greater than zero if the first argument is considered to be respectively
+ *  less than, equal to, or greater than the second.
+ *
+ * Merge sort performs between $\frac{1}{2} n \log n$ and $n \log n$ compares
+ * and at most $6n \log n$ array accesses.
+ *
+ */
+void upo_merge_sort(void *base, size_t n, size_t size, upo_sort_comparator_t cmp);
+
+/**
+ * \brief Sorts the given array according to the quick sort algorithm.
+ *
+ * \param base Pointer to the start of the input array.
+ * \param n Number of elements in the input array.
+ * \param size The size (in bytes) of each element of the array.
+ * \param cmp Pointer to the comparison function used to sort the array in
+ *  ascending order.
+ *  The comparison function is called with two arguments that point to the
+ *  objects being compared and must return an interger less than, equal to, or
+ *  greater than zero if the first argument is considered to be respectively
+ *  less than, equal to, or greater than the second.
+ */
+void upo_quick_sort(void *base, size_t n, size_t size, upo_sort_comparator_t cmp);
+
+
+#endif /* UPO_SORT_H */
diff --git a/alglib/src/hires_timer.o b/alglib/src/hires_timer.o
deleted file mode 100644
index f976c05f8f5b3685f81ce68db0d030bcda759ef5..0000000000000000000000000000000000000000
Binary files a/alglib/src/hires_timer.o and /dev/null differ
diff --git a/alglib/src/io.o b/alglib/src/io.o
deleted file mode 100644
index 404edcd4abb5c292a4214ebe0ccf5aaae1a118ba..0000000000000000000000000000000000000000
Binary files a/alglib/src/io.o and /dev/null differ
diff --git a/alglib/src/random.o b/alglib/src/random.o
deleted file mode 100644
index 5edb9d05490d837733412b02e4512421b6999bbf..0000000000000000000000000000000000000000
Binary files a/alglib/src/random.o and /dev/null differ
diff --git a/alglib/src/sort.c b/alglib/src/sort.c
new file mode 100644
index 0000000000000000000000000000000000000000..5346151b098631468d52886b482c036f64ca42f7
--- /dev/null
+++ b/alglib/src/sort.c
@@ -0,0 +1,56 @@
+/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */
+
+/*
+ * Copyright 2015 University of Piemonte Orientale, Computer Science Institute
+ *
+ * This file is part of UPOalglib.
+ *
+ * UPOalglib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * UPOalglib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with UPOalglib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include "sort_private.h"
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void upo_insertion_sort(void *base, size_t n, size_t size, upo_sort_comparator_t cmp)
+{
+    unsigned char *last_copy = malloc(size);
+    for (size_t i = 1; i < n; ++i) {
+        unsigned char *curr = (unsigned char *)base + i * size;
+        unsigned char *pos = upo_insertion_sort_insert_pos(base, curr, i + 1, size, cmp);
+        memcpy(last_copy, curr, size);
+        memmove(pos + size, pos, curr - pos);
+        memcpy(pos, last_copy, size);
+    }
+    free(last_copy);
+}
+
+void upo_merge_sort(void *base, size_t n, size_t size, upo_sort_comparator_t cmp)
+{
+    /* TO STUDENTS:
+     *  Remove the following two lines and put here your implementation. */
+    fprintf(stderr, "To be implemented!\n");
+    abort();
+}
+
+void upo_quick_sort(void *base, size_t n, size_t size, upo_sort_comparator_t cmp)
+{
+    /* TO STUDENTS:
+     *  Remove the following two lines and put here your implementation. */
+    fprintf(stderr, "To be implemented!\n");
+    abort();
+}
diff --git a/alglib/src/sort_private.c b/alglib/src/sort_private.c
new file mode 100644
index 0000000000000000000000000000000000000000..1f8193cf6c490162dfd20587abed84cd20120e50
--- /dev/null
+++ b/alglib/src/sort_private.c
@@ -0,0 +1,19 @@
+#include <assert.h>
+#include "sort_private.h"
+
+void *upo_insertion_sort_insert_pos(
+    const void *base,
+    const void *elem,
+    size_t n,
+    size_t size,
+    upo_sort_comparator_t cmp
+)
+{
+    for (size_t i = 0; i < n; ++i) {
+        if (cmp((unsigned char *)base + i * size, elem) >= 0) {
+            return (unsigned char *)base + i * size;
+        }
+    }
+    // unreachable
+    assert(0);
+}
diff --git a/alglib/src/sort_private.h b/alglib/src/sort_private.h
new file mode 100644
index 0000000000000000000000000000000000000000..a8144d9a3d5cd6d05a7b3515f7c3491891a8d86d
--- /dev/null
+++ b/alglib/src/sort_private.h
@@ -0,0 +1,61 @@
+/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */
+
+/**
+ * \file sort_private.h
+ *
+ * \brief Private header for sorting algorithms.
+ *
+ * \author Your Name
+ *
+ * \copyright 2015 University of Piemonte Orientale, Computer Science Institute
+ *
+ *  This file is part of UPOalglib.
+ *
+ *  UPOalglib is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  UPOalglib is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with UPOalglib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UPO_SORT_PRIVATE_H
+#define UPO_SORT_PRIVATE_H
+
+#include <stddef.h>
+#include <upo/sort.h>
+
+void *upo_insertion_sort_insert_pos(
+    const void *base,
+    const void *elem,
+    size_t n,
+    size_t size,
+    upo_sort_comparator_t cmp
+);
+
+/* TO STUDENTS:
+ *
+ *  This file is currently "empty".
+ *  Here you can put the prototypes of auxiliary "private" functions that are
+ *  internally used by "public" functions.
+ *  For instance, you can declare the prototype of the function that performs
+ *  the "merge" operation in the merge-sort algorithm:
+ *    static void upo_merge_sort_merge(void *base, size_t lo, size_t mid, size_t hi, size_t size, upo_sort_comparator_t cmp);
+ *  Also, you can declare the prototype of the function that performs the
+ *  the recursion in the merge-sort algorithm:
+ *    static void upo_merge_sort_rec(void *base, size_t lo, size_t hi, size_t size, upo_sort_comparator_t cmp);
+ *  Further, you can declare the prototype of the function that performs the
+ *  "partition" operation in the quick-sort algorithm:
+ *    static size_t upo_quick_sort_partition(void *base, size_t lo, size_t hi, size_t size, upo_sort_comparator_t cmp);
+ *  And so on.
+ *
+ */
+
+
+#endif /* UPO_SORT_PRIVATE_H */
diff --git a/alglib/src/stack.o b/alglib/src/stack.o
deleted file mode 100644
index 23a1dffd36afeef3d6860b679f1ab0a59e3d4b64..0000000000000000000000000000000000000000
Binary files a/alglib/src/stack.o and /dev/null differ
diff --git a/alglib/src/timer.o b/alglib/src/timer.o
deleted file mode 100644
index b253d45de6cf5cf8bdcfdac22ce63d24ff3f3e63..0000000000000000000000000000000000000000
Binary files a/alglib/src/timer.o and /dev/null differ
diff --git a/alglib/src/utility.o b/alglib/src/utility.o
deleted file mode 100644
index dafc70a2ddcea3ee9ab662735dd2a676f8e95746..0000000000000000000000000000000000000000
Binary files a/alglib/src/utility.o and /dev/null differ
diff --git a/alglib/test/mk/sort.mk b/alglib/test/mk/sort.mk
new file mode 100644
index 0000000000000000000000000000000000000000..5f639d65609e07af2b0432b20631eac73d5c6596
--- /dev/null
+++ b/alglib/test/mk/sort.mk
@@ -0,0 +1 @@
+test_targets += test_sort
diff --git a/alglib/test/test_sort.c b/alglib/test/test_sort.c
new file mode 100644
index 0000000000000000000000000000000000000000..0f085da11e069216b0b692df7ab62fd64c7d61c8
--- /dev/null
+++ b/alglib/test/test_sort.c
@@ -0,0 +1,164 @@
+/* vim: set tabstop=4 expandtab shiftwidth=4 softtabstop=4: */
+
+/*
+ * Copyright 2015 University of Piemonte Orientale, Computer Science Institute
+ *
+ * This file is part of UPOalglib.
+ *
+ * UPOalglib is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * UPOalglib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with UPOalglib.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <upo/error.h>
+#include <upo/sort.h>
+
+
+/* Types and global data */
+
+#define N 9
+
+struct item_s
+{
+    long id;
+    char *name;
+};
+typedef struct item_s item_t;
+
+static double da[] = {3.0,1.3,0.4,7.8,13.2,-1.1,6.0,-3.2,78};
+static double expect_da[] = {-3.2,-1.1,0.4,1.3,3.0,6.0,7.8,13.2,78.0};
+static const char *sa[] = {"The","quick","brown","fox","jumps","over","the","lazy","dog"};
+static const char *expect_sa[] = {"The","brown","dog","fox","jumps","lazy","over","quick","the"};
+static item_t ca[] = {{9,"john"},{8,"jane"},{7,"mary"},{6,"anthony"},{5,"stevie"},{4,"bob"},{3,"ann"},{2,"claire"},{1,"alice"}};
+static item_t expect_ca[] = {{1,"alice"},{2,"claire"},{3,"ann"},{4,"bob"},{5,"stevie"},{6,"anthony"},{7,"mary"},{8,"jane"},{9,"john"}};
+
+/* Comparators */
+
+static int double_comparator(const void *a, const void *b);
+static int string_comparator(const void *a, const void *b);
+static int item_comparator(const void *a, const void *b);
+
+/* Test cases */
+void test_sort_algorithm(void (*sort)(void*,size_t,size_t,upo_sort_comparator_t));
+static void test_insertion_sort();
+static void test_merge_sort();
+static void test_quick_sort();
+
+
+int double_comparator(const void *a, const void *b)
+{
+    const double *aa = a;
+    const double *bb = b;
+
+    return (*aa > *bb) - (*aa < *bb);
+}
+
+int string_comparator(const void *a, const void *b)
+{
+    const char **aa = (const char**) a;
+    const char **bb = (const char**) b;
+
+    return strcmp(*aa, *bb);
+}
+
+int item_comparator(const void *a, const void *b)
+{
+    const item_t *aa = a;
+    const item_t *bb = b;
+
+    return (aa->id > bb->id) - (aa->id < bb->id);
+}
+
+void test_sort_algorithm(void (*sort)(void*,size_t,size_t,upo_sort_comparator_t))
+{
+    int ok = 1;
+    size_t i = 0;
+    double *da_clone = NULL;
+    char **sa_clone = NULL;
+    item_t *ca_clone = NULL;
+
+    ok = 1;
+    da_clone = malloc(N*sizeof(double));
+    assert( da_clone != NULL );
+    memcpy(da_clone, da, N*sizeof(double));
+    sort(da_clone, N, sizeof(double), double_comparator);
+    for (i = 0; i < N; ++i)
+    {
+        ok &= !double_comparator(&da_clone[i], &expect_da[i]);
+    }
+    free(da_clone);
+    assert( ok );
+
+    ok = 1;
+    sa_clone = malloc(N*sizeof(char*));
+    assert( sa_clone != NULL );
+    memcpy(sa_clone, sa, N*sizeof(char*));
+    sort(sa_clone, N, sizeof(char*), string_comparator);
+    for (i = 0; i < N; ++i)
+    {
+        ok &= !string_comparator(&sa_clone[i], &expect_sa[i]);
+    }
+    free(sa_clone);
+    assert( ok );
+
+    ok = 1;
+    ca_clone = malloc(N*sizeof(item_t));
+    assert( ca_clone != NULL );
+    memcpy(ca_clone, ca, N*sizeof(item_t));
+    sort(ca_clone, N, sizeof(item_t), item_comparator);
+    for (i = 0; i < N; ++i)
+    {
+        ok &= !item_comparator(&ca_clone[i], &expect_ca[i]);
+    }
+    free(ca_clone);
+    assert( ok );
+}
+
+void test_insertion_sort()
+{
+    test_sort_algorithm(upo_insertion_sort);
+}
+
+void test_merge_sort()
+{
+    test_sort_algorithm(upo_merge_sort);
+}
+
+void test_quick_sort()
+{
+    test_sort_algorithm(upo_quick_sort);
+}
+
+
+int main()
+{
+    printf("Test case 'insertion sort'... ");
+    fflush(stdout);
+    test_insertion_sort();
+    printf("OK\n");
+
+    printf("Test case 'merge sort'... ");
+    fflush(stdout);
+    test_merge_sort();
+    printf("OK\n");
+
+    printf("Test case 'quick sort'... ");
+    fflush(stdout);
+    test_quick_sort();
+    printf("OK\n");
+
+    return 0;
+}
diff --git a/alglib/vgcore.5125 b/alglib/vgcore.5125
new file mode 100644
index 0000000000000000000000000000000000000000..578f0a95feb1bb21b79c5efc325b6cc84aa966f0
Binary files /dev/null and b/alglib/vgcore.5125 differ