/* src/ctl.h.  Generated from ctl.h.in by configure.  */
/* libctl: flexible Guile-based control files for scientific software 
 * Copyright (C) 1998-2014 Massachusetts Institute of Technology and Steven G. Johnson
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 *
 * Steven G. Johnson can be contacted at stevenj@alum.mit.edu.
 */

#ifndef CTL_H
#define CTL_H

#define HAVE_NO_GH 1
#ifdef HAVE_NO_GH
#  include <libguile.h>
#else
#  include <guile/gh.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif                          /* __cplusplus */

/**************************************************************************/
/* Configuration options (guessed by configure).
   We have to put them here, rather than in a private config.h file,
   because they need to be known by user ctl-io.c and main.c files. */

/* set to version string */
#define LIBCTL_VERSION "3.2.2"
#define LIBCTL_MAJOR_VERSION 3
#define LIBCTL_MINOR_VERSION 2
#define LIBCTL_BUGFIX_VERSION 2

/* Define if you have the following functions */
/* #undef HAVE_GH_ENTER */
/* #undef HAVE_GH_EVAL_STR */
/* #undef HAVE_GH_LOAD */
/* #undef HAVE_GH_BOOL2SCM */
/* #undef HAVE_GH_VECTOR_REF */
/* #undef HAVE_GH_LIST_REF */
/* #undef HAVE_GH_LENGTH */
#define HAVE_SCM_FLUSH_ALL_PORTS 1
#define HAVE_SCM_MAKE_COMPLEX 1
#define HAVE_SCM_C_MAKE_RECTANGULAR 1
#define HAVE_SCM_VARIABLE_SET_X 1
#define HAVE_SCM_C_LOOKUP 1
#define HAVE_SCM_C_MAKE_VECTOR 1
#define HAVE_SCM_VARIABLE_REF 1

/* Define if you have the HAVE_SCM_COMPLEXP macro. */
#define HAVE_SCM_COMPLEXP 1

/* Define if gh_lookup is not broken */
/* #undef GH_LOOKUP_OK */

/* Define if we have C99 complex numbers and hence complex integration */
#define CTL_HAS_COMPLEX_INTEGRATION 1

/**************************************************************************/

  /* Basic types: */

typedef int integer;
typedef double number;
typedef struct { number re, im; } cnumber; /* complex numbers! */
typedef short boolean;
typedef char *string;
typedef SCM list;
typedef SCM function;
typedef SCM object;

  /* define vector3 as a structure, not an array, so that it can
     be a function return value and so that simple assignment works. */
typedef struct { number x,y,z; } vector3;

  /* similarly for matrix3x3 */
typedef struct { vector3 c0, c1, c2; /* the columns */ } matrix3x3;

/* define complex equivalents: */
typedef struct { cnumber x,y,z; } cvector3;
typedef struct { cvector3 c0, c1, c2; /* the columns */ } cmatrix3x3;

/**************************************************************************/

#ifdef HAVE_NO_GH /* use replacements for gh functions */
#  define gh_call0 scm_call_0
#  define gh_call1 scm_call_1
#  define gh_call2 scm_call_2
#  define gh_call3 scm_call_3
#  define gh_apply scm_apply_0
#  define gh_eval_str scm_c_eval_string
#  define gh_symbol2scm scm_from_locale_symbol
#  define ctl_symbol2newstr(x) scm_to_locale_string(scm_symbol_to_string(x))
#  define gh_cons scm_cons
#  define gh_car scm_car
#  define gh_cdr scm_cdr
#  if SCM_MAJOR_VERSION >= 2 /* get types right for C++, since fc
			        argument is void* (grrr) in Guile 2.x */
#    define gh_new_procedure(name, fcn, req, opt, rst) scm_c_define_gsubr(name, req, opt, rst, (scm_t_subr) (fcn))
#  else
#    define gh_new_procedure(name, fcn, req, opt, rst) scm_c_define_gsubr(name, req, opt, rst, fcn)
#  endif
#  define gh_repl scm_shell
#else
#  define ctl_symbol2newstr(x) gh_symbol2newstr(x, 0)
#endif

#if !defined(GH_LOOKUP_OK) || defined(HAVE_NO_GH)
#  if defined(HAVE_SCM_VARIABLE_REF) && defined(HAVE_SCM_C_LOOKUP)
#    define gh_lookup(name) scm_variable_ref(scm_c_lookup(name))
#  else
#    define gh_lookup scm_symbol_value0
#  endif
#endif

