From: Florian Forster Date: Wed, 11 Mar 2009 08:10:26 +0000 (+0100) Subject: src/sn-oddevenmerge.c: Create a OEM-network. X-Git-Tag: v1.0.0~82 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=952617991a3813a504f51679ff4dc7529fe3e261;p=sort-networks.git src/sn-oddevenmerge.c: Create a OEM-network. The OEM code in sn_network.c has been improved to handle networks with numbers of inputs that are *not* a power of two. --- diff --git a/src/Makefile b/src/Makefile index 516313f..135e30e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,8 +2,9 @@ CC = gcc CFLAGS = -Wall -Werror -std=c99 -O3 -pthread #CFLAGS = -Wall -Werror -std=c99 -O0 -g -pthread -APPLICATIONS = sn-apply sn-check-bf sn-cut sn-evolution sn-merge \ - sn-normalize sn-show sn-tex +APPLICATIONS = sn-apply sn-batcher sn-check-bf sn-cut sn-cut-loop \ + sn-evolution sn-find-9 sn-merge \ + sn-normalize sn-oddevenmerge sn-show sn-tex POPULATION_CFLAGS = -I/tmp/sifnfors/libpopulation/include @@ -41,6 +42,8 @@ sn-merge: sn-merge.c sn_network.o sn_stage.o sn_comparator.o sn_random.o sn-normalize: sn-normalize.c sn_network.o sn_stage.o sn_comparator.o sn_random.o +sn-oddevenmerge: sn-oddevenmerge.c sn_network.o sn_stage.o sn_comparator.o sn_random.o + sn-show: sn-show.c sn_network.o sn_stage.o sn_comparator.o sn_random.o sn-tex: sn-tex.c sn_network.o sn_stage.o sn_comparator.o sn_random.o diff --git a/src/sn-evolution.c b/src/sn-evolution.c index 62b01eb..86bdfba 100644 --- a/src/sn-evolution.c +++ b/src/sn-evolution.c @@ -1,6 +1,6 @@ /** * collectd - src/sn-evolution.c - * Copyright (C) 2008 Florian octo Forster + * Copyright (C) 2008,2009 Florian octo Forster * * 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 the @@ -52,6 +52,7 @@ char *strdup (const char *s); static uint64_t iteration_counter = 0; static int inputs_num = 16; +static int inputs_num_is_power_of_two = 1; static char *initial_input_file = NULL; static char *best_output_file = NULL; @@ -224,7 +225,7 @@ static int create_offspring (void) assert (p1 != NULL); /* combine the two parents */ - n = sn_network_combine (p0, p1); + n = sn_network_combine (p0, p1, inputs_num_is_power_of_two); sn_network_destroy (p0); sn_network_destroy (p1); @@ -371,6 +372,7 @@ int main (int argc, char **argv) { sn_network_t *n; + int tmp; n = sn_network_read_file (initial_input_file); if (n == NULL) @@ -381,6 +383,23 @@ int main (int argc, char **argv) inputs_num = SN_NETWORK_INPUT_NUM(n); + /* Determine if `inputs_num' is a power of two. If so, more merge + * algorithms can be used. */ + tmp = inputs_num; + inputs_num_is_power_of_two = 1; + while (tmp > 0) + { + if ((tmp % 2) != 0) + { + if (tmp == 1) + inputs_num_is_power_of_two = 1; + else + inputs_num_is_power_of_two = 0; + break; + } + tmp = tmp >> 1; + } + population_insert (population, n); sn_network_destroy (n); } diff --git a/src/sn-merge.c b/src/sn-merge.c index 2c884a5..db0b4cd 100644 --- a/src/sn-merge.c +++ b/src/sn-merge.c @@ -60,7 +60,7 @@ int main (int argc, char **argv) return (1); } - n = sn_network_combine (n0, n1); + n = sn_network_combine (n0, n1, /* is power of two = */ 0); sn_network_destroy (n0); sn_network_destroy (n1); diff --git a/src/sn-oddevenmerge.c b/src/sn-oddevenmerge.c new file mode 100644 index 0000000..8cb64f6 --- /dev/null +++ b/src/sn-oddevenmerge.c @@ -0,0 +1,64 @@ +/** + * collectd - src/sn-oddevenmerge.c + * Copyright (C) 2008,2009 Florian octo Forster + * + * 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 the + * Free Software Foundation; only version 2 of the License is applicable. + * + * This program 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian octo Forster + **/ + +#ifndef _ISOC99_SOURCE +# define _ISOC99_SOURCE +#endif +#ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200112L +#endif + +#include +#include + +#include "sn_network.h" + +int main (int argc, char **argv) +{ + sn_network_t *n; + size_t inputs_num; + + if (argc != 2) + { + printf ("Usage: %s \n", argv[0]); + return (0); + } + + inputs_num = (size_t) atoi (argv[1]); + if (inputs_num < 2) + { + fprintf (stderr, "Invalid number of inputs: %zu\n", inputs_num); + return (1); + } + + n = sn_network_create_odd_even_mergesort (inputs_num); + if (n == NULL) + { + printf ("n == NULL!\n"); + return (1); + } + + sn_network_write (n, stdout); + + return (0); +} /* int main */ + +/* vim: set shiftwidth=2 softtabstop=2 : */ diff --git a/src/sn_network.c b/src/sn_network.c index 5576b86..6308b90 100644 --- a/src/sn_network.c +++ b/src/sn_network.c @@ -1,6 +1,6 @@ /** * collectd - src/sn_network.c - * Copyright (C) 2008 Florian octo Forster + * Copyright (C) 2008,2009 Florian octo Forster * * 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 the @@ -76,6 +76,64 @@ void sn_network_destroy (sn_network_t *n) /* {{{ */ free (n); } /* }}} void sn_network_destroy */ +sn_network_t *sn_network_create_odd_even_mergesort (int inputs_num) /* {{{ */ +{ + sn_network_t *n; + + n = sn_network_create (inputs_num); + + assert (inputs_num > 0); + if (inputs_num == 1) + { + return (n); + } + if (inputs_num == 2) + { + sn_stage_t *s; + sn_comparator_t c; + + c.min = 0; + c.max = 1; + + s = sn_stage_create (/* depth = */ 0); + sn_stage_comparator_add (s, &c); + sn_network_stage_add (n, s); + + return (n); + } + else + { + sn_network_t *n_left; + sn_network_t *n_right; + int inputs_left; + int inputs_right; + + inputs_left = inputs_num / 2; + inputs_right = inputs_num - inputs_left; + + n_left = sn_network_create_odd_even_mergesort (inputs_left); + if (n_left == NULL) + return (NULL); + + n_right = sn_network_create_odd_even_mergesort (inputs_right); + if (n_right == NULL) + { + sn_network_destroy (n_left); + return (NULL); + } + + n = sn_network_combine_odd_even_merge (n_left, n_right); + + sn_network_destroy (n_left); + sn_network_destroy (n_right); + + if (n != NULL) + sn_network_compress (n); + + return (n); + } +} /* }}} sn_network_t *sn_network_create_odd_even_mergesort */ + int sn_network_stage_add (sn_network_t *n, sn_stage_t *s) /* {{{ */ { sn_stage_t **temp; @@ -430,106 +488,99 @@ static int sn_network_add_bitonic_merger (sn_network_t *n) /* {{{ */ return (0); } /* }}} int sn_network_add_bitonic_merger */ -static int sn_network_add_odd_even_merger_recursive (sn_network_t *n, /* {{{ */ - int *indizes, int indizes_num) +static int sn_network_add_odd_even_merger (sn_network_t *n, /* {{{ */ + int *indizes_left, int indizes_left_num, + int *indizes_right, int indizes_right_num) { - if (indizes_num > 2) + int tmp_left[indizes_left_num]; + int tmp_left_num; + int tmp_right[indizes_left_num]; + int tmp_right_num; + int max_index; + sn_stage_t *s; + int i; + + if ((indizes_left_num == 0) || (indizes_right_num == 0)) + { + return (0); + } + else if ((indizes_left_num == 1) && (indizes_right_num == 1)) { sn_comparator_t c; sn_stage_t *s; - int indizes_half_num; - int *indizes_half; - int status; - int i; - indizes_half_num = indizes_num / 2; - indizes_half = (int *) malloc (indizes_num * sizeof (int)); - if (indizes_half == NULL) + c.min = *indizes_left; + c.max = *indizes_right; + + s = sn_stage_create (n->stages_num); + if (s == NULL) return (-1); - for (i = 0; i < indizes_half_num; i++) - { - indizes_half[i] = indizes[2 * i]; - indizes_half[indizes_half_num + i] = indizes[(2 * i) + 1]; - } + sn_stage_comparator_add (s, &c); + sn_network_stage_add (n, s); - status = sn_network_add_odd_even_merger_recursive (n, - indizes_half, indizes_half_num); - if (status != 0) - { - free (indizes_half); - return (status); - } + return (0); + } - status = sn_network_add_odd_even_merger_recursive (n, - indizes_half + indizes_half_num, indizes_half_num); - if (status != 0) - { - free (indizes_half); - return (status); - } + /* Merge odd sequences */ + tmp_left_num = (indizes_left_num + 1) / 2; + for (i = 0; i < tmp_left_num; i++) + tmp_left[i] = indizes_left[2 * i]; - free (indizes_half); + tmp_right_num = (indizes_right_num + 1) / 2; + for (i = 0; i < tmp_right_num; i++) + tmp_right[i] = indizes_right[2 * i]; - s = sn_stage_create (n->stages_num); - if (s == NULL) - return (-1); + sn_network_add_odd_even_merger (n, + tmp_left, tmp_left_num, + tmp_right, tmp_right_num); - for (i = 1; i < (indizes_num - 2); i += 2) - { - c.min = indizes[i]; - c.max = indizes[i + 1]; + /* Merge even sequences */ + tmp_left_num = indizes_left_num / 2; + for (i = 0; i < tmp_left_num; i++) + tmp_left[i] = indizes_left[(2 * i) + 1]; - sn_stage_comparator_add (s, &c); - } + tmp_right_num = indizes_right_num / 2; + for (i = 0; i < tmp_right_num; i++) + tmp_right[i] = indizes_right[(2 * i) + 1]; - sn_network_stage_add (n, s); - } + sn_network_add_odd_even_merger (n, + tmp_left, tmp_left_num, + tmp_right, tmp_right_num); + + /* Apply ``comparison-interchange'' operations. */ + s = sn_stage_create (n->stages_num); + + max_index = indizes_left_num + indizes_right_num; + if ((max_index % 2) == 0) + max_index -= 3; else + max_index -= 2; + + for (i = 1; i <= max_index; i += 2) { sn_comparator_t c; - sn_stage_t *s; - - assert (indizes_num == 2); - c.min = indizes[0]; - c.max = indizes[1]; + if (i < indizes_left_num) + c.min = indizes_left[i]; + else + c.min = indizes_right[i - indizes_left_num]; - s = sn_stage_create (n->stages_num); - if (s == NULL) - return (-1); + if ((i + 1) < indizes_left_num) + c.max = indizes_left[i + 1]; + else + c.max = indizes_right[i + 1 - indizes_left_num]; sn_stage_comparator_add (s, &c); - sn_network_stage_add (n, s); } - return (0); -} /* }}} int sn_network_add_odd_even_merger_recursive */ - -static int sn_network_add_odd_even_merger (sn_network_t *n) /* {{{ */ -{ - int *indizes; - int indizes_num; - int status; - int i; - - indizes_num = n->inputs_num; - indizes = (int *) malloc (indizes_num * sizeof (int)); - if (indizes == NULL) - return (-1); - - for (i = 0; i < indizes_num; i++) - indizes[i] = i; + sn_network_stage_add (n, s); - status = sn_network_add_odd_even_merger_recursive (n, - indizes, indizes_num); - - free (indizes); - return (status); -} /* }}} int sn_network_add_bitonic_merger */ + return (0); +} /* }}} int sn_network_add_odd_even_merger */ -static sn_network_t *sn_network_combine_bitonic (sn_network_t *n0, /* {{{ */ - sn_network_t *n1) +static sn_network_t *sn_network_combine_bitonic_shift (sn_network_t *n0, /* {{{ */ + sn_network_t *n1, int do_shift) { sn_network_t *n; sn_network_t *n1_clone; @@ -547,35 +598,77 @@ static sn_network_t *sn_network_combine_bitonic (sn_network_t *n0, /* {{{ */ sn_network_destroy (n1_clone); - shift = sn_bounded_random (0, SN_NETWORK_INPUT_NUM (n) - 1); + if (do_shift) + shift = sn_bounded_random (0, SN_NETWORK_INPUT_NUM (n) - 1); + else + shift = 0; + if (shift > 0) { - DPRINTF ("sn_network_combine_bitonic: Shifting by %i.\n", shift); + DPRINTF ("sn_network_combine_bitonic_shift: Shifting by %i.\n", shift); sn_network_shift (n, shift); } sn_network_add_bitonic_merger (n); return (n); +} /* }}} sn_network_t *sn_network_combine_bitonic_shift */ + +sn_network_t *sn_network_combine_bitonic (sn_network_t *n0, /* {{{ */ + sn_network_t *n1) +{ + return (sn_network_combine_bitonic_shift (n0, n1, /* do_shift = */ 0)); } /* }}} sn_network_t *sn_network_combine_bitonic */ -sn_network_t *sn_network_combine (sn_network_t *n0, /* {{{ */ +sn_network_t *sn_network_combine_odd_even_merge (sn_network_t *n0, /* {{{ */ sn_network_t *n1) { sn_network_t *n; + int indizes_left[n0->inputs_num]; + int indizes_left_num; + int indizes_right[n1->inputs_num]; + int indizes_right_num; + int status; + int i; + + indizes_left_num = n0->inputs_num; + indizes_right_num = n1->inputs_num; + for (i = 0; i < indizes_left_num; i++) + indizes_left[i] = i; + for (i = 0; i < indizes_right_num; i++) + indizes_right[i] = indizes_left_num + i; + + n = sn_network_concatenate (n0, n1); + if (n == NULL) + return (NULL); + + status = sn_network_add_odd_even_merger (n, + indizes_left, indizes_left_num, + indizes_right, indizes_right_num); + if (status != 0) + { + sn_network_destroy (n); + return (NULL); + } + + sn_network_compress (n); + return (n); +} /* }}} sn_network_t *sn_network_combine */ + +sn_network_t *sn_network_combine (sn_network_t *n0, /* {{{ */ + sn_network_t *n1, int is_power_of_two) +{ + sn_network_t *n; - if (sn_bounded_random (0, 2) < 2) + if ((is_power_of_two != 0) && (sn_bounded_random (0, 9) == 0)) { DPRINTF ("sn_network_combine: Using the bitonic merger.\n"); - n = sn_network_combine_bitonic (n0, n1); + n = sn_network_combine_bitonic_shift (n0, n1, /* do_shift = */ 1); } else { DPRINTF ("sn_network_combine: Using the odd-even merger.\n"); - n = sn_network_concatenate (n0, n1); - if (n == NULL) - return (NULL); - sn_network_add_odd_even_merger (n); + n = sn_network_combine_odd_even_merge (n0, n1); } sn_network_compress (n); diff --git a/src/sn_network.h b/src/sn_network.h index 3af9c72..ed96c3f 100644 --- a/src/sn_network.h +++ b/src/sn_network.h @@ -1,6 +1,6 @@ /** * collectd - src/sn_network.h - * Copyright (C) 2008 Florian octo Forster + * Copyright (C) 2008,2009 Florian octo Forster * * 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 the @@ -43,6 +43,8 @@ sn_network_t *sn_network_create (int inputs_num); sn_network_t *sn_network_clone (const sn_network_t *n); void sn_network_destroy (sn_network_t *n); +sn_network_t *sn_network_create_odd_even_mergesort (int inputs_num); + int sn_network_stage_add (sn_network_t *n, sn_stage_t *s); int sn_network_stage_remove (sn_network_t *n, int s_num); @@ -56,7 +58,10 @@ int sn_network_compress (sn_network_t *n); int sn_network_normalize (sn_network_t *n); int sn_network_cut_at (sn_network_t *n, int input, enum sn_network_cut_dir_e dir); -sn_network_t *sn_network_combine (sn_network_t *n0, sn_network_t *n1); +sn_network_t *sn_network_combine (sn_network_t *n0, sn_network_t *n1, + int is_power_of_two); +sn_network_t *sn_network_combine_bitonic (sn_network_t *n0, sn_network_t *n1); +sn_network_t *sn_network_combine_odd_even_merge (sn_network_t *n0, sn_network_t *n1); sn_network_t *sn_network_read (FILE *fh); sn_network_t *sn_network_read_file (const char *file);