list.c

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_8_6 $
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 

Generated on Fri Mar 4 09:46:01 2011 for FORS Pipeline Reference Manual by  doxygen 1.4.7