#if !defined(HAVE_GH_LOAD) || defined(HAVE_NO_GH)
#  ifdef HAVE_NO_GH
#    define gh_load scm_c_primitive_load
#  else
#    define gh_load gh_eval_file 
#  endif
#endif

extern void ctl_include(char *filename);
extern char *ctl_fix_path(const char *path);

/**************************************************************************/

#ifndef HAVE_SCM_C_MAKE_VECTOR
#  define scm_c_make_vector(n,fill) scm_make_vector(SCM_MAKINUM(n), fill)
#endif

  /* vector3 and matrix3x3 utilities: */

extern number vector3_dot(vector3 v1,vector3 v2);
extern number vector3_norm(vector3 v);
extern vector3 vector3_scale(number s, vector3 v);
extern vector3 unit_vector3(vector3 v);
extern vector3 vector3_cross(vector3 v1,vector3 v2);
extern vector3 vector3_plus(vector3 v1,vector3 v2);
extern vector3 vector3_minus(vector3 v1,vector3 v2);
extern int vector3_equal(vector3 v1, vector3 v2);

extern vector3 matrix3x3_vector3_mult(matrix3x3 m, vector3 v);
extern vector3 matrix3x3_transpose_vector3_mult(matrix3x3 m, vector3 v);
extern matrix3x3 matrix3x3_mult(matrix3x3 m1, matrix3x3 m2);
extern matrix3x3 matrix3x3_transpose(matrix3x3 m);
extern number matrix3x3_determinant(matrix3x3 m);
extern matrix3x3 matrix3x3_inverse(matrix3x3 m);
extern int matrix3x3_equal(matrix3x3 m1, matrix3x3 m2);

extern vector3 matrix3x3_row1(matrix3x3 m);
extern vector3 matrix3x3_row2(matrix3x3 m);
extern vector3 matrix3x3_row3(matrix3x3 m);

/**************************************************************************/

  /* complex number utilities */


extern cnumber make_cnumber(number r, number i);
extern cnumber cnumber_conj(cnumber c);
extern int cnumber_equal(cnumber c1, cnumber c2);
#define cnumber_re(c) ((c).re)
#define cnumber_im(c) ((c).im)

extern vector3 cvector3_re(cvector3 cv);
extern vector3 cvector3_im(cvector3 cv);
extern cvector3 make_cvector3(vector3 vr, vector3 vi);
extern int cvector3_equal(cvector3 v1, cvector3 v2);

extern matrix3x3 cmatrix3x3_re(cmatrix3x3 cm);
extern matrix3x3 cmatrix3x3_im(cmatrix3x3 cm);
extern cmatrix3x3 make_cmatrix3x3(matrix3x3 mr, matrix3x3 mi);
cmatrix3x3 make_hermitian_cmatrix3x3(number m00, number m11, number m22,
                                     cnumber m01, cnumber m02, cnumber m12);
extern int cmatrix3x3_equal(cmatrix3x3 m1, cmatrix3x3 m2);

/**************************************************************************/

  /* type conversion */

#if !defined(HAVE_GH_BOOL2SCM) && !defined(HAVE_NO_GH)
  /* Guile 1.2 is missing gh_bool2scm for some reason; redefine: */
   extern SCM ctl_gh_bool2scm(boolean);
#  define gh_bool2scm ctl_gh_bool2scm
#endif

extern vector3 scm2vector3(SCM sv);
extern SCM vector32scm(vector3 v);
extern matrix3x3 scm2matrix3x3(SCM sm);
extern SCM matrix3x32scm(matrix3x3 m);

extern cnumber scm2cnumber(SCM sx);
extern SCM cnumber2scm(cnumber x);
extern cvector3 scm2cvector3(SCM sv);
extern SCM cvector32scm(cvector3 v);
extern cmatrix3x3 scm2cmatrix3x3(SCM sm);
extern SCM cmatrix3x32scm(cmatrix3x3 m);

