src/sn-evolution.c: Added a first version of evolutionary optimization.
[sort-networks.git] / src / sn_stage.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <assert.h>
4
5 #include "sn_comparator.h"
6 #include "sn_stage.h"
7
8 sn_stage_t *sn_stage_create (int depth)
9 {
10   sn_stage_t *s;
11
12   s = (sn_stage_t *) malloc (sizeof (sn_stage_t));
13   if (s == NULL)
14     return (NULL);
15   memset (s, '\0', sizeof (sn_stage_t));
16
17   s->depth = depth;
18   
19   return (s);
20 } /* sn_stage_t *sn_stage_create */
21
22 void sn_stage_destroy (sn_stage_t *s)
23 {
24   if (s == NULL)
25     return;
26   if (s->comparators != NULL)
27     free (s->comparators);
28   free (s);
29 } /* void sn_stage_destroy */
30
31 int sn_stage_comparator_add (sn_stage_t *s, const sn_comparator_t *c)
32 {
33   sn_comparator_t *temp;
34   int i;
35
36   temp = (sn_comparator_t *) realloc (s->comparators,
37       (s->comparators_num + 1) * sizeof (sn_comparator_t));
38   if (temp == NULL)
39     return (-1);
40   s->comparators = temp;
41   temp = NULL;
42
43   for (i = 0; i < s->comparators_num; i++)
44     if (sn_comparator_compare (c, s->comparators + i) <= 0)
45       break;
46
47   /* Insert the elements in ascending order */
48   assert (i <= s->comparators_num);
49   if (i < s->comparators_num)
50   {
51     int nmemb = s->comparators_num - i;
52     memmove (s->comparators + (i + 1), s->comparators + i,
53         nmemb * sizeof (sn_comparator_t));
54   }
55   memcpy (s->comparators + i, c, sizeof (sn_comparator_t));
56   s->comparators_num++;
57
58   return (0);
59 } /* int sn_stage_comparator_add */
60
61 int sn_stage_comparator_remove (sn_stage_t *s, int c_num)
62 {
63   int nmemb = s->comparators_num - (c_num + 1);
64   sn_comparator_t *temp;
65
66   assert (c_num < s->comparators_num);
67   assert (c_num >= 0);
68
69   if (nmemb > 0)
70     memmove (s->comparators + c_num, s->comparators + (c_num + 1),
71         nmemb * sizeof (sn_comparator_t));
72   s->comparators_num--;
73
74   /* Free the unused memory */
75   if (s->comparators_num == 0)
76   {
77     free (s->comparators);
78     s->comparators = NULL;
79   }
80   else
81   {
82     temp = (sn_comparator_t *) realloc (s->comparators,
83         s->comparators_num * sizeof (sn_comparator_t));
84     if (temp == NULL)
85       return (-1);
86     s->comparators = temp;
87   }
88
89   return (0);
90 } /* int sn_stage_comparator_remove */
91
92 int sn_stage_comparator_check_conflict (sn_stage_t *s, const sn_comparator_t *c0)
93 {
94   int i;
95
96   for (i = 0; i < s->comparators_num; i++)
97   {
98     sn_comparator_t *c1 = s->comparators + i;
99     if ((SN_COMP_MIN(c0) == SN_COMP_MIN(c1))
100         || (SN_COMP_MIN(c0) == SN_COMP_MAX(c1))
101         || (SN_COMP_MAX(c0) == SN_COMP_MIN(c1))
102         || (SN_COMP_MAX(c0) == SN_COMP_MAX(c1)))
103     {
104       if ((SN_COMP_MIN(c0) == SN_COMP_MIN(c1))
105           && (SN_COMP_MAX(c0) == SN_COMP_MAX(c1)))
106         return (2);
107       else
108         return (1);
109     }
110   }
111
112   return (0);
113 } /* int sn_stage_comparator_check_conflict */
114
115 int sn_stage_show (sn_stage_t *s)
116 {
117   int lines[s->comparators_num];
118   int right[s->comparators_num];
119   int lines_used = 0;
120   int i;
121   int j;
122   int k;
123
124
125   for (i = 0; i < s->comparators_num; i++)
126   {
127     lines[i] = -1;
128     right[i] = -1;
129   }
130
131   for (i = 0; i < s->comparators_num; i++)
132   {
133     int j;
134     sn_comparator_t *c = s->comparators + i;
135
136     for (j = 0; j < lines_used; j++)
137       if (SN_COMP_LEFT (c) > right[j])
138         break;
139
140     lines[i] = j;
141     right[j] = SN_COMP_RIGHT (c);
142     if (j >= lines_used)
143       lines_used = j + 1;
144   }
145
146   for (i = 0; i < lines_used; i++)
147   {
148     printf ("%3i: ", s->depth);
149
150     for (j = 0; j <= right[i]; j++)
151     {
152       int on_elem = 0;
153       int line_after = 0;
154
155       for (k = 0; k < s->comparators_num; k++)
156       {
157         sn_comparator_t *c = s->comparators + k;
158
159         /* Check if this comparator is displayed on another line */
160         if (lines[k] != i)
161           continue;
162
163         if (j == SN_COMP_MIN (c))
164           on_elem = -1;
165         else if (j == SN_COMP_MAX (c))
166           on_elem = 1;
167
168         if ((j >= SN_COMP_LEFT (c)) && (j < SN_COMP_RIGHT (c)))
169           line_after = 1;
170
171         if ((on_elem != 0) || (line_after != 0))
172           break;
173       }
174
175       if (on_elem == 0)
176       {
177         if (line_after == 0)
178           printf ("     ");
179         else
180           printf ("-----");
181       }
182       else if (on_elem == -1)
183       {
184         if (line_after == 0)
185           printf ("-!   ");
186         else
187           printf (" !---");
188       }
189       else
190       {
191         if (line_after == 0)
192           printf ("->   ");
193         else
194           printf (" <---");
195       }
196     } /* for (columns) */
197
198     printf ("\n");
199   } /* for (lines) */
200
201   return (0);
202 } /* int sn_stage_show */
203
204 int sn_stage_invert (sn_stage_t *s)
205 {
206   int i;
207
208   for (i = 0; i < s->comparators_num; i++)
209     sn_comparator_invert (s->comparators + i);
210
211   return (0);
212 } /* int sn_stage_invert */
213
214 int sn_stage_swap (sn_stage_t *s, int con0, int con1)
215 {
216   int i;
217
218   for (i = 0; i < s->comparators_num; i++)
219     sn_comparator_swap (s->comparators + i, con0, con1);
220
221   return (0);
222 } /* int sn_stage_swap */
223
224 int sn_stage_cut_at (sn_stage_t *s, int input, enum sn_network_cut_dir_e dir)
225 {
226   int new_position = input;
227   int i;
228
229   for (i = 0; i < s->comparators_num; i++)
230   {
231     sn_comparator_t *c = s->comparators + i;
232
233     if ((SN_COMP_MIN (c) != input) && (SN_COMP_MAX (c) != input))
234       continue;
235
236     if ((dir == DIR_MIN) && (SN_COMP_MAX (c) == input))
237     {
238       new_position = SN_COMP_MIN (c);
239     }
240     else if ((dir == DIR_MAX) && (SN_COMP_MIN (c) == input))
241     {
242       new_position = SN_COMP_MAX (c);
243     }
244     break;
245   }
246
247   /*
248   if (i < s->comparators_num)
249     sn_stage_comparator_remove (s, i);
250     */
251
252   return (new_position);
253 } /* int sn_stage_cut_at */
254
255 int sn_stage_remove_input (sn_stage_t *s, int input)
256 {
257   int i;
258
259   for (i = 0; i < s->comparators_num; i++)
260   {
261     sn_comparator_t *c = s->comparators + i;
262
263     if ((SN_COMP_MIN (c) == input) || (SN_COMP_MAX (c) == input))
264     {
265       sn_stage_comparator_remove (s, i);
266       i--;
267       continue;
268     }
269
270     if (SN_COMP_MIN (c) > input)
271       SN_COMP_MIN (c) = SN_COMP_MIN (c) - 1;
272     if (SN_COMP_MAX (c) > input)
273       SN_COMP_MAX (c) = SN_COMP_MAX (c) - 1;
274   }
275
276   return (0);
277 }
278
279 sn_stage_t *sn_stage_read (FILE *fh)
280 {
281   sn_stage_t *s;
282   char buffer[64];
283   char *buffer_ptr;
284   
285   s = sn_stage_create (0);
286   if (s == NULL)
287     return (NULL);
288
289   while (fgets (buffer, sizeof (buffer), fh) != NULL)
290   {
291     char *endptr;
292     sn_comparator_t c;
293
294     if ((buffer[0] == '\0') || (buffer[0] == '\n') || (buffer[0] == '\r'))
295       break;
296     
297     buffer_ptr = buffer;
298     endptr = NULL;
299     c.min = (int) strtol (buffer_ptr, &endptr, 0);
300     if (buffer_ptr == endptr)
301       continue;
302
303     buffer_ptr = endptr;
304     endptr = NULL;
305     c.max = (int) strtol (buffer_ptr, &endptr, 0);
306     if (buffer_ptr == endptr)
307       continue;
308
309     sn_stage_comparator_add (s, &c);
310   }
311
312   if (s->comparators_num == 0)
313   {
314     sn_stage_destroy (s);
315     return (NULL);
316   }
317
318   return (s);
319 } /* sn_stage_t *sn_stage_read */
320
321 int sn_stage_write (sn_stage_t *s, FILE *fh)
322 {
323   int i;
324
325   if (s->comparators_num <= 0)
326     return (0);
327
328   for (i = 0; i < s->comparators_num; i++)
329     fprintf (fh, "%i %i\n",
330         SN_COMP_MIN (s->comparators + i),
331         SN_COMP_MAX (s->comparators + i));
332   fprintf (fh, "\n");
333
334   return (0);
335 } /* int sn_stage_write */
336
337 /* vim: set shiftwidth=2 softtabstop=2 : */