1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2006 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 equals TARGET
223 according to COMPARE given auxiliary data AUX.
224 Returns R1 if no node in R0...R1 equals TARGET. */
226 llx_find_equal (const struct llx *r0, const struct llx *r1,
228 llx_compare_func *compare, void *aux)
232 for (x = r0; x != r1; x = llx_next (x))
233 if (compare (llx_data (x), target, aux) == 0)
235 return (struct llx *) x;
238 /* Returns the first node in R0...R1 for which PREDICATE returns
239 true given auxiliary data AUX.
240 Returns R1 if PREDICATE does not return true for any node in
243 llx_find_if (const struct llx *r0, const struct llx *r1,
244 llx_predicate_func *predicate, void *aux)
248 for (x = r0; x != r1; x = llx_next (x))
249 if (predicate (llx_data (x), aux))
251 return (struct llx *) x;
254 /* Compares each pair of adjacent nodes in R0...R1
255 using COMPARE with auxiliary data AUX
256 and returns the first node of the first pair that compares
258 Returns R1 if no pair compares equal. */
260 llx_find_adjacent_equal (const struct llx *r0, const struct llx *r1,
261 llx_compare_func *compare, void *aux)
265 const struct llx *x, *y;
267 for (x = r0, y = llx_next (x); y != r1; x = y, y = llx_next (y))
268 if (compare (llx_data (x), llx_data (y), aux) == 0)
269 return (struct llx *) x;
272 return (struct llx *) r1;
275 /* Returns the number of nodes in R0...R1.
276 Executes in O(n) time in the return value. */
278 llx_count_range (const struct llx *r0, const struct llx *r1)
280 return ll_count_range (&r0->ll, &r1->ll);
283 /* Counts and returns the number of nodes in R0...R1 that equal
284 TARGET according to COMPARE given auxiliary data AUX. */
286 llx_count_equal (const struct llx *r0, const struct llx *r1,
288 llx_compare_func *compare, void *aux)
294 for (x = r0; x != r1; x = llx_next (x))
295 if (compare (llx_data (x), target, aux) == 0)
300 /* Counts and returns the number of nodes in R0...R1 for which
301 PREDICATE returns true given auxiliary data AUX. */
303 llx_count_if (const struct llx *r0, const struct llx *r1,
304 llx_predicate_func *predicate, void *aux)
310 for (x = r0; x != r1; x = llx_next (x))
311 if (predicate (llx_data (x), aux))
316 /* Returns the greatest node in R0...R1 according to COMPARE
317 given auxiliary data AUX.
318 Returns the first of multiple, equal maxima. */
320 llx_max (const struct llx *r0, const struct llx *r1,
321 llx_compare_func *compare, void *aux)
323 const struct llx *max = r0;
328 for (x = llx_next (r0); x != r1; x = llx_next (x))
329 if (compare (llx_data (x), llx_data (max), aux) > 0)
332 return (struct llx *) max;
335 /* Returns the least node in R0...R1 according to COMPARE given
337 Returns the first of multiple, equal minima. */
339 llx_min (const struct llx *r0, const struct llx *r1,
340 llx_compare_func *compare, void *aux)
342 const struct llx *min = r0;
347 for (x = llx_next (r0); x != r1; x = llx_next (x))
348 if (compare (llx_data (x), llx_data (min), aux) < 0)
351 return (struct llx *) min;
354 /* Lexicographically compares A0...A1 to B0...B1.
355 Returns negative if A0...A1 < B0...B1,
356 zero if A0...A1 == B0...B1, and
357 positive if A0...A1 > B0...B1
358 according to COMPARE given auxiliary data AUX. */
360 llx_lexicographical_compare_3way (const struct llx *a0, const struct llx *a1,
361 const struct llx *b0, const struct llx *b1,
362 llx_compare_func *compare, void *aux)
371 int cmp = compare (llx_data (a0), llx_data (b0), aux);
380 /* Calls ACTION with auxiliary data AUX
381 for every node in R0...R1 in order. */
383 llx_apply (struct llx *r0, struct llx *r1,
384 llx_action_func *action, void *aux)
388 for (llx = r0; llx != r1; llx = llx_next (llx))
389 action (llx_data (llx), aux);
392 /* Reverses the order of nodes R0...R1. */
394 llx_reverse (struct llx *r0, struct llx *r1)
396 ll_reverse (&r0->ll, &r1->ll);
399 /* Arranges R0...R1 into the lexicographically next greater
400 permutation. Returns true if successful.
401 If R0...R1 is already the lexicographically greatest
402 permutation of its elements (i.e. ordered from greatest to
403 smallest), arranges them into the lexicographically least
404 permutation (i.e. ordered from smallest to largest) and
406 COMPARE with auxiliary data AUX is used to compare nodes. */
408 llx_next_permutation (struct llx *r0, struct llx *r1,
409 llx_compare_func *compare, void *aux)
413 struct llx *i = llx_prev (r1);
417 if (compare (llx_data (i), llx_data (llx_next (i)), aux) < 0)
420 for (j = llx_prev (r1);
421 compare (llx_data (i), llx_data (j), aux) >= 0;
425 llx_reverse (llx_next (j), r1);
430 llx_reverse (r0, r1);
436 /* Arranges R0...R1 into the lexicographically next lesser
437 permutation. Returns true if successful.
438 If R0...R1 is already the lexicographically least
439 permutation of its elements (i.e. ordered from smallest to
440 greatest), arranges them into the lexicographically greatest
441 permutation (i.e. ordered from largest to smallest) and
443 COMPARE with auxiliary data AUX is used to compare nodes. */
445 llx_prev_permutation (struct llx *r0, struct llx *r1,
446 llx_compare_func *compare, void *aux)
450 struct llx *i = llx_prev (r1);
454 if (compare (llx_data (i), llx_data (llx_next (i)), aux) > 0)
457 for (j = llx_prev (r1);
458 compare (llx_data (i), llx_data (j), aux) <= 0;
462 llx_reverse (llx_next (j), r1);
467 llx_reverse (r0, r1);
473 /* Sorts R0...R1 into ascending order
474 according to COMPARE given auxiliary data AUX.
475 In use, keep in mind that R0 may move during the sort, so that
476 afterward R0...R1 may denote a different range.
477 (On the other hand, R1 is fixed in place.)
478 Runs in O(n lg n) time in the number of nodes in the range. */
480 llx_sort (struct llx *r0, struct llx *r1, llx_compare_func *compare, void *aux)
483 size_t output_run_cnt;
485 if (r0 == r1 || llx_next (r0) == r1)
488 pre_r0 = llx_prev (r0);
491 struct llx *a0 = llx_next (pre_r0);
492 for (output_run_cnt = 1; ; output_run_cnt++)
494 struct llx *a1 = llx_find_run (a0, r1, compare, aux);
495 struct llx *a2 = llx_find_run (a1, r1, compare, aux);
499 a0 = llx_merge (a0, a1, a1, a2, compare, aux);
502 while (output_run_cnt > 1);
505 /* Finds the extent of a run of nodes of increasing value
506 starting at R0 and extending no farther than R1.
507 Returns the first node in R0...R1 that is less than the
508 preceding node, or R1 if R0...R1 are arranged in nondecreasing
511 llx_find_run (const struct llx *r0, const struct llx *r1,
512 llx_compare_func *compare, void *aux)
520 while (r0 != r1 && compare (llx_data (llx_prev (r0)),
521 llx_data (r0), aux) <= 0);
524 return (struct llx *) r0;
527 /* Merges B0...B1 into A0...A1 according to COMPARE given
529 The ranges may be in the same list or different lists, but
531 The merge is "stable" if A0...A1 is considered to precede
532 B0...B1, regardless of their actual ordering.
533 Runs in O(n) time in the total number of nodes in the ranges. */
535 llx_merge (struct llx *a0, struct llx *a1, struct llx *b0, struct llx *b1,
536 llx_compare_func *compare, void *aux)
538 if (a0 != a1 && b0 != b1)
543 if (compare (llx_data (a0), llx_data (b0), aux) <= 0)
547 llx_splice (llx_next (a0), b0, llx_next (b1));
548 return llx_next (b1);
558 llx_splice (a0, x, b0);
562 llx_splice (a0, b0, llx_next (b0));
563 return llx_next (a1);
569 llx_splice (a0, b0, b1);
574 /* Returns true if R0...R1 is sorted in ascending order according
575 to COMPARE given auxiliary data AUX,
578 llx_is_sorted (const struct llx *r0, const struct llx *r1,
579 llx_compare_func *compare, void *aux)
581 return llx_find_run (r0, r1, compare, aux) == r1;
584 /* Removes all but the first in each group of sequential
585 duplicates in R0...R1. Duplicates are determined using
586 COMPARE given auxiliary data AUX. Removed duplicates are
587 inserted before DUPS if it is nonnull; otherwise, the removed
588 duplicates are freed with MANAGER.
589 Only sequential duplicates are removed. llx_sort() may be used
590 to bring duplicates together, or llx_sort_unique() can do both
593 llx_unique (struct llx *r0, struct llx *r1, struct llx *dups,
594 llx_compare_func *compare, void *aux,
595 const struct llx_manager *manager)
604 struct llx *y = llx_next (x);
611 if (compare (llx_data (x), llx_data (y), aux) == 0)
614 llx_splice (dups, y, llx_next (y));
616 llx_remove (y, manager);
629 /* Sorts R0...R1 and removes duplicates.
630 Removed duplicates are inserted before DUPS if it is nonnull;
631 otherwise, the removed duplicates are freed with MANAGER.
632 Comparisons are made with COMPARE given auxiliary data AUX.
633 In use, keep in mind that R0 may move during the sort, so that
634 afterward R0...R1 may denote a different range.
635 (On the other hand, R1 is fixed in place.)
636 Runs in O(n lg n) time in the number of nodes in the range. */
638 llx_sort_unique (struct llx *r0, struct llx *r1, struct llx *dups,
639 llx_compare_func *compare, void *aux,
640 const struct llx_manager *manager)
642 struct llx *pre_r0 = llx_prev (r0);
643 llx_sort (r0, r1, compare, aux);
644 llx_unique (llx_next (pre_r0), r1, dups, compare, aux, manager);
647 /* Inserts DATA in the proper position in R0...R1, which must
648 be sorted according to COMPARE given auxiliary data AUX.
649 If DATA is equal to one or more existing nodes in R0...R1,
650 then it is inserted after the existing nodes it equals.
651 Returns the new node (allocated with MANAGER), or a null
652 pointer if memory allocation failed.
653 Runs in O(n) time in the number of nodes in the range. */
655 llx_insert_ordered (struct llx *r0, struct llx *r1, void *data,
656 llx_compare_func *compare, void *aux,
657 const struct llx_manager *manager)
661 for (x = r0; x != r1; x = llx_next (x))
662 if (compare (llx_data (x), data, aux) > 0)
664 return llx_insert (x, data, manager);
667 /* Partitions R0...R1 into those nodes for which PREDICATE given
668 auxiliary data AUX returns true, followed by those for which
669 PREDICATE returns false.
670 Returns the first node in the "false" group, or R1 if
671 PREDICATE is true for every node in R0...R1.
672 The partition is "stable" in that the nodes in each group
673 retain their original relative order.
674 Runs in O(n) time in the number of nodes in the range. */
676 llx_partition (struct llx *r0, struct llx *r1,
677 llx_predicate_func *predicate, void *aux)
685 else if (!predicate (llx_data (r0), aux))
691 for (t0 = r0;; t0 = t1)
699 while (!predicate (llx_data (t0), aux));
707 llx_splice (r0, t0, t1);
711 while (predicate (llx_data (t1), aux));
713 llx_splice (r0, t0, t1);
717 /* Verifies that R0...R1 is parititioned into a sequence of nodes
718 for which PREDICATE given auxiliary data AUX returns true,
719 followed by those for which PREDICATE returns false.
720 Returns a null pointer if R0...R1 is not partitioned this way.
721 Otherwise, returns the first node in the "false" group, or R1
722 if PREDICATE is true for every node in R0...R1. */
724 llx_find_partition (const struct llx *r0, const struct llx *r1,
725 llx_predicate_func *predicate, void *aux)
727 const struct llx *partition, *x;
729 for (partition = r0; partition != r1; partition = llx_next (partition))
730 if (!predicate (llx_data (partition), aux))
733 for (x = partition; x != r1; x = llx_next (x))
734 if (predicate (llx_data (x), aux))
737 return (struct llx *) partition;
740 /* Allocates and returns a node using malloc. */
742 malloc_allocate_node (void *aux UNUSED)
744 return malloc (sizeof (struct llx));
747 /* Releases node LLX with free. */
749 malloc_release_node (struct llx *llx, void *aux UNUSED)
754 /* Manager that uses the standard malloc and free routines. */
755 const struct llx_manager llx_malloc_mgr =
757 malloc_allocate_node,