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