#ifdef HAVE_NO_GH
#  define ctl_convert_number_to_scm(x) scm_from_double(x)
#  define ctl_convert_number_to_c(x) scm_to_double(x)
#  define ctl_convert_integer_to_scm(x) scm_from_int(x)
#  define ctl_convert_integer_to_c(x) scm_to_int(x)
#  define ctl_convert_string_to_scm(x) scm_from_locale_string(x)
#  define ctl_convert_string_to_c(x) scm_to_locale_string(x)
#  define ctl_convert_boolean_to_scm(x) scm_from_bool(x)
#  define ctl_convert_boolean_to_c(x) scm_to_bool(x)
#else
#  define ctl_convert_number_to_scm(x) gh_double2scm(x)
#  define ctl_convert_number_to_c(x) gh_scm2double(x)
#  define ctl_convert_integer_to_scm(x) gh_int2scm(x)
#  define ctl_convert_integer_to_c(x) gh_scm2int(x)
#  define ctl_convert_string_to_scm(x) gh_str02scm(x)
#  define ctl_convert_string_to_c(x) gh_scm2newstr(x, 0)
#  define ctl_convert_boolean_to_scm(x) gh_bool2scm(x)
#  define ctl_convert_boolean_to_c(x) gh_scm2bool(x)
#endif

#define ctl_convert_cnumber_to_scm(x) cnumber2scm(x)
#define ctl_convert_vector3_to_scm(x) vector32scm(x)
#define ctl_convert_matrix3x3_to_scm(x) matrix3x32scm(x)
#define ctl_convert_cvector3_to_scm(x) cvector32scm(x)
#define ctl_convert_cmatrix3x3_to_scm(x) cmatrix3x32scm(x)
#define ctl_convert_SCM_to_scm(x) (x)
#define ctl_convert_function_to_scm(x) (x)
#define ctl_convert_object_to_scm(x) (x)
#define ctl_convert_list_to_scm(x) (x)

#define ctl_convert_cnumber_to_c(x) scm2cnumber(x)
#define ctl_convert_vector3_to_c(x) scm2vector3(x)
#define ctl_convert_matrix3x3_to_c(x) scm2matrix3x3(x)
#define ctl_convert_cvector3_to_c(x) scm2cvector3(x)
#define ctl_convert_cmatrix3x3_to_c(x) scm2cmatrix3x3(x)
#define ctl_convert_SCM_to_c(x) (x)
#define ctl_convert_function_to_c(x) (x)
#define ctl_convert_object_to_c(x) (x)
#define ctl_convert_list_to_c(x) (x)

/**************************************************************************/

  /* variable get/set functions */

extern integer ctl_get_integer(char *identifier);
extern number ctl_get_number(char *identifier);
extern cnumber ctl_get_cnumber(char *identifier);
extern boolean ctl_get_boolean(char *identifier);
extern char* ctl_get_string(char *identifier);
extern vector3 ctl_get_vector3(char *identifier);
extern matrix3x3 ctl_get_matrix3x3(char *identifier);
extern cvector3 ctl_get_cvector3(char *identifier);
extern cmatrix3x3 ctl_get_cmatrix3x3(char *identifier);
extern list ctl_get_list(char *identifier);
extern object ctl_get_object(char *identifier);
extern function ctl_get_function(char *identifier);
extern SCM ctl_get_SCM(char *identifier);

extern void ctl_set_integer(char *identifier, integer value);
extern void ctl_set_number(char *identifier, number value);
extern void ctl_set_cnumber(char *identifier, cnumber value);
extern void ctl_set_boolean(char *identifier, boolean value);
extern void ctl_set_string(char *identifier, char *value);
extern void ctl_set_vector3(char *identifier, vector3 value);
extern void ctl_set_matrix3x3(char *identifier, matrix3x3 value);
extern void ctl_set_cvector3(char *identifier, cvector3 value);
extern void ctl_set_cmatrix3x3(char *identifier, cmatrix3x3 value);
extern void ctl_set_list(char *identifier, list value);
extern void ctl_set_object(char *identifier, object value);
extern void ctl_set_function(char *identifier, function value);
extern void ctl_set_SCM(char *identifier, SCM value);

/**************************************************************************/

  /* list traversal */

extern int list_length(list l);
extern integer integer_list_ref(list l, int index);
extern number number_list_ref(list l, int index);
extern cnumber cnumber_list_ref(list l, int index);
extern boolean boolean_list_ref(list l, int index);
extern char* string_list_ref(list l, int index);
extern vector3 vector3_list_ref(list l, int index);
extern matrix3x3 matrix3x3_list_ref(list l, int index);
extern cvector3 cvector3_list_ref(list l, int index);
extern cmatrix3x3 cmatrix3x3_list_ref(list l, int index);
extern list list_list_ref(list l, int index);
extern object object_list_ref(list l, int index);
extern function function_list_ref(list l, int index);
extern SCM SCM_list_ref(list l, int index);

