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