X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fmath%2Fmerge.c;h=20d26c0420f889f15256b431d02f3c6645ff0317;hb=2f5ea6bbd8c8c8a01f87bf3cdb9e1e1eab6e7fd6;hp=2ff57c6e5ba6fa0a88a9237f95782cb55332bbd6;hpb=14aac9fe7a7efbb6c9bded2ed5969a643cb76645;p=pspp diff --git a/src/math/merge.c b/src/math/merge.c index 2ff57c6e5b..20d26c0420 100644 --- a/src/math/merge.c +++ b/src/math/merge.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2009 Free Software Foundation, Inc. + Copyright (C) 2007, 2009-11, 14 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,17 +19,17 @@ performance regression. */ #include -#include +#include "math/merge.h" -#include -#include -#include -#include -#include -#include -#include +#include "data/case.h" +#include "data/casereader.h" +#include "data/casewriter.h" +#include "data/subcase.h" +#include "libpspp/array.h" +#include "libpspp/assertion.h" +#include "libpspp/taint.h" -#include "xalloc.h" +#include "gl/xalloc.h" #define MAX_MERGE_ORDER 7 @@ -44,18 +44,24 @@ struct merge struct subcase ordering; struct merge_input inputs[MAX_MERGE_ORDER]; size_t input_cnt; - size_t value_cnt; + struct caseproto *proto; + + merge_distinct_combine_func *combine; + void *aux; }; static void do_merge (struct merge *m); struct merge * -merge_create (const struct subcase *ordering, size_t value_cnt) +merge_create (const struct subcase *ordering, const struct caseproto *proto, + merge_distinct_combine_func *combine, void *aux) { struct merge *m = xmalloc (sizeof *m); subcase_clone (&m->ordering, ordering); m->input_cnt = 0; - m->value_cnt = value_cnt; + m->proto = caseproto_ref (proto); + m->combine = combine; + m->aux = aux; return m; } @@ -69,6 +75,7 @@ merge_destroy (struct merge *m) subcase_destroy (&m->ordering); for (i = 0; i < m->input_cnt; i++) casereader_destroy (m->inputs[i].reader); + caseproto_unref (m->proto); free (m); } } @@ -97,7 +104,7 @@ merge_make_reader (struct merge *m) } else if (m->input_cnt == 0) { - struct casewriter *writer = mem_writer_create (m->value_cnt); + struct casewriter *writer = mem_writer_create (m->proto); r = casewriter_make_reader (writer); } else @@ -127,11 +134,12 @@ static void do_merge (struct merge *m) { struct casewriter *w; + struct ccase *prev_case; size_t i; assert (m->input_cnt > 1); - w = tmpfile_writer_create (m->value_cnt); + w = tmpfile_writer_create (m->proto); for (i = 0; i < m->input_cnt; i++) taint_propagate (casereader_get_taint (m->inputs[i].reader), casewriter_get_taint (w)); @@ -139,8 +147,11 @@ do_merge (struct merge *m) for (i = 0; i < m->input_cnt; ) if (read_input_case (m, i)) i++; + + prev_case = NULL; while (m->input_cnt > 0) { + struct ccase *min_case; size_t min; min = 0; @@ -149,11 +160,28 @@ do_merge (struct merge *m) &m->ordering, m->inputs[min].c) < 0) min = i; - casewriter_write (w, m->inputs[min].c); + min_case = m->inputs[min].c; + if (m->combine != NULL) + { + if (prev_case == NULL) + prev_case = min_case; + else if (subcase_equal (&m->ordering, min_case, + &m->ordering, prev_case)) + prev_case = m->combine (prev_case, min_case, m->aux); + else + { + casewriter_write (w, prev_case); + prev_case = min_case; + } + } + else + casewriter_write (w, min_case); + read_input_case (m, min); } + if (prev_case != NULL) + casewriter_write (w, prev_case); m->input_cnt = 1; m->inputs[0].reader = casewriter_make_reader (w); } -