1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2006, 2009 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* External, circular doubly linked list. */
19 /* These library routines have no external dependencies, other
20 than ll.c and the standard C library.
22 If you add routines in this file, please add a corresponding
23 test to llx-test.c. This test program should achieve 100%
24 coverage of lines and branches in this code, as reported by
31 #include <libpspp/llx.h>
36 /* Destroys LIST and frees all of its nodes using MANAGER.
37 If DESTRUCTOR is non-null, each node in the list will be
38 passed to it in list order, with AUX as auxiliary data, before
39 that node is destroyed. */
41 llx_destroy (struct llx_list *list, llx_action_func *destructor, void *aux,
42 const struct llx_manager *manager)
44 struct llx *llx, *next;
46 for (llx = llx_head (list); llx != llx_null (list); llx = next)
48 next = llx_next (llx);
49 if (destructor != NULL)
50 destructor (llx_data (llx), aux);
51 manager->release (llx, manager->aux);
55 /* Returns the number of nodes in LIST (not counting the null
56 node). Executes in O(n) time in the length of the list. */
58 llx_count (const struct llx_list *list)
60 return llx_count_range (llx_head (list), llx_null (list));
63 /* Inserts DATA at the head of LIST.
64 Returns the new node (allocated with MANAGER), or a null
65 pointer if memory allocation failed. */
67 llx_push_head (struct llx_list *list, void *data,
68 const struct llx_manager *manager)
70 return llx_insert (llx_head (list), data, manager);
73 /* Inserts DATA at the tail of LIST.
74 Returns the new node (allocated with MANAGER), or a null
75 pointer if memory allocation failed. */
77 llx_push_tail (struct llx_list *list, void *data,
78 const struct llx_manager *manager)
80 return llx_insert (llx_null (list), data, manager);
83 /* Removes the first node in LIST, which must not be empty,
84 and returns the data that the node contained.
85 Frees the node removed with MANAGER. */
87 llx_pop_head (struct llx_list *list, const struct llx_manager *manager)
89 struct llx *llx = llx_from_ll (ll_head (&list->ll_list));
90 void *data = llx_data (llx);
91 llx_remove (llx, manager);
95 /* Removes the last node in LIST, which must not be empty,
96 and returns the data that the node contained.
97 Frees the node removed with MANAGER. */
99 llx_pop_tail (struct llx_list *list, const struct llx_manager *manager)
101 struct llx *llx = llx_from_ll (ll_tail (&list->ll_list));
102 void *data = llx_data (llx);
103 llx_remove (llx, manager);
107 /* Inserts DATA before BEFORE.
108 Returns the new node (allocated with MANAGER), or a null
109 pointer if memory allocation failed. */
111 llx_insert (struct llx *before, void *data, const struct llx_manager *manager)
113 struct llx *llx = manager->allocate (manager->aux);
117 ll_insert (&before->ll, &llx->ll);
122 /* Removes R0...R1 from their current list
123 and inserts them just before BEFORE. */
125 llx_splice (struct llx *before, struct llx *r0, struct llx *r1)
127 ll_splice (&before->ll, &r0->ll, &r1->ll);
130 /* Exchanges the positions of A and B,
131 which may be in the same list or different lists. */
133 llx_swap (struct llx *a, struct llx *b)
135 ll_swap (&a->ll, &b->ll);
138 /* Exchanges the positions of A0...A1 and B0...B1,
139 which may be in the same list or different lists but must not
142 llx_swap_range (struct llx *a0, struct llx *a1,
143 struct llx *b0, struct llx *b1)
145 ll_swap_range (&a0->ll, &a1->ll, &b0->ll, &b1->ll);
148 /* Removes LLX from its list
149 and returns the node that formerly followed it.
150 Frees the node removed with MANAGER. */
152 llx_remove (struct llx *llx, const struct llx_manager *manager)
154 struct llx *next = llx_next (llx);
155 ll_remove (&llx->ll);
156 manager->release (llx, manager->aux);
160 /* Removes R0...R1 from their list.
161 Frees the removed nodes with MANAGER. */
163 llx_remove_range (struct llx *r0, struct llx *r1,
164 const struct llx_manager *manager)
168 for (llx = r0; llx != r1; )
169 llx = llx_remove (llx, manager);
172 /* Removes from R0...R1 all the nodes that equal TARGET
173 according to COMPARE given auxiliary data AUX.
174 Frees the removed nodes with MANAGER.
175 Returns the number of nodes removed. */
177 llx_remove_equal (struct llx *r0, struct llx *r1, const void *target,
178 llx_compare_func *compare, void *aux,
179 const struct llx_manager *manager)
185 for (x = r0; x != r1; )
186 if (compare (llx_data (x), target, aux) == 0)
188 x = llx_remove (x, manager);
197 /* Removes from R0...R1 all the nodes for which PREDICATE returns
198 true given auxiliary data AUX.
199 Frees the removed nodes with MANAGER.
200 Returns the number of nodes removed. */
202 llx_remove_if (struct llx *r0, struct llx *r1,
203 llx_predicate_func *predicate, void *aux,
204 const struct llx_manager *manager)
210 for (x = r0; x != r1; )
211 if (predicate (llx_data (x), aux))
213 x = llx_remove (x, manager);
222 /* Returns the first node in R0...R1 that has data TARGET.
223 Returns NULL if no node in R0...R1 equals TARGET. */
225 llx_find (const struct llx *r0, const struct llx *r1, const void *target)
229 for (x = r0; x != r1; x = llx_next (x))
230 if (llx_data (x) == target)
231 return CONST_CAST (struct llx *, x);
236 /* Returns the first node in R0...R1 that equals TARGET
237 according to COMPARE given auxiliary data AUX.
238 Returns R1 if no node in R0...R1 equals TARGET. */
240 llx_find_equal (const struct llx *r0, const struct llx *r1,
242 llx_compare_func *compare, void *aux)
246 for (x = r0; x != r1; x = llx_next (x))
247 if (compare (llx_data (x), target, aux) == 0)
249 return CONST_CAST (struct llx *, x);
252 /* Returns the first node in R0...R1 for which PREDICATE returns
253 true given auxiliary data AUX.
254 Returns R1 if PREDICATE does not return true for any node in
257 llx_find_if (const struct llx *r0, const struct llx *r1,
258 llx_predicate_func *predicate, void *aux)
262 for (x = r0; x != r1; x = llx_next (x))
263 if (predicate (llx_data (x), aux))
265 return CONST_CAST (struct llx *, x);
268 /* Compares each pair of adjacent nodes in R0...R1
269 using COMPARE with auxiliary data AUX
270 and returns the first node of the first pair that compares
272 Returns R1 if no pair compares equal. */
274 llx_find_adjacent_equal (const struct llx *r0, const struct llx *r1,
275 llx_compare_func *compare, void *aux)
279 const struct llx *x, *y;
281 for (x = r0, y = llx_next (x); y != r1; x = y, y = llx_next (y))
282 if (compare (llx_data (x), llx_data (y), aux) == 0)
283 return CONST_CAST (struct llx *, x);
286 return CONST_CAST (struct llx *, r1);
289 /* Returns the number of nodes in R0...R1.
290 Executes in O(n) time in the return value. */
292 llx_count_range (const struct llx *r0, const struct llx *r1)
294 return ll_count_range (&r0->ll, &r1->ll);
297 /* Counts and returns the number of nodes in R0...R1 that equal
298 TARGET according to COMPARE given auxiliary data AUX. */
300 llx_count_equal (const struct llx *r0, const struct llx *r1,
302 llx_compare_func *compare, void *aux)
308 for (x = r0; x != r1; x = llx_next (x))
309 if (compare (llx_data (x), target, aux) == 0)
314 /* Counts and returns the number of nodes in R0...R1 for which
315 PREDICATE returns true given auxiliary data AUX. */
317 llx_count_if (const struct llx *r0, const struct llx *r1,
318 llx_predicate_func *predicate, void *aux)
324 for (x = r0; x != r1; x = llx_next (x))
325 if (predicate (llx_data (x), aux))
330 /* Returns the greatest node in R0...R1 according to COMPARE
331 given auxiliary data AUX.
332 Returns the first of multiple, equal maxima. */
334 llx_max (const struct llx *r0, const struct llx *r1,
335 llx_compare_func *compare, void *aux)
337 const struct llx *max = r0;
342 for (x = llx_next (r0); x != r1; x = llx_next (x))
343 if (compare (llx_data (x), llx_data (max), aux) > 0)
346 return CONST_CAST (struct llx *, max);
349 /* Returns the least node in R0...R1 according to COMPARE given
351 Returns the first of multiple, equal minima. */
353 llx_min (const struct llx *r0, const struct llx *r1,
354 llx_compare_func *compare, void *aux)
356 const struct llx *min = r0;
361 for (x = llx_next (r0); x != r1; x = llx_next (x))
362 if (compare (llx_data (x), llx_data (min), aux) < 0)
365 return CONST_CAST (struct llx *, min);
368 /* Lexicographically compares A0...A1 to B0...B1.
369 Returns negative if A0...A1 < B0...B1,
370 zero if A0...A1 == B0...B1, and
371 positive if A0...A1 > B0...B1
372 according to COMPARE given auxiliary data AUX. */
374 llx_lexicographical_compare_3way (const struct llx *a0, const struct llx *a1,
375 const struct llx *b0, const struct llx *b1,
376 llx_compare_func *compare, void *aux)
385 int cmp = compare (llx_data (a0), llx_data (b0), aux);
394 /* Calls ACTION with auxiliary data AUX
395 for every node in R0...R1 in order. */
397 llx_apply (struct llx *r0, struct llx *r1,
398 llx_action_func *action, void *aux)
402 for (llx = r0; llx != r1; llx = llx_next (llx))
403 action (llx_data (llx), aux);
406 /* Reverses the order of nodes R0...R1. */
408 llx_reverse (struct llx *r0, struct llx *r1)
410 ll_reverse (&r0->ll, &r1->ll);
413 /* Arranges R0...R1 into the lexicographically next greater
414 permutation. Returns true if successful.
415 If R0...R1 is already the lexicographically greatest
416 permutation of its elements (i.e. ordered from greatest to
417 smallest), arranges them into the lexicographically least
418 permutation (i.e. ordered from smallest to largest) and
420 COMPARE with auxiliary data AUX is used to compare nodes. */
422 llx_next_permutation (struct llx *r0, struct llx *r1,
423 llx_compare_func *compare, void *aux)
427 struct llx *i = llx_prev (r1);
431 if (compare (llx_data (i), llx_data (llx_next (i)), aux) < 0)
434 for (j = llx_prev (r1);
435 compare (llx_data (i), llx_data (j), aux) >= 0;
439 llx_reverse (llx_next (j), r1);
444 llx_reverse (r0, r1);
450 /* Arranges R0...R1 into the lexicographically next lesser
451 permutation. Returns true if successful.
452 If R0...R1 is already the lexicographically least
453 permutation of its elements (i.e. ordered from smallest to
454 greatest), arranges them into the lexicographically greatest
455 permutation (i.e. ordered from largest to smallest) and
457 COMPARE with auxiliary data AUX is used to compare nodes. */
459 llx_prev_permutation (struct llx *r0, struct llx *r1,
460 llx_compare_func *compare, void *aux)
464 struct llx *i = llx_prev (r1);
468 if (compare (llx_data (i), llx_data (llx_next (i)), aux) > 0)
471 for (j = llx_prev (r1);
472 compare (llx_data (i), llx_data (j), aux) <= 0;
476 llx_reverse (llx_next (j), r1);
481 llx_reverse (r0, r1);
487 /* Sorts R0...R1 into ascending order
488 according to COMPARE given auxiliary data AUX.
489 In use, keep in mind that R0 may move during the sort, so that
490 afterward R0...R1 may denote a different range.
491 (On the other hand, R1 is fixed in place.)
492 Runs in O(n lg n) time in the number of nodes in the range. */
494 llx_sort (struct llx *r0, struct llx *r1, llx_compare_func *compare, void *aux)
497 size_t output_run_cnt;
499 if (r0 == r1 || llx_next (r0) == r1)
502 pre_r0 = llx_prev (r0);
505 struct llx *a0 = llx_next (pre_r0);
506 for (output_run_cnt = 1; ; output_run_cnt++)
508 struct llx *a1 = llx_find_run (a0, r1, compare, aux);
509 struct llx *a2 = llx_find_run (a1, r1, compare, aux);
513 a0 = llx_merge (a0, a1, a1, a2, compare, aux);
516 while (output_run_cnt > 1);
519 /* Finds the extent of a run of nodes of increasing value
520 starting at R0 and extending no farther than R1.
521 Returns the first node in R0...R1 that is less than the
522 preceding node, or R1 if R0...R1 are arranged in nondecreasing
525 llx_find_run (const struct llx *r0, const struct llx *r1,
526 llx_compare_func *compare, void *aux)
534 while (r0 != r1 && compare (llx_data (llx_prev (r0)),
535 llx_data (r0), aux) <= 0);
538 return CONST_CAST (struct llx *, r0);
541 /* Merges B0...B1 into A0...A1 according to COMPARE given
543 The ranges may be in the same list or different lists, but
545 The merge is "stable" if A0...A1 is considered to precede
546 B0...B1, regardless of their actual ordering.
547 Runs in O(n) time in the total number of nodes in the ranges. */
549 llx_merge (struct llx *a0, struct llx *a1, struct llx *b0, struct llx *b1,
550 llx_compare_func *compare, void *aux)
552 if (a0 != a1 && b0 != b1)
557 if (compare (llx_data (a0), llx_data (b0), aux) <= 0)
561 llx_splice (llx_next (a0), b0, llx_next (b1));
562 return llx_next (b1);
572 llx_splice (a0, x, b0);
576 llx_splice (a0, b0, llx_next (b0));
577 return llx_next (a1);
583 llx_splice (a0, b0, b1);
588 /* Returns true if R0...R1 is sorted in ascending order according
589 to COMPARE given auxiliary data AUX,
592 llx_is_sorted (const struct llx *r0, const struct llx *r1,
593 llx_compare_func *compare, void *aux)
595 return llx_find_run (r0, r1, compare, aux) == r1;
598 /* Removes all but the first in each group of sequential
599 duplicates in R0...R1. Duplicates are determined using
600 COMPARE given auxiliary data AUX. Removed duplicates are
601 inserted before DUPS if it is nonnull; otherwise, the removed
602 duplicates are freed with MANAGER.
603 Only sequential duplicates are removed. llx_sort() may be used
604 to bring duplicates together, or llx_sort_unique() can do both
607 llx_unique (struct llx *r0, struct llx *r1, struct llx *dups,
608 llx_compare_func *compare, void *aux,
609 const struct llx_manager *manager)
618 struct llx *y = llx_next (x);
625 if (compare (llx_data (x), llx_data (y), aux) == 0)
628 llx_splice (dups, y, llx_next (y));
630 llx_remove (y, manager);
643 /* Sorts R0...R1 and removes duplicates.
644 Removed duplicates are inserted before DUPS if it is nonnull;
645 otherwise, the removed duplicates are freed with MANAGER.
646 Comparisons are made with COMPARE given auxiliary data AUX.
647 In use, keep in mind that R0 may move during the sort, so that
648 afterward R0...R1 may denote a different range.
649 (On the other hand, R1 is fixed in place.)
650 Runs in O(n lg n) time in the number of nodes in the range. */
652 llx_sort_unique (struct llx *r0, struct llx *r1, struct llx *dups,
653 llx_compare_func *compare, void *aux,
654 const struct llx_manager *manager)
656 struct llx *pre_r0 = llx_prev (r0);
657 llx_sort (r0, r1, compare, aux);
658 llx_unique (llx_next (pre_r0), r1, dups, compare, aux, manager);
661 /* Inserts DATA in the proper position in R0...R1, which must
662 be sorted according to COMPARE given auxiliary data AUX.
663 If DATA is equal to one or more existing nodes in R0...R1,
664 then it is inserted after the existing nodes it equals.
665 Returns the new node (allocated with MANAGER), or a null
666 pointer if memory allocation failed.
667 Runs in O(n) time in the number of nodes in the range. */
669 llx_insert_ordered (struct llx *r0, struct llx *r1, void *data,
670 llx_compare_func *compare, void *aux,
671 const struct llx_manager *manager)
675 for (x = r0; x != r1; x = llx_next (x))
676 if (compare (llx_data (x), data, aux) > 0)
678 return llx_insert (x, data, manager);
681 /* Partitions R0...R1 into those nodes for which PREDICATE given
682 auxiliary data AUX returns true, followed by those for which
683 PREDICATE returns false.
684 Returns the first node in the "false" group, or R1 if
685 PREDICATE is true for every node in R0...R1.
686 The partition is "stable" in that the nodes in each group
687 retain their original relative order.
688 Runs in O(n) time in the number of nodes in the range. */
690 llx_partition (struct llx *r0, struct llx *r1,
691 llx_predicate_func *predicate, void *aux)
699 else if (!predicate (llx_data (r0), aux))
705 for (t0 = r0;; t0 = t1)
713 while (!predicate (llx_data (t0), aux));
721 llx_splice (r0, t0, t1);
725 while (predicate (llx_data (t1), aux));
727 llx_splice (r0, t0, t1);
731 /* Verifies that R0...R1 is parititioned into a sequence of nodes
732 for which PREDICATE given auxiliary data AUX returns true,
733 followed by those for which PREDICATE returns false.
734 Returns a null pointer if R0...R1 is not partitioned this way.
735 Otherwise, returns the first node in the "false" group, or R1
736 if PREDICATE is true for every node in R0...R1. */
738 llx_find_partition (const struct llx *r0, const struct llx *r1,
739 llx_predicate_func *predicate, void *aux)
741 const struct llx *partition, *x;
743 for (partition = r0; partition != r1; partition = llx_next (partition))
744 if (!predicate (llx_data (partition), aux))
747 for (x = partition; x != r1; x = llx_next (x))
748 if (predicate (llx_data (x), aux))
751 return CONST_CAST (struct llx *, partition);
754 /* Allocates and returns a node using malloc. */
756 malloc_allocate_node (void *aux UNUSED)
758 return malloc (sizeof (struct llx));
761 /* Releases node LLX with free. */
763 malloc_release_node (struct llx *llx, void *aux UNUSED)
768 /* Manager that uses the standard malloc and free routines. */
769 const struct llx_manager llx_malloc_mgr =
771 malloc_allocate_node,