1 static char rcsid[] = "$Id: intlist.c 218147 2019-01-16 21:28:41Z twu $";
2 #ifdef HAVE_CONFIG_H
3 #include <config.h>
4 #endif
5 
6 #include "intlist.h"
7 #include <stdio.h>		/* For sprintf */
8 #include <stdlib.h>
9 #include <string.h>		/* For strlen */
10 #include "mem.h"
11 
12 
13 #define T Intlist_T
14 
15 #if !defined(HAVE_INLINE)
16 T
Intlist_push(T list,int x)17 Intlist_push (T list, int x) {
18   T new = (T) MALLOC(sizeof(*new));
19 
20   new->first = x;
21   new->rest = list;
22   return new;
23 }
24 
25 T
Intlist_pop(T list,int * x)26 Intlist_pop (T list, int *x) {
27   T head;
28 
29   if (list) {
30     head = list->rest;
31     *x = list->first;
32     FREE(list);
33     return head;
34   } else {
35     return list;
36   }
37 }
38 
39 int
Intlist_head(T list)40 Intlist_head (T list) {
41   return list->first;
42 }
43 
44 T
Intlist_next(T list)45 Intlist_next (T list) {
46   if (list) {
47     return list->rest;
48   } else {
49     return NULL;
50   }
51 }
52 
53 void
Intlist_free(T * list)54 Intlist_free (T *list) {
55   T prev;
56 
57   while ((prev = *list) != NULL) {
58     *list = prev->rest;
59     FREE(prev);
60   }
61 }
62 
63 T
Intlist_reverse(T list)64 Intlist_reverse (T list) {
65   T head = NULL, next;
66 
67   for ( ; list; list = next) {
68     next = list->rest;
69     list->rest = head;
70     head = list;
71   }
72   return head;
73 }
74 
75 int
Intlist_length(T list)76 Intlist_length (T list) {
77   int n;
78 
79   for (n = 0; list; list = list->rest) {
80     n++;
81   }
82   return n;
83 }
84 #endif
85 
86 
87 T
Intlist_push_in(T list,int x)88 Intlist_push_in (T list, int x) {
89   T new = (T) MALLOC_IN(sizeof(*new));
90 
91   new->first = x;
92   new->rest = list;
93   return new;
94 }
95 
96 T
Intlist_insert_second(T list,int x)97 Intlist_insert_second (T list, int x) {
98   T new = (T) MALLOC(sizeof(*new));
99 
100   new->first = x;
101   new->rest = list->rest;
102   list->rest = new;
103   return list;
104 }
105 
106 void
Intlist_delete(T prev,T this)107 Intlist_delete (T prev, T this) {
108   prev->rest = this->rest;
109   FREE(this);
110   return;
111 }
112 
113 
114 void
Intlist_head_set(T this,int x)115 Intlist_head_set (T this, int x) {
116   this->first = x;
117   return;
118 }
119 
120 void
Intlist_free_in(T * list)121 Intlist_free_in (T *list) {
122   T prev;
123 
124   while ((prev = *list) != NULL) {
125     *list = prev->rest;
126     FREE_IN(prev);
127   }
128 }
129 
130 T
Intlist_keep_one(T list,int i)131 Intlist_keep_one (T list, int i) {
132   T head;
133 
134   while (--i >= 0) {
135     /* Pop */
136     head = list->rest;
137     FREE(list);
138     list = head;
139   }
140 
141   Intlist_free(&list->rest);
142   return list;
143 }
144 
145 
146 
147 int
Intlist_max(T list)148 Intlist_max (T list) {
149   int m = 0;
150 
151   while (list) {
152     if (list->first > m) {
153       m = list->first;
154     }
155     list = list->rest;
156   }
157 
158   return m;
159 }
160 
161 int
Intlist_min(T list)162 Intlist_min (T list) {
163   int m;
164 
165   if (list == NULL) {
166     return 0;
167 
168   } else {
169     m = list->first;
170     list = list->rest;
171     while (list) {
172       if (list->first < m) {
173 	m = list->first;
174       }
175       list = list->rest;
176     }
177 
178     return m;
179   }
180 }
181 
182 
183 int
Intlist_sum(T list)184 Intlist_sum (T list) {
185   int sum = 0;
186 
187   while (list) {
188     sum += list->first;
189     list = list->rest;
190   }
191 
192   return sum;
193 }
194 
195 
196 bool
Intlist_vary(T list)197 Intlist_vary (T list) {
198   int m;
199 
200   if (list == NULL) {
201     return false;
202 
203   } else {
204     m = list->first;
205     list = list->rest;
206     while (list) {
207       if (list->first != m) {
208 	return true;
209       }
210       list = list->rest;
211     }
212 
213     return false;
214   }
215 }
216 
217 bool
Intlist_exists_p(T list,int x)218 Intlist_exists_p (T list, int x) {
219   while (list) {
220     if (list->first == x) {
221       return true;
222     }
223     list = list->rest;
224   }
225   return false;
226 }
227 
228 int *
Intlist_to_array(int * n,T list)229 Intlist_to_array (int *n, T list) {
230   int *array;
231   int i;
232 
233   *n = Intlist_length(list);
234   if (*n == 0) {
235     return NULL;
236   } else {
237     array = (int *) CALLOC(*n,sizeof(int));
238     for (i = 0; i < *n; i++) {
239       array[i] = list->first;
240       list = list->rest;
241     }
242     return array;
243   }
244 }
245 
246 int *
Intlist_to_array_plus_extra(int * n,T list)247 Intlist_to_array_plus_extra (int *n, T list) {
248   int *array;
249   int i;
250 
251   *n = Intlist_length(list);
252   if (*n == 0) {
253     return NULL;
254   } else {
255     array = (int *) CALLOC((*n)+1,sizeof(int));
256     for (i = 0; i < *n; i++) {
257       array[i] = list->first;
258       list = list->rest;
259     }
260     return array;
261   }
262 }
263 
264 void
Intlist_fill_array(int * array,T list)265 Intlist_fill_array (int *array, T list) {
266   int i = 0;
267 
268   while (list) {
269     array[i++] = list->first;
270     list = list->rest;
271   }
272 
273   return;
274 }
275 
276 
277 void
Intlist_fill_array_and_free(int * array,T * list)278 Intlist_fill_array_and_free (int *array, T *list) {
279   T prev;
280   int i = 0;
281 
282   while ((prev = *list) != NULL) {
283     array[i++] = prev->first;
284     *list = prev->rest;
285     FREE(prev);
286   }
287 
288   return;
289 }
290 
291 int *
Intlist_to_array_out(int * n,T list)292 Intlist_to_array_out (int *n, T list) {
293   int *array;
294   int i;
295 
296   *n = Intlist_length(list);
297   if (*n == 0) {
298     return NULL;
299   } else {
300     array = (int *) CALLOC_OUT(*n,sizeof(int));
301     for (i = 0; i < *n; i++) {
302       array[i] = list->first;
303       list = list->rest;
304     }
305     return array;
306   }
307 }
308 
309 
310 char *
Intlist_to_char_array(int * n,T list)311 Intlist_to_char_array (int *n, T list) {
312   char *array;
313   int i;
314 
315   *n = Intlist_length(list);
316   if (*n == 0) {
317     return NULL;
318   } else {
319     array = (char *) MALLOC((*n + 1)*sizeof(char));
320     for (i = 0; i < *n; i++) {
321       array[i] = (char) list->first;
322       list = list->rest;
323     }
324     array[*n] = '\0';
325     return array;
326   }
327 }
328 
329 char *
Intlist_to_char_array_in(int * n,T list)330 Intlist_to_char_array_in (int *n, T list) {
331   char *array;
332   int i;
333 
334   *n = Intlist_length(list);
335   if (*n == 0) {
336     return NULL;
337   } else {
338     array = (char *) MALLOC_IN((*n + 1)*sizeof(char));
339     for (i = 0; i < *n; i++) {
340       array[i] = (char) list->first;
341       list = list->rest;
342     }
343     array[*n] = '\0';
344     return array;
345   }
346 }
347 
348 T
Intlist_from_array(int * array,int n)349 Intlist_from_array (int *array, int n) {
350   T list = NULL, p;
351 
352   while (--n >= 0) {
353     p = (T) MALLOC(sizeof(*p));
354     p->first = array[n];
355     p->rest = list;
356     list = p;
357   }
358 
359   return list;
360 }
361 
362 T
Intlist_copy(T list)363 Intlist_copy (T list) {
364   T head, *p = &head;
365 
366   for ( ; list; list = list->rest) {
367     *p = (T) MALLOC(sizeof(**p));
368     (*p)->first = list->first;
369     p = &(*p)->rest;
370   }
371   *p = NULL;
372   return head;
373 }
374 
375 T
Intlist_append(T list,T tail)376 Intlist_append (T list, T tail) {
377   T *p = &list;
378 
379   while (*p) {
380     p = &(*p)->rest;
381   }
382   *p = tail;
383   return list;
384 }
385 
386 int
Intlist_last_value(T this)387 Intlist_last_value (T this) {
388   T last = NULL, r;
389 
390   for (r = this; r != NULL; r = r->rest) {
391     last = r;
392   }
393   return last->first;
394 }
395 
396 int
Intlist_penultimate_value(T this)397 Intlist_penultimate_value (T this) {
398   T last = NULL, r;
399 
400   for (r = this; r->rest != NULL; r = r->rest) {
401     last = r;
402   }
403   return last->first;
404 }
405 
406 int
Intlist_index(T this,int index)407 Intlist_index (T this, int index) {
408   while (index-- > 0) {
409     this = this->rest;
410   }
411   return this->first;
412 }
413 
414 T
Intlist_from_string(char * string)415 Intlist_from_string (char *string) {
416   T this = NULL;
417   char *p = string;
418   int x;
419 
420   while (sscanf(p,"%d",&x) > 0) {
421     this = Intlist_push(this,x);
422     while (*p != '\0' && *p != ',') {
423       p++;
424     }
425     if (*p == ',') {
426       p++;
427     }
428   }
429   return Intlist_reverse(this);
430 }
431 
432 char *
Intlist_to_string(T this)433 Intlist_to_string (T this) {
434   char *string, Buffer[256];
435   T p;
436   int n, i, strlength;
437 
438   if ((n = Intlist_length(this)) == 0) {
439     string = (char *) CALLOC(1,sizeof(char));
440     string[0] = '\0';
441   } else {
442     strlength = 0;
443     for (i = 0, p = this; i < n-1; i++, p = Intlist_next(p)) {
444       sprintf(Buffer,"%d,",Intlist_head(p));
445       strlength += strlen(Buffer);
446     }
447     sprintf(Buffer,"%d",Intlist_head(p));
448     strlength += strlen(Buffer);
449 
450     string = (char *) CALLOC(strlength + 1,sizeof(char));
451     string[0] = '\0';
452     for (i = 0, p = this; i < n-1; i++, p = Intlist_next(p)) {
453       sprintf(Buffer,"%d,",Intlist_head(p));
454       strcat(string,Buffer);
455     }
456     sprintf(Buffer,"%d",Intlist_head(p));
457     strcat(string,Buffer);
458   }
459 
460   return string;
461 }
462 
463 
464 struct Cell_T {
465   int elt;
466   int keyvalue;
467 };
468 
469 static int
cell_ascending(const void * a,const void * b)470 cell_ascending (const void *a, const void *b) {
471   struct Cell_T *x = (struct Cell_T *) a;
472   struct Cell_T *y = (struct Cell_T *) b;
473 
474   if (x->keyvalue < y->keyvalue) {
475     return -1;
476   } else if (y->keyvalue < x->keyvalue) {
477     return +1;
478   } else {
479     return 0;
480   }
481 }
482 
483 static int
cell_ascending_dual(const void * a,const void * b)484 cell_ascending_dual (const void *a, const void *b) {
485   struct Cell_T *x = (struct Cell_T *) a;
486   struct Cell_T *y = (struct Cell_T *) b;
487 
488   if (x->keyvalue < y->keyvalue) {
489     return -1;
490   } else if (y->keyvalue < x->keyvalue) {
491     return +1;
492   } else if (x->elt < y->elt) {
493     return -1;
494   } else if (y->elt < x->elt) {
495     return +1;
496   } else {
497     return 0;
498   }
499 }
500 
501 static int
cell_descending(const void * a,const void * b)502 cell_descending (const void *a, const void *b) {
503   struct Cell_T *x = (struct Cell_T *) a;
504   struct Cell_T *y = (struct Cell_T *) b;
505 
506   if (x->keyvalue > y->keyvalue) {
507     return -1;
508   } else if (y->keyvalue > x->keyvalue) {
509     return +1;
510   } else {
511     return 0;
512   }
513 }
514 
515 int *
Intlist_array_ascending_by_key(int * n,T this,T key)516 Intlist_array_ascending_by_key (int *n, T this, T key) {
517   int *sorted, i;
518   struct Cell_T *cells;
519   T p, q;
520 
521   /* find length */
522   for (*n = 0, p = this; p; p = p->rest) {
523     (*n)++;
524   }
525 
526   cells = (struct Cell_T *) CALLOC(*n,sizeof(struct Cell_T));
527   for (p = this, q = key, i = 0; p != NULL; p = p->rest, q = q->rest, i++) {
528     cells[i].elt = p->first;
529     cells[i].keyvalue = q->first;
530   }
531   qsort(cells,*n,sizeof(struct Cell_T),cell_ascending);
532 
533   sorted = (int *) CALLOC(*n,sizeof(int));
534   for (i = 0; i < *n; i++) {
535     sorted[i] = cells[i].elt;
536   }
537 
538   FREE(cells);
539   return sorted;
540 }
541 
542 
543 void
Intlist_array_dual_ascending_by_key(int * sorted,int * keyarray,int n,T this,T key)544 Intlist_array_dual_ascending_by_key (int *sorted, int *keyarray, int n, T this, T key) {
545   int i;
546   struct Cell_T *cells;
547   T p, q;
548 
549   cells = (struct Cell_T *) MALLOCA(n * sizeof(struct Cell_T));
550   for (p = this, q = key, i = 0; p != NULL; p = p->rest, q = q->rest, i++) {
551     cells[i].elt = p->first;
552     cells[i].keyvalue = q->first;
553   }
554   qsort(cells,n,sizeof(struct Cell_T),cell_ascending_dual);
555 
556   for (i = 0; i < n; i++) {
557     sorted[i] = cells[i].elt;
558     keyarray[i] = cells[i].keyvalue;
559   }
560 
561   FREEA(cells);
562   return;
563 }
564 
565 
566 T
Intlist_list_ascending_by_key(T this,T key)567 Intlist_list_ascending_by_key (T this, T key) {
568   T sorted = NULL, p, q;
569   int n, i;
570   struct Cell_T *cells;
571 
572   /* find length */
573   for (n = 0, p = this; p; p = p->rest) {
574     n++;
575   }
576 
577   cells = (struct Cell_T *) CALLOC(n,sizeof(struct Cell_T));
578   for (p = this, q = key, i = 0; p != NULL; p = p->rest, q = q->rest, i++) {
579     cells[i].elt = p->first;
580     cells[i].keyvalue = q->first;
581   }
582   qsort(cells,n,sizeof(struct Cell_T),cell_descending);
583 
584   for (i = 0; i < n; i++) {
585     sorted = Intlist_push(sorted,cells[i].elt);
586   }
587   /* No need to reverse list because we sorted by descending key */
588 
589   FREE(cells);
590 
591   return sorted;
592 }
593 
594 
595 T
Intlist_list_descending_by_key(T this,T key)596 Intlist_list_descending_by_key (T this, T key) {
597   T sorted = NULL, p, q;
598   int n, i;
599   struct Cell_T *cells;
600 
601   /* find length */
602   for (n = 0, p = this; p; p = p->rest) {
603     n++;
604   }
605 
606   cells = (struct Cell_T *) CALLOC(n,sizeof(struct Cell_T));
607   for (p = this, q = key, i = 0; p != NULL; p = p->rest, q = q->rest, i++) {
608     cells[i].elt = p->first;
609     cells[i].keyvalue = q->first;
610   }
611   qsort(cells,n,sizeof(struct Cell_T),cell_ascending);
612 
613   for (i = 0; i < n; i++) {
614     sorted = Intlist_push(sorted,cells[i].elt);
615   }
616   /* No need to reverse list because we sorted by ascending key */
617 
618   FREE(cells);
619 
620   return sorted;
621 }
622 
623 
624 T
Intlist_sort_ascending(T this)625 Intlist_sort_ascending (T this) {
626   T sorted = NULL, p;
627   int n, i;
628   struct Cell_T *cells;
629 
630   /* find length */
631   for (n = 0, p = this; p; p = p->rest) {
632     n++;
633   }
634 
635   cells = (struct Cell_T *) CALLOC(n,sizeof(struct Cell_T));
636   for (p = this, i = 0; p != NULL; p = p->rest, i++) {
637     cells[i].keyvalue = p->first;
638   }
639   qsort(cells,n,sizeof(struct Cell_T),cell_descending);
640 
641   for (i = 0; i < n; i++) {
642     sorted = Intlist_push(sorted,cells[i].keyvalue);
643   }
644   /* No need to reverse list because we sorted by descending key */
645 
646   FREE(cells);
647 
648   return sorted;
649 }
650 
651 bool
Intlist_equal(T x,T y)652 Intlist_equal (T x, T y) {
653 
654   while (x && y && x->first == y->first) {
655     x = x->rest;
656     y = y->rest;
657   }
658   if (x || y) {
659     return false;
660   } else {
661     return true;
662   }
663 }
664 
665 bool
Intlist_intersect_p(T x,T y)666 Intlist_intersect_p (T x, T y) {
667   T q;
668   int value;
669 
670   while (x) {
671     value = x->first;
672     for (q = y; q != NULL; q = q->rest) {
673       if (q->first == value) {
674 	return true;
675       }
676     }
677     x = x->rest;
678   }
679 
680   return false;
681 }
682 
683 #if 0
684 /* Reverses elements in x */
685 T
686 Intlist_intersect (T x, T y) {
687   T list = NULL, new, q;
688   int value;
689 
690   while (x) {
691     value = x->first;
692     for (q = y; q != NULL; q = q->rest) {
693       if (q->first == value) {
694 	/* list = Intlist_push(list,value) */
695 	new = (T) MALLOC(sizeof(*new));
696 	new->first = value;
697 	new->rest = list;
698 	list = new;
699       }
700     }
701     x = x->rest;
702   }
703 
704   return list;
705 }
706 #endif
707 
708 
709 T
Intlist_filter(T list,bool * deletep)710 Intlist_filter (T list, bool *deletep) {
711   T newlist = NULL, next;
712   int i = 0;
713 
714   while (list) {
715     next = list->rest;
716     if (deletep[i++] == false) {
717       /* Push cell onto newlist */
718       list->rest = newlist;
719       newlist = list;
720     } else {
721       FREE(list);
722     }
723     list = next;
724   }
725 
726   /* return Intlist_reverse(newlist); */
727   return newlist;
728 }
729