2 * collectd - src/sn_network.c
3 * Copyright (C) 2008 Florian octo Forster
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Florian octo Forster <octo at verplant.org>
22 #ifndef _ISOC99_SOURCE
23 # define _ISOC99_SOURCE
25 #ifndef _POSIX_C_SOURCE
26 # define _POSIX_C_SOURCE 200112L
30 # define DPRINTF(...) fprintf (stderr, "sn_network: " __VA_ARGS__)
32 # define DPRINTF(...) /**/
42 #include "sn_network.h"
43 #include "sn_random.h"
45 sn_network_t *sn_network_create (int inputs_num) /* {{{ */
49 n = (sn_network_t *) malloc (sizeof (sn_network_t));
52 memset (n, '\0', sizeof (sn_network_t));
54 n->inputs_num = inputs_num;
57 } /* }}} sn_network_t *sn_network_create */
59 void sn_network_destroy (sn_network_t *n) /* {{{ */
64 if (n->stages != NULL)
67 for (i = 0; i < n->stages_num; i++)
69 sn_stage_destroy (n->stages[i]);
77 } /* }}} void sn_network_destroy */
79 int sn_network_stage_add (sn_network_t *n, sn_stage_t *s) /* {{{ */
83 temp = (sn_stage_t **) realloc (n->stages, (n->stages_num + 1)
84 * sizeof (sn_stage_t *));
89 SN_STAGE_DEPTH (s) = n->stages_num;
90 n->stages[n->stages_num] = s;
94 } /* }}} int sn_network_stage_add */
96 int sn_network_stage_remove (sn_network_t *n, int s_num) /* {{{ */
98 int nmemb = n->stages_num - (s_num + 1);
101 assert (s_num < n->stages_num);
103 sn_stage_destroy (n->stages[s_num]);
104 n->stages[s_num] = NULL;
108 memmove (n->stages + s_num, n->stages + (s_num + 1),
109 nmemb * sizeof (sn_stage_t *));
110 n->stages[n->stages_num - 1] = NULL;
114 /* Free the unused memory */
115 if (n->stages_num == 0)
122 temp = (sn_stage_t **) realloc (n->stages,
123 n->stages_num * sizeof (sn_stage_t *));
130 } /* }}} int sn_network_stage_remove */
132 sn_network_t *sn_network_clone (const sn_network_t *n) /* {{{ */
134 sn_network_t *n_copy;
137 n_copy = sn_network_create (n->inputs_num);
141 for (i = 0; i < n->stages_num; i++)
146 s = sn_stage_clone (n->stages[i]);
150 status = sn_network_stage_add (n_copy, s);
155 if (i < n->stages_num)
157 sn_network_destroy (n_copy);
162 } /* }}} sn_network_t *sn_network_clone */
164 int sn_network_show (sn_network_t *n) /* {{{ */
168 for (i = 0; i < n->stages_num; i++)
169 sn_stage_show (n->stages[i]);
172 } /* }}} int sn_network_show */
174 int sn_network_invert (sn_network_t *n) /* {{{ */
178 for (i = 0; i < n->stages_num; i++)
179 sn_stage_invert (n->stages[i]);
182 } /* }}} int sn_network_invert */
184 int sn_network_shift (sn_network_t *n, int sw) /* {{{ */
188 for (i = 0; i < n->stages_num; i++)
189 sn_stage_shift (n->stages[i], sw, SN_NETWORK_INPUT_NUM (n));
192 } /* }}} int sn_network_shift */
194 int sn_network_compress (sn_network_t *n) /* {{{ */
200 for (i = 1; i < n->stages_num; i++)
206 for (j = 0; j < SN_STAGE_COMP_NUM (s); j++)
208 sn_comparator_t *c = SN_STAGE_COMP_GET (s, j);
211 for (k = i - 1; k >= 0; k--)
215 conflict = sn_stage_comparator_check_conflict (n->stages[k], c);
230 sn_stage_comparator_add (n->stages[move_to], c);
231 sn_stage_comparator_remove (s, j);
237 while ((n->stages_num > 0)
238 && (SN_STAGE_COMP_NUM (n->stages[n->stages_num - 1]) == 0))
239 sn_network_stage_remove (n, n->stages_num - 1);
242 } /* }}} int sn_network_compress */
244 int sn_network_normalize (sn_network_t *n) /* {{{ */
248 for (i = n->stages_num - 1; i >= 0; i--)
255 for (j = 0; j < SN_STAGE_COMP_NUM (s); j++)
261 c = SN_STAGE_COMP_GET (s, j);
270 for (k = i; k >= 0; k--)
271 sn_stage_swap (n->stages[k], min, max);
273 } /* for (j = 0 .. #comparators) */
274 } /* for (i = n->stages_num - 1 .. 0) */
277 } /* }}} int sn_network_normalize */
279 int sn_network_cut_at (sn_network_t *n, int input, /* {{{ */
280 enum sn_network_cut_dir_e dir)
283 int position = input;
285 for (i = 0; i < n->stages_num; i++)
291 new_position = sn_stage_cut_at (s, position, dir);
293 if (position != new_position)
297 for (j = 0; j < i; j++)
298 sn_stage_swap (n->stages[j], position, new_position);
301 position = new_position;
304 assert (((dir == DIR_MIN) && (position == 0))
305 || ((dir == DIR_MAX) && (position == (n->inputs_num - 1))));
307 for (i = 0; i < n->stages_num; i++)
308 sn_stage_remove_input (n->stages[i], position);
313 } /* }}} int sn_network_cut_at */
315 /* sn_network_concatenate
317 * `Glues' two networks together, resulting in a comparator network with twice
318 * as many inputs but one that doesn't really sort anymore. It produces a
319 * bitonic sequence, though, that can be used by the mergers below. */
320 static sn_network_t *sn_network_concatenate (sn_network_t *n0, /* {{{ */
328 stages_num = (n0->stages_num > n1->stages_num)
332 n = sn_network_create (n0->inputs_num + n1->inputs_num);
336 for (i = 0; i < stages_num; i++)
338 sn_stage_t *s = sn_stage_create (i);
340 if (i < n0->stages_num)
341 for (j = 0; j < SN_STAGE_COMP_NUM (n0->stages[i]); j++)
343 sn_comparator_t *c = SN_STAGE_COMP_GET (n0->stages[i], j);
344 sn_stage_comparator_add (s, c);
347 if (i < n1->stages_num)
348 for (j = 0; j < SN_STAGE_COMP_NUM (n1->stages[i]); j++)
350 sn_comparator_t *c_orig = SN_STAGE_COMP_GET (n1->stages[i], j);
351 sn_comparator_t c_copy;
353 SN_COMP_MIN(&c_copy) = SN_COMP_MIN(c_orig) + n0->inputs_num;
354 SN_COMP_MAX(&c_copy) = SN_COMP_MAX(c_orig) + n0->inputs_num;
356 sn_stage_comparator_add (s, &c_copy);
359 sn_network_stage_add (n, s);
363 } /* }}} sn_network_t *sn_network_concatenate */
365 static int sn_network_add_bitonic_merger_recursive (sn_network_t *n, /* {{{ */
375 s = sn_stage_create (n->stages_num);
381 for (i = low; i < (low + m); i++)
388 sn_stage_comparator_add (s, &c);
391 sn_network_stage_add (n, s);
393 sn_network_add_bitonic_merger_recursive (n, low, m);
394 sn_network_add_bitonic_merger_recursive (n, low + m, m);
397 } /* }}} int sn_network_add_bitonic_merger_recursive */
399 static int sn_network_add_bitonic_merger (sn_network_t *n) /* {{{ */
406 s = sn_stage_create (n->stages_num);
410 m = n->inputs_num / 2;
412 for (i = 0; i < m; i++)
417 c.max = n->inputs_num - (i + 1);
419 sn_stage_comparator_add (s, &c);
422 sn_network_stage_add (n, s);
424 sn_network_add_bitonic_merger_recursive (n, 0, m);
425 sn_network_add_bitonic_merger_recursive (n, m, m);
427 sn_network_add_bitonic_merger_recursive (n, 0, SN_NETWORK_INPUT_NUM (n));
431 } /* }}} int sn_network_add_bitonic_merger */
433 static int sn_network_add_odd_even_merger_recursive (sn_network_t *n, /* {{{ */
434 int *indizes, int indizes_num)
440 int indizes_half_num;
445 indizes_half_num = indizes_num / 2;
446 indizes_half = (int *) malloc (indizes_num * sizeof (int));
447 if (indizes_half == NULL)
450 for (i = 0; i < indizes_half_num; i++)
452 indizes_half[i] = indizes[2 * i];
453 indizes_half[indizes_half_num + i] = indizes[(2 * i) + 1];
456 status = sn_network_add_odd_even_merger_recursive (n,
457 indizes_half, indizes_half_num);
464 status = sn_network_add_odd_even_merger_recursive (n,
465 indizes_half + indizes_half_num, indizes_half_num);
474 s = sn_stage_create (n->stages_num);
478 for (i = 1; i < (indizes_num - 2); i += 2)
481 c.max = indizes[i + 1];
483 sn_stage_comparator_add (s, &c);
486 sn_network_stage_add (n, s);
493 assert (indizes_num == 2);
498 s = sn_stage_create (n->stages_num);
502 sn_stage_comparator_add (s, &c);
503 sn_network_stage_add (n, s);
507 } /* }}} int sn_network_add_odd_even_merger_recursive */
509 static int sn_network_add_odd_even_merger (sn_network_t *n) /* {{{ */
516 indizes_num = n->inputs_num;
517 indizes = (int *) malloc (indizes_num * sizeof (int));
521 for (i = 0; i < indizes_num; i++)
524 status = sn_network_add_odd_even_merger_recursive (n,
525 indizes, indizes_num);
529 } /* }}} int sn_network_add_bitonic_merger */
531 static sn_network_t *sn_network_combine_bitonic (sn_network_t *n0, /* {{{ */
535 sn_network_t *n1_clone;
538 n1_clone = sn_network_clone (n1);
539 if (n1_clone == NULL)
542 sn_network_invert (n1_clone);
544 n = sn_network_concatenate (n0, n1_clone);
548 sn_network_destroy (n1_clone);
550 shift = sn_bounded_random (0, SN_NETWORK_INPUT_NUM (n) - 1);
553 DPRINTF ("sn_network_combine_bitonic: Shifting by %i.\n", shift);
554 sn_network_shift (n, shift);
557 sn_network_add_bitonic_merger (n);
560 } /* }}} sn_network_t *sn_network_combine_bitonic */
562 sn_network_t *sn_network_combine (sn_network_t *n0, /* {{{ */
567 if (sn_bounded_random (0, 2) < 2)
569 DPRINTF ("sn_network_combine: Using the bitonic merger.\n");
570 n = sn_network_combine_bitonic (n0, n1);
574 DPRINTF ("sn_network_combine: Using the odd-even merger.\n");
575 n = sn_network_concatenate (n0, n1);
578 sn_network_add_odd_even_merger (n);
581 sn_network_compress (n);
584 } /* }}} sn_network_t *sn_network_combine */
586 int sn_network_sort (sn_network_t *n, int *values) /* {{{ */
592 for (i = 0; i < n->stages_num; i++)
594 status = sn_stage_sort (n->stages[i], values);
600 } /* }}} int sn_network_sort */
602 int sn_network_brute_force_check (sn_network_t *n) /* {{{ */
604 int test_pattern[n->inputs_num];
605 int values[n->inputs_num];
609 memset (test_pattern, 0, sizeof (test_pattern));
615 /* Copy the current pattern and let the network sort it */
616 memcpy (values, test_pattern, sizeof (values));
617 status = sn_network_sort (n, values);
621 /* Check if the array is now sorted. */
622 previous = values[0];
623 for (i = 1; i < n->inputs_num; i++)
625 if (previous > values[i])
627 previous = values[i];
630 /* Generate the next test pattern */
632 for (i = 0; i < n->inputs_num; i++)
634 if (test_pattern[i] == 0)
647 /* Break out of the while loop if we tested all possible patterns */
652 /* All tests successfull */
654 } /* }}} int sn_network_brute_force_check */
656 sn_network_t *sn_network_read (FILE *fh) /* {{{ */
663 while (fgets (buffer, sizeof (buffer), fh) != NULL)
665 char *str_key = buffer;
666 char *str_value = NULL;
667 int buffer_len = strlen (buffer);
669 while ((buffer_len > 0) && ((buffer[buffer_len - 1] == '\n')
670 || (buffer[buffer_len - 1] == '\r')))
673 buffer[buffer_len] = '\0';
678 str_value = strchr (buffer, ':');
679 if (str_value == NULL)
681 printf ("Cannot parse line: %s\n", buffer);
685 *str_value = '\0'; str_value++;
686 while ((*str_value != '\0') && (isspace (*str_value) != 0))
689 if (strcasecmp ("Inputs", str_key) == 0)
690 opt_inputs = atoi (str_value);
692 printf ("Unknown key: %s\n", str_key);
693 } /* while (fgets) */
698 n = sn_network_create (opt_inputs);
704 s = sn_stage_read (fh);
708 sn_network_stage_add (n, s);
711 if (SN_NETWORK_STAGE_NUM (n) < 1)
713 sn_network_destroy (n);
718 } /* }}} sn_network_t *sn_network_read */
720 sn_network_t *sn_network_read_file (const char *file) /* {{{ */
725 fh = fopen (file, "r");
729 n = sn_network_read (fh);
734 } /* }}} sn_network_t *sn_network_read_file */
736 int sn_network_write (sn_network_t *n, FILE *fh) /* {{{ */
740 fprintf (fh, "Inputs: %i\n", n->inputs_num);
743 for (i = 0; i < n->stages_num; i++)
744 sn_stage_write (n->stages[i], fh);
747 } /* }}} int sn_network_write */
749 int sn_network_write_file (sn_network_t *n, const char *file) /* {{{ */
754 fh = fopen (file, "w");
758 status = sn_network_write (n, fh);
763 } /* }}} int sn_network_write_file */
765 int sn_network_serialize (sn_network_t *n, char **ret_buffer, /* {{{ */
766 size_t *ret_buffer_size)
773 buffer = *ret_buffer;
774 buffer_size = *ret_buffer_size;
776 #define SNPRINTF_OR_FAIL(...) \
777 status = snprintf (buffer, buffer_size, __VA_ARGS__); \
778 if ((status < 1) || (status >= buffer_size)) \
781 buffer_size -= status;
783 SNPRINTF_OR_FAIL ("Inputs: %i\r\n\r\n", n->inputs_num);
785 for (i = 0; i < n->stages_num; i++)
787 status = sn_stage_serialize (n->stages[i], &buffer, &buffer_size);
792 *ret_buffer = buffer;
793 *ret_buffer_size = buffer_size;
795 } /* }}} int sn_network_serialize */
797 sn_network_t *sn_network_unserialize (char *buffer, /* {{{ */
803 if (buffer_size == 0)
806 /* Read options first */
807 while (buffer_size > 0)
816 endptr = strchr (buffer, '\n');
823 line_len = strlen (line);
825 if ((line_len > 0) && (line[line_len - 1] == '\r'))
827 line[line_len - 1] = 0;
835 str_value = strchr (line, ':');
836 if (str_value == NULL)
838 printf ("Cannot parse line: %s\n", line);
842 *str_value = '\0'; str_value++;
843 while ((*str_value != '\0') && (isspace (*str_value) != 0))
846 if (strcasecmp ("Inputs", str_key) == 0)
847 opt_inputs = atoi (str_value);
849 printf ("Unknown key: %s\n", str_key);
850 } /* while (fgets) */
855 n = sn_network_create (opt_inputs);
861 s = sn_stage_unserialize (&buffer, &buffer_size);
865 sn_network_stage_add (n, s);
868 if (SN_NETWORK_STAGE_NUM (n) < 1)
870 sn_network_destroy (n);
875 } /* }}} sn_network_t *sn_network_unserialize */
877 /* vim: set sw=2 sts=2 et fdm=marker : */