FORS Pipeline Reference Manual  4.12.5
list.c
1 /* $Id: list.c,v 1.19 2013-05-16 08:40:07 cgarcia Exp $
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16  */
17 
18 /*
19  * $Author: cgarcia $
20  * $Date: 2013-05-16 08:40:07 $
21  * $Revision: 1.19 $
22  * $Name: not supported by cvs2svn $
23  */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <list_void.h>
30 
31 #include <math.h>
32 #include <stdbool.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 
73 /* Same data structure as C++ STL's vector */
74 struct list
75 {
76  void **elements;
77  int size;
78  int back; /* Extra allocated space */
79 
80  int current; /* 1 element iteration */
81 
82  int current_p1, current_p2; /* pair iteration */
83 };
84 
88 //static void *(*const list_malloc)(size_t) = malloc;
89 //static void *(*const list_calloc)(size_t, size_t) = calloc;
90 //static void *(*const list_realloc)(void *, size_t) = realloc;
91 //static void (*const list_free)(const void *) = (void (*)(const void *))free;
92 static void *(*list_malloc)(size_t) = malloc;
93 static void *(*list_calloc)(size_t, size_t) = calloc;
94 static void *(*list_realloc)(void *, size_t) = realloc;
95 static void (*list_free)(const void *) = (void (*)(const void *))free;
96 
100 #include <assert.h>
101 #define assure(EXPR) assert(EXPR)
102 
107 list *
108 list_new(void)
109 {
110  list *l = list_malloc(sizeof(*l));
111 
112  l->elements = NULL;
113  l->size = 0;
114  l->back = 0;
115 
116  return l;
117 }
118 
125 list *
126 list_duplicate(const list *l, void * (*duplicate)(const void *))
127 {
128  assure( l != NULL );
129 
130  {
131  list *dupl = list_malloc(sizeof(*dupl));
132 
133  dupl->elements = list_malloc((l->size+l->back) * sizeof(*dupl->elements));
134  dupl->size = l->size;
135  dupl->back = l->back;
136  dupl->current = l->current;
137  dupl->current_p1 = l->current_p1;
138  dupl->current_p2 = l->current_p2;
139 
140  {
141  int i;
142  for (i = 0; i < l->size; i++) {
143  if (duplicate != NULL) {
144  dupl->elements[i] = duplicate(l->elements[i]);
145  }
146  else {
147  dupl->elements[i] = l->elements[i];
148  }
149  }
150  }
151 
152  return dupl;
153  }
154 }
155 
156 /*
157  * @brief Destructor
158  * @param l list to delete
159  * @param delete element copy constructor. If NULL,
160  * elements are not deleted.
161  */
162 void
163 list_delete_const(const list **l, void (*ldelete)(void **))
164 {
165  if (l != NULL && *l != NULL) {
166 
167  if (ldelete != NULL) {
168 
169  int i;
170  for (i = 0; i < (*l)->size; i++) {
171  ldelete(&((*l)->elements[i]));
172  }
173  }
174  list_free((*l)->elements);
175  list_free((*l)); *l = NULL;
176  }
177  return;
178 }
179 
180 void
181 list_delete(list **l, void (*ldelete)(void **))
182 {
183  list_delete_const((const list **)l, ldelete);
184  return;
185 }
186 
187 /*
188  * @brief Get list size
189  * @param l list
190  * @return number of elements in list
191  *
192  * Time: O(1)
193  */
194 int
195 list_size(const list *l)
196 {
197  assure( l != NULL );
198 
199  return l->size;
200 }
201 
202 /*
203  * @brief Insert element
204  * @param l list
205  * @param e element to insert. Must be non-NULL
206  * @return number of elements in list
207  *
208  * Time: Amortized O(1)
209  */
210 void
211 list_insert(list *l, void *e)
212 {
213  assure( e != NULL );
214 
215  if (l->back == 0) {
216  l->back = l->size + 1;
217  l->elements = list_realloc(l->elements, (l->size + l->back) * sizeof(*l->elements));
218  }
219 
220  l->size++;
221  l->back--;
222  l->elements[l->size - 1] = e;
223 
224  return;
225 }
226 
227 /*
228  * @brief Remove element
229  * @param l list
230  * @param e element to remove. Note: pointer comparison
231  * @return e
232  *
233  * The provided element must exist in the list.
234  * Only one occurrence of e is removed.
235  * The element is removed from the list, but not deallocated.
236  *
237  * For convenience, the function returns the provided element pointer.
238  * This is to allow code like
239  * @code
240  * element *e = element_list_remove(l, element_list_first(l));
241  * @endcode
242  *
243  * Time: Worst case O(n), O(1) for removing the element returned by list_first()
244  */
245 const void *
246 list_remove_const(list *l, const void *e)
247 {
248  assure( l != NULL );
249  assure( e != NULL );
250 
251  {
252  int i;
253  int indx = -1;
254  for (i = l->size - 1; i >= 0 && indx < 0; i--) {
255  if (l->elements[i] == e) {
256  indx = i;
257  }
258  }
259 
260  assure( indx >= 0 );
261 
262  for (i = indx; i < l->size-1; i++) {
263  l->elements[i] = l->elements[i+1];
264  }
265  }
266 
267  l->size--;
268  l->back++;
269 
270  if (l->back > 4 * l->size) {
271  /* Note: amortized constant time */
272  l->back = l->size;
273  l->elements = list_realloc(l->elements,
274  (l->size + l->back) * sizeof(*l->elements));
275  }
276 
277  return e;
278 }
279 
280 void *
281 list_remove(list *l, void *e)
282 {
283  return (void *)list_remove_const(l, e);
284 }
285 
286 /*
287  * @brief Reverse the order of list elements
288  * @param l list
289  * @return Nothing
290  *
291  * Time: O(N)
292  */
293 void
294 list_reverse(list *l)
295 {
296  int i, k;
297 
298  assure( l != NULL );
299 
300  for (i = 0, k = l->size-1; i < k; i++, k--)
301  {
302  void *tmp;
303  tmp = l->elements[i];
304  l->elements[i] = l->elements[k];
305  l->elements[k] = tmp;
306  }
307 
308  return;
309 }
310 
311 /*
312  * @brief Iterate
313  * @param l list
314  * @return first element, or NULL if list empty
315  *
316  * @code
317  * for(element *e = list_first(l);
318  * e != NULL;
319  * e = list_next(l)) {...}
320  * @endcode
321  *
322  * The list must not be modified between calls to list_first() or list_next()
323  *
324  * Note: It is not possible to have more simultaneous iterations over the same
325  * list. This functionality can be achived by duplicating the list.
326  *
327  * Time: O(1)
328  */
329 const void *
330 list_first_const(const list *l)
331 {
332  assure( l != NULL );
333 
334  if (l->size == 0) return NULL;
335 
336  /* Loop backwards, faster if user
337  erases the first element */
338 
339  ((list *)l)->current = l->size - 1;
340  return l->elements[l->current];
341 }
342 
343 void *
344 list_first(list *l)
345 {
346  return (void *)list_first_const(l);
347 }
348 
349 /*
350  * @brief Iterate
351  * @param l list
352  * @return next element, or NULL if no more elements
353  *
354  * See list_first().
355  *
356  * Time: O(1)
357  */
358 const void *
359 list_next_const(const list *l)
360 {
361  assure( l != NULL );
362 
363  if (l->size == 0) return NULL;
364 
365  ((list *)l)->current -= 1;
366 
367  if (l->current < 0) return NULL;
368  else return l->elements[l->current];
369 }
370 
371 void *
372 list_next(list *l)
373 {
374  return (void *)list_next_const(l);
375 }
376 
377 /*
378  * @brief Iterate through pairs
379  * @param l list
380  * @param e1 (output) first pair 1st element, or NULL if list
381  has less than two elements
382  * @param e2 (output) first pair 2nd element
383  *
384  * The iteration is through the K(n,2) different pairs, i.e. the
385  * pair (e1,e2) is considered equal to the pair (e2,e1) and only
386  * visited once.
387  *
388  * @code
389  * for(list_first_pair(l, &e1, &e2);
390  * e1 != NULL;
391  * list_next_pair(l, &e1, &e2))
392  * @endcode
393  *
394  * The list must not be modified between calls to
395  * list_first_pair() or list_next_pair()
396  *
397  * The current position is cached in the list object. Therefore simultaneous
398  * pair iterations over the same list is not allowed.
399  *
400  * However, iterating pairs simultaneously with a 1 element iteration (using
401  * list_first() and list_next()) is allowed.
402  *
403  * Time: O(1)
404  */
405 void
406 list_first_pair_const(const list *l,
407  const void **e1,
408  const void **e2)
409 {
410  assure( l != NULL );
411  assure( e1 != NULL );
412  assure( e2 != NULL );
413 
414  if (l->size <= 1) {
415  *e1 = NULL;
416  *e2 = NULL;
417  return;
418  }
419 
420  ((list *)l)->current_p1 = l->size - 1;
421  ((list *)l)->current_p2 = l->size - 2;
422 
423  *e1 = l->elements[l->current_p1];
424  *e2 = l->elements[l->current_p2];
425 
426  return;
427 }
428 
429 void
430 list_first_pair(list *l,
431  void **e1,
432  void **e2)
433 {
434  list_first_pair_const(l,
435  (const void **)e1,
436  (const void **)e2);
437 
438  return;
439 }
440 
441 /*
442  * @brief Iterate through pairs
443  * @param l list
444  * @param e1 (output) next pair 1st element, or NULL if no more pairs
445  * @param e2 (output) next pair 2nd element, or NULL if no more pairs
446  *
447  * See list_first_pair().
448  *
449  * Time: O(1)
450  */
451 void
452 list_next_pair_const(const list *l,
453  const void **e1,
454  const void **e2)
455 {
456  assure( l != NULL );
457  assure( e1 != NULL );
458  assure( e2 != NULL );
459 
460  if (l->size <= 1) {
461  *e1 = NULL;
462  *e2 = NULL;
463  return;
464  }
465 
466  ((list *)l)->current_p2 -= 1;
467 
468  if (l->current_p2 < 0) {
469  ((list *)l)->current_p1 -= 1;
470  ((list *)l)->current_p2 = l->current_p1 - 1;
471  if (l->current_p2 < 0) {
472  *e1 = NULL;
473  *e2 = NULL;
474  return;
475  }
476  *e1 = l->elements[l->current_p1];
477  *e2 = l->elements[l->current_p2];
478  return;
479  }
480 
481  *e2 = l->elements[l->current_p2];
482  return;
483 }
484 
485 void
486 list_next_pair(list *l,
487  void **e1,
488  void **e2)
489 {
490  list_next_pair_const(l, (const void **)e1, (const void **)e2);
491  return;
492 }
493 
506 list *
508  void *(*duplicate)(const void *),
509  bool (*predicate)(const void *, void *),
510  void *data)
511 {
512  assure( l != NULL );
513  assure( duplicate != NULL);
514  assure( predicate != NULL);
515 
516  {
517  list *ex = list_new();
518  int i;
519 
520  for (i = 0; i < l->size; i++) {
521  if (predicate(l->elements[i], data)) {
522  list_insert(ex, duplicate(l->elements[i]));
523  }
524  }
525 
526  return ex;
527  }
528 }
529 
530 /*
531  * @brief Find minimum element
532  * @param l non-empty list
533  * @param less_than comparison function which must return true, iff
534  * its first argument is considered less than the second argument.
535  * The 3rd argument is auxillary data used for the comparison.
536  * The provided function should be a strict ordering (i.e. behave
537  * like <)
538  * @param data Auxillary data sent to the comparison function. May be NULL.
539  * @return minimum element
540  *
541  * Time: O(n)
542  */
543 void *
544 list_min(list *l, list_func_lt less_than, void *data)
545 {
546  assure( l != NULL );
547  assure( less_than != NULL);
548  assure( list_size(l) > 0);
549 
550  {
551  int minindex = 0;
552  int i;
553  for (i = 1; i < l->size; i++) {
554  if (less_than(l->elements[i], l->elements[minindex], data))
555  minindex = i;
556  }
557 
558  return l->elements[minindex];
559  }
560 }
561 
562 /*
563  * @brief Find minimum element
564  * @param l non-empty list
565  * @param eval evaluation function
566  * @param data Auxillary data sent to the evaluation function. May be NULL.
567  * @return minimum (as defined by the evaluation function) element
568  *
569  * Time: O(n)
570  */
571 void *
572 list_min_val(list *l, list_func_eval eval, void *data)
573 {
574  assure( l != NULL );
575  assure( eval != NULL);
576  assure( list_size(l) > 0);
577 
578  {
579  int minindex = 0;
580  double minval = eval(l->elements[0], data);
581  int i;
582 
583  for (i = 1; i < l->size; i++) {
584  double val = eval(l->elements[i], data);
585  if (val < minval) {
586  minval = val;
587  minindex = i;
588  }
589  }
590 
591  return l->elements[minindex];
592  }
593 }
594 
595 /*
596  * @brief Find maximum element
597  * @param l non-empty list
598  * @param eval evaluation function
599  * @param data Auxillary data sent to the evaluation function. May be NULL.
600  * @return maximum (as defined by the evaluation function) element
601  *
602  * Time: O(n)
603  */
604 void *
605 list_max_val(list *l, list_func_eval eval, void *data)
606 {
607  assure( l != NULL );
608  assure( eval != NULL);
609  assure( list_size(l) > 0);
610 
611  {
612  int maxindex = 0;
613  double maxval = eval(l->elements[0], data);
614  int i;
615 
616  for (i = 1; i < l->size; i++) {
617  double val = eval(l->elements[i], data);
618  if (val > maxval) {
619  maxval = val;
620  maxindex = i;
621  }
622  }
623 
624  return l->elements[maxindex];
625  }
626 }
627 
628 /*
629  * @brief Find maximum element
630  * @param l see list_min()
631  * @param less_than see list_min()
632  * @param data see list_min()
633  * @return maximum element
634  *
635  * Time: O(n)
636  */
637 const void *
638 list_max_const(const list *l, list_func_lt less_than, void *data)
639 {
640  assure( l != NULL );
641  assure( less_than != NULL);
642  assure( list_size(l) > 0);
643 
644  {
645  int maxindex = 0;
646  int i;
647  for (i = 1; i < l->size; i++) {
648  if (!less_than(l->elements[i], l->elements[maxindex], data))
649  maxindex = i;
650  }
651 
652  return l->elements[maxindex];
653  }
654 }
655 
656 void *
657 list_max(list *l, list_func_lt less_than, void *data)
658 {
659  return (void *)list_max_const(l, less_than, data);
660 }
661 
662 
663 /*
664  * @brief Find k'th element
665  * @param l non-empty list
666  * @param k between 1 and list size, inclusive.
667  * @param n list size
668  * @param less_than see list_min()
669  * @param data see list_min()
670  * @return k'th element
671  *
672  * Be careful to provide an irreflexive comparison function (i.e.
673  * x < x must always be false), or this function may not return.
674  *
675  * Time: Worst case O(n*n). Average over all input: O(n)
676  */
677 static const void *
678 kth(const void *a[], int k, int n, list_func_lt less_than, void *data)
679 {
680  int i, j, lo, hi;
681 
682  k -= 1;
683 
684  lo = 0;
685  hi = n - 1;
686  while (lo < hi) {
687  const void *pivot = a[k];//fixme select randomly, swap with a[k]
688  i = lo;
689  j = hi;
690  do {
691  while (less_than(a[i], pivot, data)) i++;
692  while (less_than(pivot, a[j], data)) {
693  j--;
694  }
695  if (i <= j) {
696  const void *tmp = a[i];
697  a[i] = a[j];
698  a[j] = tmp;
699  i++; j--;
700  }
701  } while (i <= j);
702  if (j < k) lo = i;
703  if (k < i) hi = j;
704  }
705  return a[k];
706 }
707 
708 const void *
709 list_kth_const(const list *l, int k,
710  list_func_lt less_than, void *data)
711 {
712  void *kp;
713  void **elemcpy;
714  int len;
715 
716  assure( l != NULL );
717  assure( 1 <= k && k <= l->size );
718 
719  /* the function kth() scrambles the elements, so copy them */
720  len = l->size * sizeof(*l->elements);
721  elemcpy = list_malloc(len);
722  memcpy(elemcpy, l->elements, len);
723 
724  kp = (void*)kth((const void **)elemcpy, k, l->size, less_than, data);
725 
726  list_free(elemcpy);
727 
728  return kp;
729 }
730 
731 void *
732 list_kth(list *l, int k,
733  list_func_lt less_than,
734  void *data)
735 {
736  return (void *)list_kth_const(l, k, less_than, data);
737 }
738 
739 /*
740  * @brief Determine order of elements given an evaluation function
741  * @param e1 first element
742  * @param e2 second element
743  * @param data containing the evaluation function, and
744  * additional data which is passed to the evaluation function
745  * @return true iff e1 evaluates to a number less than e2
746  */
747 static
748 bool val_less_than(const void *e1, const void *e2, void *data)
749 {
750  struct {
751  list_func_eval f;
752  void *aux_data;
753  } *d = data;
754  /* Cast is safe, see caller of this function */
755 
756 
757  /* Unfortunately, as the following commented code demonstrated,
758  with GCC-4.2.0 calling the evaluation function two times with the same
759  input can give two numbers which satisfy both equality (==) *and*
760  less than (<) (!) but not greater than (>). This causes the kth function
761  to loop infinitely.
762 
763  Avoid that by handling explicitly this special case.
764  */
765 
766  if (e1 == e2) return false;
767 
768  /*
769  double d1 = d->f(e1, d->aux_data);
770  fprintf(stderr, "%s got %f %g \n", __func__, d1, d1);
771  fprintf(stderr, "%.100f\n", d1);
772 
773  double d2 = d->f(e2, d->aux_data);
774  fprintf(stderr, "%s %d %d %d\n", __func__, i1, i2, i3);
775 
776  fprintf(stderr, "%s got %f %g %d %d\n", __func__, d2, d2, d1 < d2, e1 == e2);
777  fprintf(stderr, "%.100f %d %d %d %d %d\n", d2,
778  d1 < d2, d2 > d1, d1 == d2, d1 > d2, d2 < d1);
779 
780  fprintf(stderr, "l1 = %ld\n", d1);
781  fprintf(stderr, "l2 = %ld\n", d2);
782  */
783 
784  return (d->f(e1, d->aux_data) < d->f(e2, d->aux_data));
785 }
786 
787 /*
788  * @brief k'th element
789  * @param l list
790  * @param k counting from 1
791  * @param eval returns the value of an element
792  * @param data sent to eval
793  * @return a k'th element according to the evaluation function
794  */
795 const void *
796 list_kth_val_const(const list *l, int k, list_func_eval eval, void *data)
797 {
798  assure( l != NULL );
799  assure( 1 <= k && k <= l->size );
800  assure( eval != NULL );
801 
802  struct {
803  list_func_eval f;
804  void *aux_data;
805  } d;
806  d.f = eval;
807  d.aux_data = data;
808 
809  return list_kth_const(l, k, val_less_than, &d);
810 }
811 void *
812 list_kth_val(list *l, int k, list_func_eval eval, void *data)
813 {
814  return (void *) list_kth_val_const(l, k, eval, data);
815 }
816 
817 /*
818  * @brief Compute median
819  * @param l list
820  * @param eval returns the value of an element
821  * @param data additional data passed to eval
822  * @return median
823  *
824  * Time: Average O(n).
825  *
826  * For an even number of elements, the median is the
827  * average of the two central values.
828  */
829 double
830 list_median(const list *l, list_func_eval eval, void *data)
831 {
832  assure( l != NULL );
833  assure( eval != NULL );
834  assure( l->size > 0 );
835 
836  const void *median_element = list_kth_val_const(l, (l->size+1)/2, eval, data);
837 
838  double median_val = eval(median_element, data);
839 
840  if (list_size(l) && 2 == 0)
841  {
842  const void *other_median_element =
843  list_kth_val_const(l, (l->size+2)/2, eval, data);
844 
845  median_val = (median_val + eval(other_median_element, data) ) / 2.0;
846  }
847 
848  return median_val;
849 }
850 
851 /*
852  * @brief Compute mean
853  * @param l list
854  * @param eval returns the value of an element
855  * @param data additional data passed to eval
856  * @return arithmetic average
857  *
858  * Time: O(n).
859  */
860 double
861 list_mean(const list *l, list_func_eval eval, void *data)
862 {
863  assure( l != NULL );
864  assure( eval != NULL );
865  assure( l->size > 0 );
866 
867  double result = eval(l->elements[0], data);
868  int i;
869 
870  for (i = 1; i < l->size; i++) {
871  result += eval(l->elements[i], data);
872  }
873 
874  result /= l->size;
875 
876  return result;
877 }
878 
879 /*
880  * @brief Compute optimally weighted mean
881  * @param l list with two or more elements
882  * @param eval returns the value of an element
883  * @param data additional data passed to eval
884  * @param eval_err returns the error (1 sigma) of an element,
885  * must be positive
886  * @param data_err additional data passed to eval_err
887  * @param err (output) square root variance
888  * @param red_chisq (output) reduced chi square, may be NULL
889  * @return optimal mean
890  *
891  * average = [ sum x_i / sigma_i^2 ] / [sum 1 / sigma_i^2]
892  * variance = 1 / [sum 1 / sigma_i^2]
893  *
894  * chi^2/(n-1) = sum ((x_i - average) / sigma_i)^2 / (n-1)
895  *
896  * Time: O(n).
897  */
898 double
899 list_mean_optimal(const list *l,
900  list_func_eval eval, void *data_eval,
901  list_func_eval eval_err, void *data_err,
902  double *err,
903  double *red_chisq)
904 {
905  assure( l != NULL );
906  assure( l->size >= 1 );
907  assure( red_chisq == NULL || l->size >= 2 );
908  assure( eval != NULL );
909  assure( eval_err != NULL );
910  assure( err != NULL );
911 
912  double sum_weights = 0;
913  double opt_average = 0;
914  int i;
915 
916  for (i = 0; i < l->size; i++) {
917  void *e = l->elements[i];
918  double sigma = eval_err(e, data_err);
919 
920  assure( sigma > 0 );
921 
922  double weight = 1/(sigma*sigma);
923 
924  opt_average += eval(e, data_eval) * weight;
925  sum_weights += weight;
926  }
927  opt_average /= sum_weights;
928  *err = 1 / sqrt(sum_weights);
929 
930  if (red_chisq != NULL) {
931  *red_chisq = 0;
932  for (i = 0; i < l->size; i++) {
933  void *e = l->elements[i];
934  double residual = ((eval(e, data_eval) - opt_average)) / eval_err(e, data_err);
935  *red_chisq += residual * residual;
936  }
937  *red_chisq /= (l->size - 1);
938  }
939 
940  return opt_average;
941 }
942 
943 
944 
945 /*
946  * @brief Compute absolute deviation
947  * @param e1 element
948  * @param data reference value, and evaluation function
949  * and additional data passed to the evaluation function
950  * @return absolute difference between e1 and reference point
951  */
952 static double
953 abs_dev(const void *e1, void *data)
954 {
955  struct {
956  double ref;
957  list_func_eval f;
958  void *aux_data;
959  } *d = data;
960  /* Cast is safe, see caller */
961 
962  return fabs(d->f(e1, d->aux_data) - d->ref);
963 }
964 
965 /*
966  * @brief Compute median absolute deviation wrt median
967  * @param l list
968  * @param eval returns the value of an element
969  * @param data additional data passed to eval
970  * @return mad
971  *
972  * Time: Average O(n).
973  */
974 double
975 list_mad(list *l, list_func_eval eval, void *data)
976 {
977  assure( l != NULL );
978  assure( eval != NULL );
979 
980  double median = list_median(l, eval, data);
981 
982  struct {
983  double ref;
984  list_func_eval f;
985  void *aux_data;
986  } d;
987 
988  d.ref = median;
989  d.f = eval;
990  d.aux_data = data;
991 
992  return list_median(l, abs_dev, &d);
993 }
994 
list * list_duplicate(const list *l, void *(*duplicate)(const void *))
Copy constructor.
Definition: list.c:126
list * list_extract(const list *l, void *(*duplicate)(const void *), bool(*predicate)(const void *, void *), void *data)
Extract elements.
Definition: list.c:507
#define assure(EXPR)
Definition: list.c:101
list * list_new(void)
Constructor.
Definition: list.c:108
Definition: list.c:74
static void *(* list_malloc)(size_t)
Definition: list.c:92