/* $Id: list.h,v 1.10 2013-05-16 08:40:07 cgarcia Exp $
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */

/*
 * $Author: cgarcia $
 * $Date: 2013-05-16 08:40:07 $
 * $Revision: 1.10 $
 * $Name: not supported by cvs2svn $
 */

#ifndef LIST_ELEM
#error Define LIST_ELEM before including
#endif

#include <cpl.h>
#include <list_void.h>
#include <stdio.h>

#define LIST_CON(a,b) a ## _ ## b
#define LIST_CAT(a,b) LIST_CON(a,b)

#define LIST LIST_CAT(LIST_ELEM, list)

#ifndef LIST_DEFINE

typedef struct LIST LIST;

typedef double (*LIST_CAT(LIST, func_eval))(const LIST_ELEM *,
					    void *);

typedef bool (*LIST_CAT(LIST, func_lt))(const LIST_ELEM *,
					const LIST_ELEM *,
					void *);

typedef bool (*LIST_CAT(LIST, func_predicate))(const LIST_ELEM *,
					       void *);

#endif

CPL_BEGIN_DECLS

LIST *
LIST_CAT(LIST, new)(void) 
#ifdef LIST_DEFINE 
{
  return (LIST *) list_new();
}
#else
;
#endif


LIST *
LIST_CAT(LIST, duplicate)(const LIST *l,
			  LIST_ELEM * (*duplicate)(const LIST_ELEM *))
#ifdef LIST_DEFINE 
{
    return (LIST *) 
        list_duplicate((const list *)l,
                       (void *(*)(const void *)) duplicate);
}
#else
;
#endif

void
LIST_CAT(LIST, delete)(LIST **l,
                                 void (*ldelete)(LIST_ELEM **))
#ifdef LIST_DEFINE 
{
  list_delete((list **)l, (void (*)(void **))ldelete);
}
#else
;
#endif

void
LIST_CAT(LIST, delete_const)(const LIST **l,
			     void (*ldelete)(LIST_ELEM **))
#ifdef LIST_DEFINE 
{
    list_delete_const((const list **)l, (void (*)(void **))ldelete);
}
#else
;
#endif

void
LIST_CAT(LIST, insert)(LIST *l, LIST_ELEM *e)
#ifdef LIST_DEFINE 
{
  list_insert((list *)l, e);
}
#else
;
#endif

void
LIST_CAT(LIST, reverse)(LIST *l)
#ifdef LIST_DEFINE 
{
  list_reverse((list *)l);
}
#else
;
#endif

int
LIST_CAT(LIST, size)(const LIST *l)
#ifdef LIST_DEFINE 
{
    return list_size((const list *)l);
}
#else
;
#endif


LIST_ELEM *
LIST_CAT(LIST, first)(LIST *l)
#ifdef LIST_DEFINE 
{
  return (LIST_ELEM*)list_first((list *)l);
}
#else
;
#endif


LIST_ELEM *
LIST_CAT(LIST, next)(LIST *l)
#ifdef LIST_DEFINE 
{
  return (LIST_ELEM*)list_next((list *)l);
}
#else
;
#endif


const LIST_ELEM *
LIST_CAT(LIST, first_const)(const LIST *l)
#ifdef LIST_DEFINE 
{
  return (const LIST_ELEM*)list_first_const((list *)l);
}
#else
;
#endif


const LIST_ELEM *
LIST_CAT(LIST, next_const)(const LIST *l)
#ifdef LIST_DEFINE 
{
    return (const LIST_ELEM*)list_next_const((const list *)l);
}
#else
;
#endif

void
LIST_CAT(LIST, first_pair)(LIST *l, 
				     LIST_ELEM **e1,
				     LIST_ELEM **e2)
#ifdef LIST_DEFINE 
{
    list_first_pair((list *)l, (void **)e1, (void **)e2);
    return;
}
#else
;
#endif

void
LIST_CAT(LIST, next_pair)(LIST *l, 
				    LIST_ELEM **e1,
				    LIST_ELEM **e2)
#ifdef LIST_DEFINE 
{
    list_next_pair((list *)l, (void **)e1, (void **)e2);
    return;
}
#else
;
#endif

void
LIST_CAT(LIST, first_pair_const)(const LIST *l, 
					   const LIST_ELEM **e1,
					   const LIST_ELEM **e2)
#ifdef LIST_DEFINE 
{
    list_first_pair((list *)l, (void **)e1, (void **)e2);
    return;
}
#else
;
#endif
void
LIST_CAT(LIST, next_pair_const)(const LIST *l, 
					  const LIST_ELEM **e1,
					  const LIST_ELEM **e2)
#ifdef LIST_DEFINE 
{
    list_next_pair((list *)l, (void **)e1, (void **)e2);
    return;
}
#else
;
#endif

const LIST_ELEM *
LIST_CAT(LIST, remove_const)(LIST *l, const LIST_ELEM *e)
#ifdef LIST_DEFINE 
{
    return (const LIST_ELEM*)list_remove_const((list *)l, e);
}
#else
;
#endif

