FORS Pipeline Reference Manual 4.9.20
|
00001 /* $Id: list.c,v 1.18 2009/03/26 09:28:22 hlorch Exp $ 00002 * 00003 * This program is free software; you can redistribute it and/or modify 00004 * it under the terms of the GNU General Public License as published by 00005 * the Free Software Foundation; either version 2 of the License, or 00006 * (at your option) any later version. 00007 * 00008 * This program is distributed in the hope that it will be useful, 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 * GNU General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU General Public License 00014 * along with this program; if not, write to the Free Software 00015 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00016 */ 00017 00018 /* 00019 * $Author: hlorch $ 00020 * $Date: 2009/03/26 09:28:22 $ 00021 * $Revision: 1.18 $ 00022 * $Name: fors-4_9_20 $ 00023 */ 00024 00025 #ifdef HAVE_CONFIG_H 00026 #include <config.h> 00027 #endif 00028 00029 #include <list_void.h> 00030 00031 #include <math.h> 00032 #include <stdbool.h> 00033 #include <stdlib.h> 00034 #include <stdio.h> 00035 #include <string.h> 00036 00073 /* Same data structure as C++ STL's vector */ 00074 struct list 00075 { 00076 void **elements; 00077 int size; 00078 int back; /* Extra allocated space */ 00079 00080 int current; /* 1 element iteration */ 00081 00082 int current_p1, current_p2; /* pair iteration */ 00083 }; 00084 00088 //static void *(*const list_malloc)(size_t) = malloc; 00089 //static void *(*const list_calloc)(size_t, size_t) = calloc; 00090 //static void *(*const list_realloc)(void *, size_t) = realloc; 00091 //static void (*const list_free)(const void *) = (void (*)(const void *))free; 00092 static void *(*list_malloc)(size_t) = malloc; 00093 static void *(*list_calloc)(size_t, size_t) = calloc; 00094 static void *(*list_realloc)(void *, size_t) = realloc; 00095 static void (*list_free)(const void *) = (void (*)(const void *))free; 00096 00100 #include <assert.h> 00101 #define assure(EXPR) assert(EXPR) 00102 00107 list * 00108 list_new(void) 00109 { 00110 list *l = list_malloc(sizeof(*l)); 00111 00112 l->elements = NULL; 00113 l->size = 0; 00114 l->back = 0; 00115 00116 return l; 00117 } 00118 00125 list * 00126 list_duplicate(const list *l, void * (*duplicate)(const void *)) 00127 { 00128 assure( l != NULL ); 00129 00130 { 00131 list *dupl = list_malloc(sizeof(*dupl)); 00132 00133 dupl->elements = list_malloc((l->size+l->back) * sizeof(*dupl->elements)); 00134 dupl->size = l->size; 00135 dupl->back = l->back; 00136 dupl->current = l->current; 00137 dupl->current_p1 = l->current_p1; 00138 dupl->current_p2 = l->current_p2; 00139 00140 { 00141 int i; 00142 for (i = 0; i < l->size; i++) { 00143 if (duplicate != NULL) { 00144 dupl->elements[i] = duplicate(l->elements[i]); 00145 } 00146 else { 00147 dupl->elements[i] = l->elements[i]; 00148 } 00149 } 00150 } 00151 00152 return dupl; 00153 } 00154 } 00155 00156 /* 00157 * @brief Destructor 00158 * @param l list to delete 00159 * @param delete element copy constructor. If NULL, 00160 * elements are not deleted. 00161 */ 00162 void 00163 list_delete_const(const list **l, void (*delete)(void **)) 00164 { 00165 if (l != NULL && *l != NULL) { 00166 00167 if (delete != NULL) { 00168 00169 int i; 00170 for (i = 0; i < (*l)->size; i++) { 00171 delete(&((*l)->elements[i])); 00172 } 00173 } 00174 list_free((*l)->elements); 00175 list_free((*l)); *l = NULL; 00176 } 00177 return; 00178 } 00179 00180 void 00181 list_delete(list **l, void (*delete)(void **)) 00182 { 00183 list_delete_const((const list **)l, delete); 00184 return; 00185 } 00186 00187 /* 00188 * @brief Get list size 00189 * @param l list 00190 * @return number of elements in list 00191 * 00192 * Time: O(1) 00193 */ 00194 int 00195 list_size(const list *l) 00196 { 00197 assure( l != NULL ); 00198 00199 return l->size; 00200 } 00201 00202 /* 00203 * @brief Insert element 00204 * @param l list 00205 * @param e element to insert. Must be non-NULL 00206 * @return number of elements in list 00207 * 00208 * Time: Amortized O(1) 00209 */ 00210 void 00211 list_insert(list *l, void *e) 00212 { 00213 assure( e != NULL ); 00214 00215 if (l->back == 0) { 00216 l->back = l->size + 1; 00217 l->elements = list_realloc(l->elements, (l->size + l->back) * sizeof(*l->elements)); 00218 } 00219 00220 l->size++; 00221 l->back--; 00222 l->elements[l->size - 1] = e; 00223 00224 return; 00225 } 00226 00227 /* 00228 * @brief Remove element 00229 * @param l list 00230 * @param e element to remove. Note: pointer comparison 00231 * @return e 00232 * 00233 * The provided element must exist in the list. 00234 * Only one occurrence of e is removed. 00235 * The element is removed from the list, but not deallocated. 00236 * 00237 * For convenience, the function returns the provided element pointer. 00238 * This is to allow code like 00239 * @code 00240 * element *e = element_list_remove(l, element_list_first(l)); 00241 * @endcode 00242 * 00243 * Time: Worst case O(n), O(1) for removing the element returned by list_first() 00244 */ 00245 const void * 00246 list_remove_const(list *l, const void *e) 00247 { 00248 assure( l != NULL ); 00249 assure( e != NULL ); 00250 00251 { 00252 int i; 00253 int indx = -1; 00254 for (i = l->size - 1; i >= 0 && indx < 0; i--) { 00255 if (l->elements[i] == e) { 00256 indx = i; 00257 } 00258 } 00259 00260 assure( indx >= 0 ); 00261 00262 for (i = indx; i < l->size-1; i++) { 00263 l->elements[i] = l->elements[i+1]; 00264 } 00265 } 00266 00267 l->size--; 00268 l->back++; 00269 00270 if (l->back > 4 * l->size) { 00271 /* Note: amortized constant time */ 00272 l->back = l->size; 00273 l->elements = list_realloc(l->elements, 00274 (l->size + l->back) * sizeof(*l->elements)); 00275 } 00276 00277 return e; 00278 } 00279 00280 void * 00281 list_remove(list *l, void *e) 00282 { 00283 return (void *)list_remove_const(l, e); 00284 } 00285 00286 /* 00287 * @brief Reverse the order of list elements 00288 * @param l list 00289 * @return Nothing 00290 * 00291 * Time: O(N) 00292 */ 00293 void 00294 list_reverse(list *l) 00295 { 00296 int i, k; 00297 00298 assure( l != NULL ); 00299 00300 for (i = 0, k = l->size-1; i < k; i++, k--) 00301 { 00302 void *tmp; 00303 tmp = l->elements[i]; 00304 l->elements[i] = l->elements[k]; 00305 l->elements[k] = tmp; 00306 } 00307 00308 return; 00309 } 00310 00311 /* 00312 * @brief Iterate 00313 * @param l list 00314 * @return first element, or NULL if list empty 00315 * 00316 * @code 00317 * for(element *e = list_first(l); 00318 * e != NULL; 00319 * e = list_next(l)) {...} 00320 * @endcode 00321 * 00322 * The list must not be modified between calls to list_first() or list_next() 00323 * 00324 * Note: It is not possible to have more simultaneous iterations over the same 00325 * list. This functionality can be achived by duplicating the list. 00326 * 00327 * Time: O(1) 00328 */ 00329 const void * 00330 list_first_const(const list *l) 00331 { 00332 assure( l != NULL ); 00333 00334 if (l->size == 0) return NULL; 00335 00336 /* Loop backwards, faster if user 00337 erases the first element */ 00338 00339 ((list *)l)->current = l->size - 1; 00340 return l->elements[l->current]; 00341 } 00342 00343 void * 00344 list_first(list *l) 00345 { 00346 return (void *)list_first_const(l); 00347 } 00348 00349 /* 00350 * @brief Iterate 00351 * @param l list 00352 * @return next element, or NULL if no more elements 00353 * 00354 * See list_first(). 00355 * 00356 * Time: O(1) 00357 */ 00358 const void * 00359 list_next_const(const list *l) 00360 { 00361 assure( l != NULL ); 00362 00363 if (l->size == 0) return NULL; 00364 00365 ((list *)l)->current -= 1; 00366 00367 if (l->current < 0) return NULL; 00368 else return l->elements[l->current]; 00369 } 00370 00371 void * 00372 list_next(list *l) 00373 { 00374 return (void *)list_next_const(l); 00375 } 00376 00377 /* 00378 * @brief Iterate through pairs 00379 * @param l list 00380 * @param e1 (output) first pair 1st element, or NULL if list 00381 has less than two elements 00382 * @param e2 (output) first pair 2nd element 00383 * 00384 * The iteration is through the K(n,2) different pairs, i.e. the 00385 * pair (e1,e2) is considered equal to the pair (e2,e1) and only 00386 * visited once. 00387 * 00388 * @code 00389 * for(list_first_pair(l, &e1, &e2); 00390 * e1 != NULL; 00391 * list_next_pair(l, &e1, &e2)) 00392 * @endcode 00393 * 00394 * The list must not be modified between calls to 00395 * list_first_pair() or list_next_pair() 00396 * 00397 * The current position is cached in the list object. Therefore simultaneous 00398 * pair iterations over the same list is not allowed. 00399 * 00400 * However, iterating pairs simultaneously with a 1 element iteration (using 00401 * list_first() and list_next()) is allowed. 00402 * 00403 * Time: O(1) 00404 */ 00405 void 00406 list_first_pair_const(const list *l, 00407 const void **e1, 00408 const void **e2) 00409 { 00410 assure( l != NULL ); 00411 assure( e1 != NULL ); 00412 assure( e2 != NULL ); 00413 00414 if (l->size <= 1) { 00415 *e1 = NULL; 00416 *e2 = NULL; 00417 return; 00418 } 00419 00420 ((list *)l)->current_p1 = l->size - 1; 00421 ((list *)l)->current_p2 = l->size - 2; 00422 00423 *e1 = l->elements[l->current_p1]; 00424 *e2 = l->elements[l->current_p2]; 00425 00426 return; 00427 } 00428 00429 void 00430 list_first_pair(list *l, 00431 void **e1, 00432 void **e2) 00433 { 00434 list_first_pair_const(l, 00435 (const void **)e1, 00436 (const void **)e2); 00437 00438 return; 00439 } 00440 00441 /* 00442 * @brief Iterate through pairs 00443 * @param l list 00444 * @param e1 (output) next pair 1st element, or NULL if no more pairs 00445 * @param e2 (output) next pair 2nd element, or NULL if no more pairs 00446 * 00447 * See list_first_pair(). 00448 * 00449 * Time: O(1) 00450 */ 00451 void 00452 list_next_pair_const(const list *l, 00453 const void **e1, 00454 const void **e2) 00455 { 00456 assure( l != NULL ); 00457 assure( e1 != NULL ); 00458 assure( e2 != NULL ); 00459 00460 if (l->size <= 1) { 00461 *e1 = NULL; 00462 *e2 = NULL; 00463 return; 00464 } 00465 00466 ((list *)l)->current_p2 -= 1; 00467 00468 if (l->current_p2 < 0) { 00469 ((list *)l)->current_p1 -= 1; 00470 ((list *)l)->current_p2 = l->current_p1 - 1; 00471 if (l->current_p2 < 0) { 00472 *e1 = NULL; 00473 *e2 = NULL; 00474 return; 00475 } 00476 *e1 = l->elements[l->current_p1]; 00477 *e2 = l->elements[l->current_p2]; 00478 return; 00479 } 00480 00481 *e2 = l->elements[l->current_p2]; 00482 return; 00483 } 00484 00485 void 00486 list_next_pair(list *l, 00487 void **e1, 00488 void **e2) 00489 { 00490 list_next_pair_const(l, (const void **)e1, (const void **)e2); 00491 return; 00492 } 00493 00506 list * 00507 list_extract(const list *l, 00508 void *(*duplicate)(const void *), 00509 bool (*predicate)(const void *, void *), 00510 void *data) 00511 { 00512 assure( l != NULL ); 00513 assure( duplicate != NULL); 00514 assure( predicate != NULL); 00515 00516 { 00517 list *ex = list_new(); 00518 int i; 00519 00520 for (i = 0; i < l->size; i++) { 00521 if (predicate(l->elements[i], data)) { 00522 list_insert(ex, duplicate(l->elements[i])); 00523 } 00524 } 00525 00526 return ex; 00527 } 00528 } 00529 00530 /* 00531 * @brief Find minimum element 00532 * @param l non-empty list 00533 * @param less_than comparison function which must return true, iff 00534 * its first argument is considered less than the second argument. 00535 * The 3rd argument is auxillary data used for the comparison. 00536 * The provided function should be a strict ordering (i.e. behave 00537 * like <) 00538 * @param data Auxillary data sent to the comparison function. May be NULL. 00539 * @return minimum element 00540 * 00541 * Time: O(n) 00542 */ 00543 void * 00544 list_min(list *l, list_func_lt less_than, void *data) 00545 { 00546 assure( l != NULL ); 00547 assure( less_than != NULL); 00548 assure( list_size(l) > 0); 00549 00550 { 00551 int minindex = 0; 00552 int i; 00553 for (i = 1; i < l->size; i++) { 00554 if (less_than(l->elements[i], l->elements[minindex], data)) 00555 minindex = i; 00556 } 00557 00558 return l->elements[minindex]; 00559 } 00560 } 00561 00562 /* 00563 * @brief Find minimum element 00564 * @param l non-empty list 00565 * @param eval evaluation function 00566 * @param data Auxillary data sent to the evaluation function. May be NULL. 00567 * @return minimum (as defined by the evaluation function) element 00568 * 00569 * Time: O(n) 00570 */ 00571 void * 00572 list_min_val(list *l, list_func_eval eval, void *data) 00573 { 00574 assure( l != NULL ); 00575 assure( eval != NULL); 00576 assure( list_size(l) > 0); 00577 00578 { 00579 int minindex = 0; 00580 double minval = eval(l->elements[0], data); 00581 int i; 00582 00583 for (i = 1; i < l->size; i++) { 00584 double val = eval(l->elements[i], data); 00585 if (val < minval) { 00586 minval = val; 00587 minindex = i; 00588 } 00589 } 00590 00591 return l->elements[minindex]; 00592 } 00593 } 00594 00595 /* 00596 * @brief Find maximum element 00597 * @param l non-empty list 00598 * @param eval evaluation function 00599 * @param data Auxillary data sent to the evaluation function. May be NULL. 00600 * @return maximum (as defined by the evaluation function) element 00601 * 00602 * Time: O(n) 00603 */ 00604 void * 00605 list_max_val(list *l, list_func_eval eval, void *data) 00606 { 00607 assure( l != NULL ); 00608 assure( eval != NULL); 00609 assure( list_size(l) > 0); 00610 00611 { 00612 int maxindex = 0; 00613 double maxval = eval(l->elements[0], data); 00614 int i; 00615 00616 for (i = 1; i < l->size; i++) { 00617 double val = eval(l->elements[i], data); 00618 if (val > maxval) { 00619 maxval = val; 00620 maxindex = i; 00621 } 00622 } 00623 00624 return l->elements[maxindex]; 00625 } 00626 } 00627 00628 /* 00629 * @brief Find maximum element 00630 * @param l see list_min() 00631 * @param less_than see list_min() 00632 * @param data see list_min() 00633 * @return maximum element 00634 * 00635 * Time: O(n) 00636 */ 00637 const void * 00638 list_max_const(const list *l, list_func_lt less_than, void *data) 00639 { 00640 assure( l != NULL ); 00641 assure( less_than != NULL); 00642 assure( list_size(l) > 0); 00643 00644 { 00645 int maxindex = 0; 00646 int i; 00647 for (i = 1; i < l->size; i++) { 00648 if (!less_than(l->elements[i], l->elements[maxindex], data)) 00649 maxindex = i; 00650 } 00651 00652 return l->elements[maxindex]; 00653 } 00654 } 00655 00656 void * 00657 list_max(list *l, list_func_lt less_than, void *data) 00658 { 00659 return (void *)list_max_const(l, less_than, data); 00660 } 00661 00662 00663 /* 00664 * @brief Find k'th element 00665 * @param l non-empty list 00666 * @param k between 1 and list size, inclusive. 00667 * @param n list size 00668 * @param less_than see list_min() 00669 * @param data see list_min() 00670 * @return k'th element 00671 * 00672 * Be careful to provide an irreflexive comparison function (i.e. 00673 * x < x must always be false), or this function may not return. 00674 * 00675 * Time: Worst case O(n*n). Average over all input: O(n) 00676 */ 00677 static const void * 00678 kth(const void *a[], int k, int n, list_func_lt less_than, void *data) 00679 { 00680 int i, j, lo, hi; 00681 00682 k -= 1; 00683 00684 lo = 0; 00685 hi = n - 1; 00686 while (lo < hi) { 00687 const void *pivot = a[k];//fixme select randomly, swap with a[k] 00688 i = lo; 00689 j = hi; 00690 do { 00691 while (less_than(a[i], pivot, data)) i++; 00692 while (less_than(pivot, a[j], data)) { 00693 j--; 00694 } 00695 if (i <= j) { 00696 const void *tmp = a[i]; 00697 a[i] = a[j]; 00698 a[j] = tmp; 00699 i++; j--; 00700 } 00701 } while (i <= j); 00702 if (j < k) lo = i; 00703 if (k < i) hi = j; 00704 } 00705 return a[k]; 00706 } 00707 00708 const void * 00709 list_kth_const(const list *l, int k, 00710 list_func_lt less_than, void *data) 00711 { 00712 void *kp; 00713 void **elemcpy; 00714 int len; 00715 00716 assure( l != NULL ); 00717 assure( 1 <= k && k <= l->size ); 00718 00719 /* the function kth() scrambles the elements, so copy them */ 00720 len = l->size * sizeof(*l->elements); 00721 elemcpy = list_malloc(len); 00722 memcpy(elemcpy, l->elements, len); 00723 00724 kp = (void*)kth((const void **)elemcpy, k, l->size, less_than, data); 00725 00726 list_free(elemcpy); 00727 00728 return kp; 00729 } 00730 00731 void * 00732 list_kth(list *l, int k, 00733 list_func_lt less_than, 00734 void *data) 00735 { 00736 return (void *)list_kth_const(l, k, less_than, data); 00737 } 00738 00739 /* 00740 * @brief Determine order of elements given an evaluation function 00741 * @param e1 first element 00742 * @param e2 second element 00743 * @param data containing the evaluation function, and 00744 * additional data which is passed to the evaluation function 00745 * @return true iff e1 evaluates to a number less than e2 00746 */ 00747 static 00748 bool val_less_than(const void *e1, const void *e2, void *data) 00749 { 00750 struct { 00751 list_func_eval f; 00752 void *aux_data; 00753 } *d = data; 00754 /* Cast is safe, see caller of this function */ 00755 00756 00757 /* Unfortunately, as the following commented code demonstrated, 00758 with GCC-4.2.0 calling the evaluation function two times with the same 00759 input can give two numbers which satisfy both equality (==) *and* 00760 less than (<) (!) but not greater than (>). This causes the kth function 00761 to loop infinitely. 00762 00763 Avoid that by handling explicitly this special case. 00764 */ 00765 00766 if (e1 == e2) return false; 00767 00768 /* 00769 double d1 = d->f(e1, d->aux_data); 00770 fprintf(stderr, "%s got %f %g \n", __func__, d1, d1); 00771 fprintf(stderr, "%.100f\n", d1); 00772 00773 double d2 = d->f(e2, d->aux_data); 00774 fprintf(stderr, "%s %d %d %d\n", __func__, i1, i2, i3); 00775 00776 fprintf(stderr, "%s got %f %g %d %d\n", __func__, d2, d2, d1 < d2, e1 == e2); 00777 fprintf(stderr, "%.100f %d %d %d %d %d\n", d2, 00778 d1 < d2, d2 > d1, d1 == d2, d1 > d2, d2 < d1); 00779 00780 fprintf(stderr, "l1 = %ld\n", d1); 00781 fprintf(stderr, "l2 = %ld\n", d2); 00782 */ 00783 00784 return (d->f(e1, d->aux_data) < d->f(e2, d->aux_data)); 00785 } 00786 00787 /* 00788 * @brief k'th element 00789 * @param l list 00790 * @param k counting from 1 00791 * @param eval returns the value of an element 00792 * @param data sent to eval 00793 * @return a k'th element according to the evaluation function 00794 */ 00795 const void * 00796 list_kth_val_const(const list *l, int k, list_func_eval eval, void *data) 00797 { 00798 assure( l != NULL ); 00799 assure( 1 <= k && k <= l->size ); 00800 assure( eval != NULL ); 00801 00802 struct { 00803 list_func_eval f; 00804 void *aux_data; 00805 } d; 00806 d.f = eval; 00807 d.aux_data = data; 00808 00809 return list_kth_const(l, k, val_less_than, &d); 00810 } 00811 void * 00812 list_kth_val(list *l, int k, list_func_eval eval, void *data) 00813 { 00814 return (void *) list_kth_val_const(l, k, eval, data); 00815 } 00816 00817 /* 00818 * @brief Compute median 00819 * @param l list 00820 * @param eval returns the value of an element 00821 * @param data additional data passed to eval 00822 * @return median 00823 * 00824 * Time: Average O(n). 00825 * 00826 * For an even number of elements, the median is the 00827 * average of the two central values. 00828 */ 00829 double 00830 list_median(const list *l, list_func_eval eval, void *data) 00831 { 00832 assure( l != NULL ); 00833 assure( eval != NULL ); 00834 assure( l->size > 0 ); 00835 00836 const void *median_element = list_kth_val_const(l, (l->size+1)/2, eval, data); 00837 00838 double median_val = eval(median_element, data); 00839 00840 if (list_size(l) && 2 == 0) 00841 { 00842 const void *other_median_element = 00843 list_kth_val_const(l, (l->size+2)/2, eval, data); 00844 00845 median_val = (median_val + eval(other_median_element, data) ) / 2.0; 00846 } 00847 00848 return median_val; 00849 } 00850 00851 /* 00852 * @brief Compute mean 00853 * @param l list 00854 * @param eval returns the value of an element 00855 * @param data additional data passed to eval 00856 * @return arithmetic average 00857 * 00858 * Time: O(n). 00859 */ 00860 double 00861 list_mean(const list *l, list_func_eval eval, void *data) 00862 { 00863 assure( l != NULL ); 00864 assure( eval != NULL ); 00865 assure( l->size > 0 ); 00866 00867 double result = eval(l->elements[0], data); 00868 int i; 00869 00870 for (i = 1; i < l->size; i++) { 00871 result += eval(l->elements[i], data); 00872 } 00873 00874 result /= l->size; 00875 00876 return result; 00877 } 00878 00879 /* 00880 * @brief Compute optimally weighted mean 00881 * @param l list with two or more elements 00882 * @param eval returns the value of an element 00883 * @param data additional data passed to eval 00884 * @param eval_err returns the error (1 sigma) of an element, 00885 * must be positive 00886 * @param data_err additional data passed to eval_err 00887 * @param err (output) square root variance 00888 * @param red_chisq (output) reduced chi square, may be NULL 00889 * @return optimal mean 00890 * 00891 * average = [ sum x_i / sigma_i^2 ] / [sum 1 / sigma_i^2] 00892 * variance = 1 / [sum 1 / sigma_i^2] 00893 * 00894 * chi^2/(n-1) = sum ((x_i - average) / sigma_i)^2 / (n-1) 00895 * 00896 * Time: O(n). 00897 */ 00898 double 00899 list_mean_optimal(const list *l, 00900 list_func_eval eval, void *data_eval, 00901 list_func_eval eval_err, void *data_err, 00902 double *err, 00903 double *red_chisq) 00904 { 00905 assure( l != NULL ); 00906 assure( l->size >= 1 ); 00907 assure( red_chisq == NULL || l->size >= 2 ); 00908 assure( eval != NULL ); 00909 assure( eval_err != NULL ); 00910 assure( err != NULL ); 00911 00912 double sum_weights = 0; 00913 double opt_average = 0; 00914 int i; 00915 00916 for (i = 0; i < l->size; i++) { 00917 void *e = l->elements[i]; 00918 double sigma = eval_err(e, data_err); 00919 00920 assure( sigma > 0 ); 00921 00922 double weight = 1/(sigma*sigma); 00923 00924 opt_average += eval(e, data_eval) * weight; 00925 sum_weights += weight; 00926 } 00927 opt_average /= sum_weights; 00928 *err = 1 / sqrt(sum_weights); 00929 00930 if (red_chisq != NULL) { 00931 *red_chisq = 0; 00932 for (i = 0; i < l->size; i++) { 00933 void *e = l->elements[i]; 00934 double residual = ((eval(e, data_eval) - opt_average)) / eval_err(e, data_err); 00935 *red_chisq += residual * residual; 00936 } 00937 *red_chisq /= (l->size - 1); 00938 } 00939 00940 return opt_average; 00941 } 00942 00943 00944 00945 /* 00946 * @brief Compute absolute deviation 00947 * @param e1 element 00948 * @param data reference value, and evaluation function 00949 * and additional data passed to the evaluation function 00950 * @return absolute difference between e1 and reference point 00951 */ 00952 static double 00953 abs_dev(const void *e1, void *data) 00954 { 00955 struct { 00956 double ref; 00957 list_func_eval f; 00958 void *aux_data; 00959 } *d = data; 00960 /* Cast is safe, see caller */ 00961 00962 return fabs(d->f(e1, d->aux_data) - d->ref); 00963 } 00964 00965 /* 00966 * @brief Compute median absolute deviation wrt median 00967 * @param l list 00968 * @param eval returns the value of an element 00969 * @param data additional data passed to eval 00970 * @return mad 00971 * 00972 * Time: Average O(n). 00973 */ 00974 double 00975 list_mad(list *l, list_func_eval eval, void *data) 00976 { 00977 assure( l != NULL ); 00978 assure( eval != NULL ); 00979 00980 double median = list_median(l, eval, data); 00981 00982 struct { 00983 double ref; 00984 list_func_eval f; 00985 void *aux_data; 00986 } d; 00987 00988 d.ref = median; 00989 d.f = eval; 00990 d.aux_data = data; 00991 00992 return list_median(l, abs_dev, &d); 00993 } 00994