/**************************************************************************/

  /* list creation */

extern list make_integer_list(int num_items, const integer *items);
extern list make_number_list(int num_items, const number *items);
extern list make_cnumber_list(int num_items, const cnumber *items);
extern list make_boolean_list(int num_items, const boolean *items);
extern list make_string_list(int num_items, const char **items);
extern list make_vector3_list(int num_items, const vector3 *items);
extern list make_matrix3x3_list(int num_items, const matrix3x3 *items);
extern list make_cvector3_list(int num_items, const cvector3 *items);
extern list make_cmatrix3x3_list(int num_items, const cmatrix3x3 *items);
extern list make_list_list(int num_items, const list *items);
extern list make_object_list(int num_items, const object *items);
extern list make_function_list(int num_items, const function *items);
extern list make_SCM_list(int num_items, const function *items);

/**************************************************************************/

  /* object properties */

boolean object_is_member(char *type_name, object o);

extern integer integer_object_property(object o, char *property_name);
extern number number_object_property(object o, char *property_name);
extern cnumber cnumber_object_property(object o, char *property_name);
extern boolean boolean_object_property(object o, char *property_name);
extern char* string_object_property(object o, char *property_name);
extern vector3 vector3_object_property(object o, char *property_name);
extern matrix3x3 matrix3x3_object_property(object o, char *property_name);
extern cvector3 cvector3_object_property(object o, char *property_name);
extern cmatrix3x3 cmatrix3x3_object_property(object o, char *property_name);
extern list list_object_property(object o, char *property_name);
extern object object_object_property(object o, char *property_name);
extern function function_object_property(object o, char *property_name);
extern SCM SCM_object_property(object o, char *property_name);

/**************************************************************************/

/* main() hook functions.  These are prototypes of functions
   defined by the USER and called just before the program starts
   and just before it ends, respectively.  If you want to define
   them, you should also define HAVE_CTL_HOOKS when compiling main.c.
   
   Note that due to the behavior of the Guile interactive mode, 
   ctl_stop_hook will only get called in non-interactive mode.  Sigh. */

extern void ctl_start_hook(int *argc, char ***argv);
extern void ctl_stop_hook(void);

/**************************************************************************/

  /* subplex multi-dimensional minimization routines: */

typedef number (*multivar_func) (integer, number *, void *);

extern number subplex(multivar_func f, number *x, integer n, void *fdata,
		      number tol, integer maxnfe,	
		      number fmin, boolean use_fmin,
		      number *scale,	
		      integer *nfe, integer *errflag);
extern SCM subplex_scm(SCM f_scm, SCM x_scm,
		       SCM tol_scm, SCM maxnfe_scm,
		       SCM fmin_scm, SCM use_fmin_scm,
		       SCM scale_scm);

  /* multi-dimensional integration routines */

extern number adaptive_integration(multivar_func f, number *xmin, number *xmax,
				   integer n, void *fdata, 
				   number abstol, number reltol, 
				   integer maxnfe, 
				   number *esterr, integer *errflag);

extern SCM adaptive_integration_scm(SCM f_scm, SCM xmin_scm, SCM xmax_scm,
				    SCM abstol_scm, SCM reltol_scm, SCM maxnfe_scm);

#ifdef CTL_HAS_COMPLEX_INTEGRATION

typedef cnumber (*cmultivar_func) (integer, number *, void *);

extern cnumber cadaptive_integration(cmultivar_func f, number *xmin, number *xmax,
				     integer n, void *fdata, 
				     number abstol, number reltol,
				     integer maxnfe, 
				     number *esterr, integer *errflag);

extern SCM cadaptive_integration_scm(SCM f_scm, SCM xmin_scm, SCM xmax_scm,
				     SCM abstol_scm, SCM reltol_scm, SCM maxnfe_scm);

#endif /* CTL_HAS_COMPLEX_INTEGRATION */

/**************************************************************************/

#ifdef __cplusplus
	   }                               /* extern "C" */
#endif                          /* __cplusplus */

#endif /* CTL_H */
