X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fmath%2Fsort.c;h=827c2314f2e6e54ceab3a3cb597fbc8287993e31;hb=19d0debdc5b72e1bb6c79956403a4d3bc054f300;hp=20d8dde73cb81a34fca282eab444d10760a300ec;hpb=a19b858e0ac3c69e4a28c0ca6d8674427268a863;p=pspp-builds.git diff --git a/src/math/sort.c b/src/math/sort.c index 20d8dde7..827c2314 100644 --- a/src/math/sort.c +++ b/src/math/sort.c @@ -18,30 +18,37 @@ 02110-1301, USA. */ #include + #include "sort.h" -#include -#include + +#include #include +#include #include #include -#include -#include -#include + +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include - #include -#include #include -#include -#include + +#include "minmax.h" #include "gettext.h" #define _(msgid) gettext (msgid) -#include - /* These should only be changed for testing purposes. */ int min_buffers = 64; int max_buffers = INT_MAX; @@ -54,61 +61,63 @@ static struct casefile *do_internal_sort (struct casereader *, static struct casefile *do_external_sort (struct casereader *, const struct sort_criteria *); -/* Gets ready to sort the active file, either in-place or to a - separate casefile. */ -static bool -prepare_to_sort_active_file (void) -{ - bool ok; - - /* Cancel temporary transformations and PROCESS IF. */ - if (temporary != 0) - cancel_temporary (); - expr_free (process_if_expr); - process_if_expr = NULL; - - /* Make sure source cases are in a storage source. */ - ok = procedure (NULL, NULL); - assert (case_source_is_class (vfm_source, &storage_source_class)); - - return ok; -} /* Sorts the active file in-place according to CRITERIA. - Returns nonzero if successful. */ -int -sort_active_file_in_place (const struct sort_criteria *criteria) + Returns true if successful. */ +bool +sort_active_file_in_place (struct dataset *ds, + const struct sort_criteria *criteria) { - struct casefile *src, *dst; + struct casefile *in, *out; + + proc_cancel_temporary_transformations (ds); + if (!procedure (ds, NULL, NULL)) + return false; - if (!prepare_to_sort_active_file ()) - return 0; + in = proc_capture_output (ds); + out = sort_execute (casefile_get_destructive_reader (in), criteria); + if (out == NULL) + return false; - src = storage_source_get_casefile (vfm_source); - dst = sort_execute (casefile_get_destructive_reader (src), criteria); - free_case_source (vfm_source); - vfm_source = NULL; + proc_set_source (ds, storage_source_create (out)); + return true; +} - if (dst == NULL) - return 0; +/* Data passed to sort_to_casefile_callback(). */ +struct sort_to_casefile_cb_data + { + const struct sort_criteria *criteria; + struct casefile *output; + }; - vfm_source = storage_source_create (dst); - return 1; +/* Sorts casefile CF according to the criteria in CB_DATA. */ +static bool +sort_to_casefile_callback (const struct casefile *cf, void *cb_data_) +{ + struct sort_to_casefile_cb_data *cb_data = cb_data_; + cb_data->output = sort_execute (casefile_get_reader (cf, NULL), cb_data->criteria); + return cb_data->output != NULL; } /* Sorts the active file to a separate casefile. If successful, returns the sorted casefile. Returns a null pointer on failure. */ struct casefile * -sort_active_file_to_casefile (const struct sort_criteria *criteria) +sort_active_file_to_casefile (struct dataset *ds, + const struct sort_criteria *criteria) { - struct casefile *src; + struct sort_to_casefile_cb_data cb_data; - if (!prepare_to_sort_active_file ()) - return NULL; + proc_cancel_temporary_transformations (ds); - src = storage_source_get_casefile (vfm_source); - return sort_execute (casefile_get_reader (src), criteria); + cb_data.criteria = criteria; + cb_data.output = NULL; + if (!multipass_procedure (ds, sort_to_casefile_callback, &cb_data)) + { + casefile_destroy (cb_data.output); + return NULL; + } + return cb_data.output; } @@ -132,7 +141,7 @@ struct indexed_case unsigned long idx; /* Index to allow for stable sorting. */ }; -static int compare_indexed_cases (const void *, const void *, void *); +static int compare_indexed_cases (const void *, const void *, const void *); /* If the data is in memory, do an internal sort and return a new casefile for the data. Otherwise, return a null pointer. */ @@ -152,7 +161,7 @@ do_internal_sort (struct casereader *reader, return NULL; case_cnt = casefile_get_case_cnt (src); - dst = casefile_create (casefile_get_value_cnt (src)); + dst = fastfile_create (casefile_get_value_cnt (src)); if (case_cnt != 0) { struct indexed_case *cases = nmalloc (sizeof *cases, case_cnt); @@ -164,7 +173,7 @@ do_internal_sort (struct casereader *reader, { bool ok = casereader_read_xfer (reader, &cases[i].c); if (!ok) - abort (); + NOT_REACHED (); cases[i].idx = i; } @@ -174,7 +183,7 @@ do_internal_sort (struct casereader *reader, for (i = 0; i < case_cnt; i++) casefile_append_xfer (dst, &cases[i].c); if (casefile_error (dst)) - abort (); + NOT_REACHED (); free (cases); } @@ -193,9 +202,9 @@ do_internal_sort (struct casereader *reader, at A and B, with a "last resort" comparison for stability, and returns a strcmp()-type result. */ static int -compare_indexed_cases (const void *a_, const void *b_, void *criteria_) +compare_indexed_cases (const void *a_, const void *b_, const void *criteria_) { - struct sort_criteria *criteria = criteria_; + const struct sort_criteria *criteria = criteria_; const struct indexed_case *a = a_; const struct indexed_case *b = b_; int result = compare_record (&a->c, &b->c, criteria); @@ -301,19 +310,18 @@ struct initial_run_state int okay; /* Zero if an error has been encountered. */ }; -static const struct case_sink_class sort_sink_class; - static bool destroy_initial_run_state (struct initial_run_state *); -static void process_case (struct initial_run_state *, const struct ccase *, - size_t); +static void process_case (struct initial_run_state *, + const struct ccase *, size_t); static int allocate_cases (struct initial_run_state *); static void output_record (struct initial_run_state *); static void start_run (struct initial_run_state *); static void end_run (struct initial_run_state *); static int compare_record_run (const struct record_run *, const struct record_run *, - struct initial_run_state *); -static int compare_record_run_minheap (const void *, const void *, void *); + const struct initial_run_state *); +static int compare_record_run_minheap (const void *, const void *, + const void *); /* Reads cases from READER and composes initial runs in XSRT. */ static int @@ -356,7 +364,8 @@ write_runs (struct external_sort *xsrt, struct casereader *reader) /* Add a single case to an initial run. */ static void -process_case (struct initial_run_state *irs, const struct ccase *c, size_t idx) +process_case (struct initial_run_state *irs, const struct ccase *c, + size_t idx) { struct record_run *rr; @@ -475,7 +484,7 @@ compare_record (const struct ccase *a, const struct ccase *b, static int compare_record_run (const struct record_run *a, const struct record_run *b, - struct initial_run_state *irs) + const struct initial_run_state *irs) { int result = a->run < b->run ? -1 : a->run > b->run; if (result == 0) @@ -489,7 +498,7 @@ compare_record_run (const struct record_run *a, on the current record according to SCP, but in descending order. */ static int -compare_record_run_minheap (const void *a, const void *b, void *irs) +compare_record_run_minheap (const void *a, const void *b, const void *irs) { return -compare_record_run (a, b, irs); } @@ -500,7 +509,7 @@ start_run (struct initial_run_state *irs) { irs->run++; irs->case_cnt = 0; - irs->casefile = casefile_create (irs->xsrt->value_cnt); + irs->casefile = fastfile_create (irs->xsrt->value_cnt); casefile_to_disk (irs->casefile); case_nullify (&irs->last_output); } @@ -580,7 +589,7 @@ merge (struct external_sort *xsrt) { while (xsrt->run_cnt > 1) { - int order = min (MAX_MERGE_ORDER, xsrt->run_cnt); + int order = MIN (MAX_MERGE_ORDER, xsrt->run_cnt); int idx = choose_merge (xsrt->runs, xsrt->run_cnt, order); xsrt->runs[idx] = merge_once (xsrt, xsrt->runs + idx, order); remove_range (xsrt->runs, xsrt->run_cnt, sizeof *xsrt->runs, @@ -665,7 +674,7 @@ merge_once (struct external_sort *xsrt, } /* Create output file. */ - output = casefile_create (xsrt->value_cnt); + output = fastfile_create (xsrt->value_cnt); casefile_to_disk (output); /* Merge. */