LIST_ELEM *
LIST_CAT(LIST, remove)(LIST *l, LIST_ELEM *e)
#ifdef LIST_DEFINE 
{
    return (LIST_ELEM*)list_remove((list *)l, e);
}
#else
;
#endif


LIST *
LIST_CAT(LIST, extract)(const LIST *l,
			LIST_ELEM * (*duplicate)(const LIST_ELEM *),
			LIST_CAT(LIST, func_predicate) predicate,
			void *data)
#ifdef LIST_DEFINE 
{
    return (LIST *)list_extract((const list *)l,
				(void *(*)(const void *))duplicate,
				(list_func_predicate) predicate,
				data);
}
#else
;
#endif


const LIST_ELEM *
LIST_CAT(LIST, max_const)(const LIST *l,
			  LIST_CAT(LIST, func_lt) less_than,
			  void *data)
#ifdef LIST_DEFINE
{
    return (const LIST_ELEM*)list_max_const((list *)l, 
                          (list_func_lt) less_than,
                          data);
}
#else
;
#endif

LIST_ELEM *
LIST_CAT(LIST, max)(LIST *l,
		    LIST_CAT(LIST, func_lt) less_than,
		    void *data)
#ifdef LIST_DEFINE
{
    return (LIST_ELEM*)list_max((list *)l, 
                    (list_func_lt) less_than,
                    data);
}
#else
;
#endif

LIST_ELEM *
LIST_CAT(LIST, min)(LIST *l,
		    LIST_CAT(LIST, func_lt) less_than,
		    void *data)
#ifdef LIST_DEFINE
{
    return (LIST_ELEM*)list_min((list *)l,
                    (list_func_lt) less_than,
                    data);
}
#else
;
#endif


LIST_ELEM *
LIST_CAT(LIST, min_val)(LIST *l,
			LIST_CAT(LIST, func_eval) eval,
			void *data)
#ifdef LIST_DEFINE
{
    return (LIST_ELEM*)list_min_val((list *)l,
			(list_func_eval) eval,
			data);
}
#else
;
#endif


LIST_ELEM *
LIST_CAT(LIST, max_val)(LIST *l,
			LIST_CAT(LIST, func_eval) eval,
			void *data)
#ifdef LIST_DEFINE
{
    return (LIST_ELEM*)list_max_val((list *)l,
			(list_func_eval) eval,
			data);
}
#else
;
#endif


const LIST_ELEM *
LIST_CAT(LIST, kth_const)(const LIST *l, int k,
			  LIST_CAT(LIST, func_lt) less_than,
			  void *data)
#ifdef LIST_DEFINE
{
  return (const LIST_ELEM*)list_kth_const((list *)l, k,
			(list_func_lt) less_than,
                        data);
}
#else
;
#endif

LIST_ELEM *
LIST_CAT(LIST, kth)(LIST *l, int k,
		    LIST_CAT(LIST, func_lt) less_than,
		    void *data)
#ifdef LIST_DEFINE
{
    return (LIST_ELEM*)list_kth((list *)l, k,
		    (list_func_lt) less_than,
                    data);
}
#else
;
#endif


LIST_ELEM *
LIST_CAT(LIST, kth_val)(LIST *l, int k,
			LIST_CAT(LIST, func_eval) eval, 
			void *data)
#ifdef LIST_DEFINE
{
    return (LIST_ELEM*)list_kth_val((list *)l, k,
			(list_func_eval) eval,
			data);
}
#else
;
#endif



const LIST_ELEM *
LIST_CAT(LIST, kth_val_const)(const LIST *l, int k,
			      LIST_CAT(LIST, func_eval) eval, 
			      void *data)
#ifdef LIST_DEFINE
{
    return (const LIST_ELEM*)list_kth_val_const((const list *)l, k,
			      (list_func_eval) eval,
			      data);
}
#else
;
#endif




double
LIST_CAT(LIST, mean)(LIST *l,
		     LIST_CAT(LIST, func_eval) eval,
		     void *data)
#ifdef LIST_DEFINE
{
    return list_mean((list *)l,
		     (list_func_eval) eval,
		     data);
}
#else
;
#endif

double
LIST_CAT(LIST, mean_optimal)(LIST *l,
			     LIST_CAT(LIST, func_eval) eval, void *data_eval,
			     LIST_CAT(LIST, func_eval) eval_err, void *data_err,
			     double *err,
			     double *red_chisq)
#ifdef LIST_DEFINE
{
    return list_mean_optimal((list *)l,
			     (list_func_eval) eval, data_eval,
			     (list_func_eval) eval_err, data_err,
			     err,
			     red_chisq);
}
#else
;
#endif


double
LIST_CAT(LIST, median)(const LIST *l,
		       LIST_CAT(LIST, func_eval) eval,
		       void *data)
#ifdef LIST_DEFINE
{
    return list_median((const list *)l,
		       (list_func_eval) eval,
		       data);
}
#else
;
#endif


double
LIST_CAT(LIST, mad)(LIST *l,
		    LIST_CAT(LIST, func_eval) eval,
		    void *data)
#ifdef LIST_DEFINE
{
    return list_mad((list *)l,
		    (list_func_eval) eval,
		    data);
}
#else
;
#endif

CPL_END_DECLS

