src/sn_network.c: Implement shifting when using the bitonic merge.
[sort-networks.git] / src / sn_network.c
1 /**
2  * collectd - src/sn_network.c
3  * Copyright (C) 2008  Florian octo Forster
4  *
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.
8  *
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.
13  *
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
17  *
18  * Authors:
19  *   Florian octo Forster <octo at verplant.org>
20  **/
21
22 #ifndef _ISOC99_SOURCE
23 # define _ISOC99_SOURCE
24 #endif
25 #ifndef _POSIX_C_SOURCE
26 # define _POSIX_C_SOURCE 200112L
27 #endif
28
29 #if 0
30 # define DPRINTF(...) fprintf (stderr, "sn_network: " __VA_ARGS__)
31 #else
32 # define DPRINTF(...) /**/
33 #endif
34
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <strings.h>
39 #include <ctype.h>
40 #include <assert.h>
41
42 #include "sn_network.h"
43 #include "sn_random.h"
44
45 sn_network_t *sn_network_create (int inputs_num) /* {{{ */
46 {
47   sn_network_t *n;
48
49   n = (sn_network_t *) malloc (sizeof (sn_network_t));
50   if (n == NULL)
51     return (NULL);
52   memset (n, '\0', sizeof (sn_network_t));
53
54   n->inputs_num = inputs_num;
55
56   return (n);
57 } /* }}} sn_network_t *sn_network_create */
58
59 void sn_network_destroy (sn_network_t *n) /* {{{ */
60 {
61   if (n == NULL)
62     return;
63
64   if (n->stages != NULL)
65   {
66     int i;
67     for (i = 0; i < n->stages_num; i++)
68     {
69       sn_stage_destroy (n->stages[i]);
70       n->stages[i] = NULL;
71     }
72     free (n->stages);
73     n->stages = NULL;
74   }
75
76   free (n);
77 } /* }}} void sn_network_destroy */
78
79 int sn_network_stage_add (sn_network_t *n, sn_stage_t *s) /* {{{ */
80 {
81   sn_stage_t **temp;
82
83   temp = (sn_stage_t **) realloc (n->stages, (n->stages_num + 1)
84       * sizeof (sn_stage_t *));
85   if (temp == NULL)
86     return (-1);
87
88   n->stages = temp;
89   SN_STAGE_DEPTH (s) = n->stages_num;
90   n->stages[n->stages_num] = s;
91   n->stages_num++;
92
93   return (0);
94 } /* }}} int sn_network_stage_add */
95
96 int sn_network_stage_remove (sn_network_t *n, int s_num) /* {{{ */
97 {
98   int nmemb = n->stages_num - (s_num + 1);
99   sn_stage_t **temp;
100
101   assert (s_num < n->stages_num);
102
103   sn_stage_destroy (n->stages[s_num]);
104   n->stages[s_num] = NULL;
105
106   if (nmemb > 0)
107   {
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;
111   }
112   n->stages_num--;
113
114   /* Free the unused memory */
115   if (n->stages_num == 0)
116   {
117     free (n->stages);
118     n->stages = NULL;
119   }
120   else
121   {
122     temp = (sn_stage_t **) realloc (n->stages,
123         n->stages_num * sizeof (sn_stage_t *));
124     if (temp == NULL)
125       return (-1);
126     n->stages = temp;
127   }
128
129   return (0);
130 } /* }}} int sn_network_stage_remove */
131
132 sn_network_t *sn_network_clone (const sn_network_t *n) /* {{{ */
133 {
134   sn_network_t *n_copy;
135   int i;
136
137   n_copy = sn_network_create (n->inputs_num);
138   if (n_copy == NULL)
139     return (NULL);
140
141   for (i = 0; i < n->stages_num; i++)
142   {
143     sn_stage_t *s;
144     int status;
145
146     s = sn_stage_clone (n->stages[i]);
147     if (s == NULL)
148       break;
149
150     status = sn_network_stage_add (n_copy, s);
151     if (status != 0)
152       break;
153   }
154
155   if (i < n->stages_num)
156   {
157     sn_network_destroy (n_copy);
158     return (NULL);
159   }
160
161   return (n_copy);
162 } /* }}} sn_network_t *sn_network_clone */
163
164 int sn_network_show (sn_network_t *n) /* {{{ */
165 {
166   int i;
167
168   for (i = 0; i < n->stages_num; i++)
169     sn_stage_show (n->stages[i]);
170
171   return (0);
172 } /* }}} int sn_network_show */
173
174 int sn_network_invert (sn_network_t *n) /* {{{ */
175 {
176   int i;
177
178   for (i = 0; i < n->stages_num; i++)
179     sn_stage_invert (n->stages[i]);
180
181   return (0);
182 } /* }}} int sn_network_invert */
183
184 int sn_network_shift (sn_network_t *n, int sw) /* {{{ */
185 {
186   int i;
187
188   for (i = 0; i < n->stages_num; i++)
189     sn_stage_shift (n->stages[i], sw, SN_NETWORK_INPUT_NUM (n));
190
191   return (0);
192 } /* }}} int sn_network_shift */
193
194 int sn_network_compress (sn_network_t *n) /* {{{ */
195 {
196   int i;
197   int j;
198   int k;
199
200   for (i = 1; i < n->stages_num; i++)
201   {
202     sn_stage_t *s;
203     
204     s = n->stages[i];
205     
206     for (j = 0; j < SN_STAGE_COMP_NUM (s); j++)
207     {
208       sn_comparator_t *c = SN_STAGE_COMP_GET (s, j);
209       int move_to = i;
210
211       for (k = i - 1; k >= 0; k--)
212       {
213         int conflict;
214
215         conflict = sn_stage_comparator_check_conflict (n->stages[k], c);
216         if (conflict == 0)
217         {
218           move_to = k;
219           continue;
220         }
221
222         if (conflict == 2)
223           move_to = -1;
224         break;
225       }
226
227       if (move_to < i)
228       {
229         if (move_to >= 0)
230           sn_stage_comparator_add (n->stages[move_to], c);
231         sn_stage_comparator_remove (s, j);
232         j--;
233       }
234     }
235   }
236
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);
240
241   return (0);
242 } /* }}} int sn_network_compress */
243
244 int sn_network_normalize (sn_network_t *n) /* {{{ */
245 {
246   int i;
247
248   for (i = n->stages_num - 1; i >= 0; i--)
249   {
250     sn_stage_t *s;
251     int j;
252
253     s = n->stages[i];
254
255     for (j = 0; j < SN_STAGE_COMP_NUM (s); j++)
256     {
257       sn_comparator_t *c;
258       int min;
259       int max;
260
261       c = SN_STAGE_COMP_GET (s, j);
262
263       min = c->min;
264       max = c->max;
265
266       if (min > max)
267       {
268         int k;
269
270         for (k = i; k >= 0; k--)
271           sn_stage_swap (n->stages[k], min, max);
272       }
273     } /* for (j = 0 .. #comparators) */
274   } /* for (i = n->stages_num - 1 .. 0) */
275
276   return (0);
277 } /* }}} int sn_network_normalize */
278
279 int sn_network_cut_at (sn_network_t *n, int input, /* {{{ */
280     enum sn_network_cut_dir_e dir)
281 {
282   int i;
283   int position = input;
284
285   for (i = 0; i < n->stages_num; i++)
286   {
287     sn_stage_t *s;
288     int new_position;
289     
290     s = n->stages[i];
291     new_position = sn_stage_cut_at (s, position, dir);
292     
293     if (position != new_position)
294     {
295       int j;
296
297       for (j = 0; j < i; j++)
298         sn_stage_swap (n->stages[j], position, new_position);
299     }
300
301     position = new_position;
302   }
303
304   assert (((dir == DIR_MIN) && (position == 0))
305       || ((dir == DIR_MAX) && (position == (n->inputs_num - 1))));
306
307   for (i = 0; i < n->stages_num; i++)
308     sn_stage_remove_input (n->stages[i], position);
309
310   n->inputs_num--;
311
312   return (0);
313 } /* }}} int sn_network_cut_at */
314
315 /* sn_network_concatenate
316  *
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, /* {{{ */
321     sn_network_t *n1)
322 {
323   sn_network_t *n;
324   int stages_num;
325   int i;
326   int j;
327
328   stages_num = (n0->stages_num > n1->stages_num)
329     ? n0->stages_num
330     : n1->stages_num;
331
332   n = sn_network_create (n0->inputs_num + n1->inputs_num);
333   if (n == NULL)
334     return (NULL);
335
336   for (i = 0; i < stages_num; i++)
337   {
338     sn_stage_t *s = sn_stage_create (i);
339
340     if (i < n0->stages_num)
341       for (j = 0; j < SN_STAGE_COMP_NUM (n0->stages[i]); j++)
342       {
343         sn_comparator_t *c = SN_STAGE_COMP_GET (n0->stages[i], j);
344         sn_stage_comparator_add (s, c);
345       }
346
347     if (i < n1->stages_num)
348       for (j = 0; j < SN_STAGE_COMP_NUM (n1->stages[i]); j++)
349       {
350         sn_comparator_t *c_orig = SN_STAGE_COMP_GET (n1->stages[i], j);
351         sn_comparator_t  c_copy;
352
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;
355
356         sn_stage_comparator_add (s, &c_copy);
357       }
358
359     sn_network_stage_add (n, s);
360   }
361
362   return (n);
363 } /* }}} sn_network_t *sn_network_concatenate */
364
365 static int sn_network_add_bitonic_merger_recursive (sn_network_t *n, /* {{{ */
366     int low, int num)
367 {
368   sn_stage_t *s;
369   int m;
370   int i;
371
372   if (num == 1)
373     return (0);
374
375   s = sn_stage_create (n->stages_num);
376   if (s == NULL)
377     return (-1);
378
379   m = num / 2;
380
381   for (i = low; i < (low + m); i++)
382   {
383     sn_comparator_t c;
384
385     c.min = i;
386     c.max = i + m;
387
388     sn_stage_comparator_add (s, &c);
389   }
390
391   sn_network_stage_add (n, s);
392
393   sn_network_add_bitonic_merger_recursive (n, low, m);
394   sn_network_add_bitonic_merger_recursive (n, low + m, m);
395
396   return (0);
397 } /* }}} int sn_network_add_bitonic_merger_recursive */
398
399 static int sn_network_add_bitonic_merger (sn_network_t *n) /* {{{ */
400 {
401 #if 0
402   sn_stage_t *s;
403   int m;
404   int i;
405
406   s = sn_stage_create (n->stages_num);
407   if (s == NULL)
408     return (-1);
409
410   m = n->inputs_num / 2;
411
412   for (i = 0; i < m; i++)
413   {
414     sn_comparator_t c;
415
416     c.min = i;
417     c.max = n->inputs_num - (i + 1);
418
419     sn_stage_comparator_add (s, &c);
420   }
421
422   sn_network_stage_add (n, s);
423
424   sn_network_add_bitonic_merger_recursive (n, 0, m);
425   sn_network_add_bitonic_merger_recursive (n, m, m);
426 #else
427   sn_network_add_bitonic_merger_recursive (n, 0, SN_NETWORK_INPUT_NUM (n));
428 #endif
429
430   return (0);
431 } /* }}} int sn_network_add_bitonic_merger */
432
433 static int sn_network_add_odd_even_merger_recursive (sn_network_t *n, /* {{{ */
434     int *indizes, int indizes_num)
435 {
436   if (indizes_num > 2)
437   {
438     sn_comparator_t c;
439     sn_stage_t *s;
440     int indizes_half_num;
441     int *indizes_half;
442     int status;
443     int i;
444
445     indizes_half_num = indizes_num / 2;
446     indizes_half = (int *) malloc (indizes_num * sizeof (int));
447     if (indizes_half == NULL)
448       return (-1);
449
450     for (i = 0; i < indizes_half_num; i++)
451     {
452       indizes_half[i] = indizes[2 * i];
453       indizes_half[indizes_half_num + i] = indizes[(2 * i) + 1];
454     }
455
456     status = sn_network_add_odd_even_merger_recursive (n,
457         indizes_half, indizes_half_num);
458     if (status != 0)
459     {
460       free (indizes_half);
461       return (status);
462     }
463
464     status = sn_network_add_odd_even_merger_recursive (n,
465         indizes_half + indizes_half_num, indizes_half_num);
466     if (status != 0)
467     {
468       free (indizes_half);
469       return (status);
470     }
471
472     free (indizes_half);
473
474     s = sn_stage_create (n->stages_num);
475     if (s == NULL)
476       return (-1);
477
478     for (i = 1; i < (indizes_num - 2); i += 2)
479     {
480       c.min = indizes[i];
481       c.max = indizes[i + 1];
482
483       sn_stage_comparator_add (s, &c);
484     }
485
486     sn_network_stage_add (n, s);
487   }
488   else
489   {
490     sn_comparator_t c;
491     sn_stage_t *s;
492
493     assert (indizes_num == 2);
494
495     c.min = indizes[0];
496     c.max = indizes[1];
497
498     s = sn_stage_create (n->stages_num);
499     if (s == NULL)
500       return (-1);
501
502     sn_stage_comparator_add (s, &c);
503     sn_network_stage_add (n, s);
504   }
505
506   return (0);
507 } /* }}} int sn_network_add_odd_even_merger_recursive */
508
509 static int sn_network_add_odd_even_merger (sn_network_t *n) /* {{{ */
510 {
511   int *indizes;
512   int indizes_num;
513   int status;
514   int i;
515
516   indizes_num = n->inputs_num;
517   indizes = (int *) malloc (indizes_num * sizeof (int));
518   if (indizes == NULL)
519     return (-1);
520
521   for (i = 0; i < indizes_num; i++)
522     indizes[i] = i;
523
524   status = sn_network_add_odd_even_merger_recursive (n,
525       indizes, indizes_num);
526   
527   free (indizes);
528   return (status);
529 } /* }}} int sn_network_add_bitonic_merger */
530
531 static sn_network_t *sn_network_combine_bitonic (sn_network_t *n0, /* {{{ */
532     sn_network_t *n1)
533 {
534   sn_network_t *n;
535   sn_network_t *n1_clone;
536   int shift;
537
538   n1_clone = sn_network_clone (n1);
539   if (n1_clone == NULL)
540     return (NULL);
541
542   sn_network_invert (n1_clone);
543
544   n = sn_network_concatenate (n0, n1_clone);
545   if (n == NULL)
546     return (NULL);
547
548   sn_network_destroy (n1_clone);
549
550   shift = sn_bounded_random (0, SN_NETWORK_INPUT_NUM (n) - 1);
551   if (shift > 0)
552   {
553     DPRINTF ("sn_network_combine_bitonic: Shifting by %i.\n", shift);
554     sn_network_shift (n, shift);
555   }
556
557   sn_network_add_bitonic_merger (n);
558
559   return (n);
560 } /* }}} sn_network_t *sn_network_combine_bitonic */
561
562 sn_network_t *sn_network_combine (sn_network_t *n0, /* {{{ */
563     sn_network_t *n1)
564 {
565   sn_network_t *n;
566
567   if (sn_bounded_random (0, 2) < 2)
568   {
569     DPRINTF ("sn_network_combine: Using the bitonic merger.\n");
570     n = sn_network_combine_bitonic (n0, n1);
571   }
572   else
573   {
574     DPRINTF ("sn_network_combine: Using the odd-even merger.\n");
575     n = sn_network_concatenate (n0, n1);
576     if (n == NULL)
577       return (NULL);
578     sn_network_add_odd_even_merger (n);
579   }
580
581   sn_network_compress (n);
582
583   return (n);
584 } /* }}} sn_network_t *sn_network_combine */
585
586 int sn_network_sort (sn_network_t *n, int *values) /* {{{ */
587 {
588   int status;
589   int i;
590
591   status = 0;
592   for (i = 0; i < n->stages_num; i++)
593   {
594     status = sn_stage_sort (n->stages[i], values);
595     if (status != 0)
596       return (status);
597   }
598
599   return (status);
600 } /* }}} int sn_network_sort */
601
602 int sn_network_brute_force_check (sn_network_t *n) /* {{{ */
603 {
604   int test_pattern[n->inputs_num];
605   int values[n->inputs_num];
606   int status;
607   int i;
608
609   memset (test_pattern, 0, sizeof (test_pattern));
610   while (42)
611   {
612     int previous;
613     int overflow;
614
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);
618     if (status != 0)
619       return (status);
620
621     /* Check if the array is now sorted. */
622     previous = values[0];
623     for (i = 1; i < n->inputs_num; i++)
624     {
625       if (previous > values[i])
626         return (1);
627       previous = values[i];
628     }
629
630     /* Generate the next test pattern */
631     overflow = 1;
632     for (i = 0; i < n->inputs_num; i++)
633     {
634       if (test_pattern[i] == 0)
635       {
636         test_pattern[i] = 1;
637         overflow = 0;
638         break;
639       }
640       else
641       {
642         test_pattern[i] = 0;
643         overflow = 1;
644       }
645     }
646
647     /* Break out of the while loop if we tested all possible patterns */
648     if (overflow == 1)
649       break;
650   } /* while (42) */
651
652   /* All tests successfull */
653   return (0);
654 } /* }}} int sn_network_brute_force_check */
655
656 sn_network_t *sn_network_read (FILE *fh) /* {{{ */
657 {
658   sn_network_t *n;
659   char buffer[64];
660
661   int opt_inputs = 0;
662
663   while (fgets (buffer, sizeof (buffer), fh) != NULL)
664   {
665     char *str_key = buffer;
666     char *str_value = NULL;
667     int   buffer_len = strlen (buffer);
668
669     while ((buffer_len > 0) && ((buffer[buffer_len - 1] == '\n')
670           || (buffer[buffer_len - 1] == '\r')))
671     {
672       buffer_len--;
673       buffer[buffer_len] = '\0';
674     }
675     if (buffer_len == 0)
676       break;
677
678     str_value = strchr (buffer, ':');
679     if (str_value == NULL)
680     {
681       printf ("Cannot parse line: %s\n", buffer);
682       continue;
683     }
684
685     *str_value = '\0'; str_value++;
686     while ((*str_value != '\0') && (isspace (*str_value) != 0))
687       str_value++;
688
689     if (strcasecmp ("Inputs", str_key) == 0)
690       opt_inputs = atoi (str_value);
691     else
692       printf ("Unknown key: %s\n", str_key);
693   } /* while (fgets) */
694
695   if (opt_inputs < 2)
696     return (NULL);
697
698   n = sn_network_create (opt_inputs);
699
700   while (42)
701   {
702     sn_stage_t *s;
703
704     s = sn_stage_read (fh);
705     if (s == NULL)
706       break;
707
708     sn_network_stage_add (n, s);
709   }
710
711   if (SN_NETWORK_STAGE_NUM (n) < 1)
712   {
713     sn_network_destroy (n);
714     return (NULL);
715   }
716
717   return (n);
718 } /* }}} sn_network_t *sn_network_read */
719
720 sn_network_t *sn_network_read_file (const char *file) /* {{{ */
721 {
722   sn_network_t *n;
723   FILE *fh;
724
725   fh = fopen (file, "r");
726   if (fh == NULL)
727     return (NULL);
728
729   n = sn_network_read (fh);
730
731   fclose (fh);
732
733   return (n);
734 } /* }}} sn_network_t *sn_network_read_file */
735
736 int sn_network_write (sn_network_t *n, FILE *fh) /* {{{ */
737 {
738   int i;
739
740   fprintf (fh, "Inputs: %i\n", n->inputs_num);
741   fprintf (fh, "\n");
742
743   for (i = 0; i < n->stages_num; i++)
744     sn_stage_write (n->stages[i], fh);
745
746   return (0);
747 } /* }}} int sn_network_write */
748
749 int sn_network_write_file (sn_network_t *n, const char *file) /* {{{ */
750 {
751   int status;
752   FILE *fh;
753
754   fh = fopen (file, "w");
755   if (fh == NULL)
756     return (-1);
757
758   status = sn_network_write (n, fh);
759
760   fclose (fh);
761
762   return (status);
763 } /* }}} int sn_network_write_file */
764
765 int sn_network_serialize (sn_network_t *n, char **ret_buffer, /* {{{ */
766     size_t *ret_buffer_size)
767 {
768   char *buffer;
769   size_t buffer_size;
770   int status;
771   int i;
772
773   buffer = *ret_buffer;
774   buffer_size = *ret_buffer_size;
775
776 #define SNPRINTF_OR_FAIL(...) \
777   status = snprintf (buffer, buffer_size, __VA_ARGS__); \
778   if ((status < 1) || (status >= buffer_size)) \
779     return (-1); \
780   buffer += status; \
781   buffer_size -= status;
782
783   SNPRINTF_OR_FAIL ("Inputs: %i\r\n\r\n", n->inputs_num);
784
785   for (i = 0; i < n->stages_num; i++)
786   {
787     status = sn_stage_serialize (n->stages[i], &buffer, &buffer_size);
788     if (status != 0)
789       return (status);
790   }
791
792   *ret_buffer = buffer;
793   *ret_buffer_size = buffer_size;
794   return (0);
795 } /* }}} int sn_network_serialize */
796
797 sn_network_t *sn_network_unserialize (char *buffer, /* {{{ */
798     size_t buffer_size)
799 {
800   sn_network_t *n;
801   int opt_inputs = 0;
802
803   if (buffer_size == 0)
804     return (NULL);
805
806   /* Read options first */
807   while (buffer_size > 0)
808   {
809     char *endptr;
810     char *str_key;
811     char *str_value;
812     char *line;
813     int   line_len;
814
815     line = buffer;
816     endptr = strchr (buffer, '\n');
817     if (endptr == NULL)
818       return (NULL);
819
820     *endptr = 0;
821     endptr++;
822     buffer = endptr;
823     line_len = strlen (line);
824
825     if ((line_len > 0) && (line[line_len - 1] == '\r'))
826     {
827       line[line_len - 1] = 0;
828       line_len--;
829     }
830
831     if (line_len == 0)
832       break;
833
834     str_key = line;
835     str_value = strchr (line, ':');
836     if (str_value == NULL)
837     {
838       printf ("Cannot parse line: %s\n", line);
839       continue;
840     }
841
842     *str_value = '\0'; str_value++;
843     while ((*str_value != '\0') && (isspace (*str_value) != 0))
844       str_value++;
845
846     if (strcasecmp ("Inputs", str_key) == 0)
847       opt_inputs = atoi (str_value);
848     else
849       printf ("Unknown key: %s\n", str_key);
850   } /* while (fgets) */
851
852   if (opt_inputs < 2)
853     return (NULL);
854
855   n = sn_network_create (opt_inputs);
856
857   while (42)
858   {
859     sn_stage_t *s;
860
861     s = sn_stage_unserialize (&buffer, &buffer_size);
862     if (s == NULL)
863       break;
864
865     sn_network_stage_add (n, s);
866   }
867
868   if (SN_NETWORK_STAGE_NUM (n) < 1)
869   {
870     sn_network_destroy (n);
871     return (NULL);
872   }
873
874   return (n);
875 } /* }}} sn_network_t *sn_network_unserialize */
876
877 /* vim: set sw=2 sts=2 et fdm=marker : */