caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* nonlinear fit function binding
@ 2007-05-25  7:54 matthieu.dubuget
  2007-05-31 11:42 ` [Caml-list] " Matthieu Dubuget
  0 siblings, 1 reply; 2+ messages in thread
From: matthieu.dubuget @ 2007-05-25  7:54 UTC (permalink / raw)
  To: Caml List

Hello,

I'm want to bind one non linear fitting function of MINPACK
(Fortran).

My first attempt seems to work, but...

1/ I used one GNU C extension (nested function definition):
I'd like
to know if any more portable solution exists, with a license
suitable
for a commercial product

2/ I'm still not sure about my use of the CAML* macros (see in
C part,
later)





/* Seen from C, the fitting FORTRAN function I first bound is: */
extern void lmdif1_(void fcn(int *m, int *n, double *x, double
*fvec, int *iflag),
	     int * m, int * n, double * x, double * fvec,
	     double * tol, int * info, int * iwa, double * wa, int *
lwa);

/* where fcn() is a user supplied C function pointer. */





(* From OCaml, I wanted to have something like this: *)
type float1darray =
    (float, Bigarray.float64_elt, Bigarray.c_layout)
Bigarray.Genarray.t

(* Here is the kind of function I want to fit.
   The first argument contains the parameters to adjust.
   The second one is the abscisse *)
type fitable = float1darray -> float -> float

(* Since I also want to be able to use directly C functions: *)
type fitfunc =
    OFitfunc of (string * fitable) (* OCaml function. The first
				   parameter is one string. It
                                   allows to name a registered

                                   callback, and pass it to C
*)

  | CFitfunc of nativeint         (* This is directly a C
pointer to a
			          function written in C. The type of C
			          function is ffittable (see in C
			          part). almost same thing as type
			          fitable *)

(* Here is the interface of the C function *)
external fit :
  fitfunc -> float1darray -> float1darray -> float1darray ->
float -> int
  = "minpack_fit"

(* The fitting function I intend to use:
   x contains absisses of experimental datas
   y contains experimental values
   p0 contains an initial guess of the parameters

   The function returns the info code given by MINPACK function.

   Side effect: p0 datas are modified and contain the adjusted
   parameters.
*)
val minimize : fcn:fitfunc -> x:float1darray -> y:float1darray ->
     p0:float1darray -> ?tol:float -> unit -> int

(* implementation: *)
let minimize ~fcn ~x ~y ~p0 ?(tol=1e-6) () =
  let () = match fcn with
      OFitfunc (nom, fc)  -> Callback.register nom fc;
    | CFitfunc _ -> ()
  in
    fit fcn x y p0 tol


/* And know, the C world: */

/* This is the kind of function pointer I can use. */
typedef double (*ffittable)(double, double *);

CAMLprim value minpack_fit(value func, value x, value y,
                           value params0, value tol){
  CAMLparam5(func, x, y, params0, tol);

  double * my_x, * my_y, *my_params, *fvec, *wa;
  double my_tol;
  int m, n, lwa, info, *iwa;
  ffittable f = NULL;
  value * ofunc = NULL;   /* I'm not sure here. Should I have
used a
  			     CAMLlocal macro */

  /* .

     ...Erased sanity checks for shortening the mail...
     .
  */

  /* my_* are C converted versions of '*' parameters */
  my_x = Data_bigarray_val(x);
  my_y = Data_bigarray_val(y);
  my_params = Data_bigarray_val(params0);

  /* Number of experimental data points */
  m = Bigarray_val(x)->dim[0];

  /* Number of parameters */
  n = Bigarray_val(params0)->dim[0];

  my_tol=Double_val(tol);

  /*.
    ... Allocations of fvec, iwa, wa....
    ... Initialisation lwa....
    .
  */

  if (Tag_val(func) == 0){	/* OFitfunc of (string * fitable) */

    /* Nested function definition: GCC EXTENSION */
    void my_fcn(int *m, int *n, double *params, double *fvec,
int *iflag){

      /* Should any CAML* macro be used here? */
      value baparams;
      int i;

      /* And here? */
      ofunc = caml_named_value(
String_val(Field(Field(func,0), 0)) );
      assert(ofunc);

      baparams =
        alloc_bigarray_dims(BIGARRAY_FLOAT64
|BIGARRAY_C_LAYOUT,1, params, *n);

      /* For each data point, fvec is filled with the distance
between
      computed value and experimental values */

      for (i=0; i<(*m); i++){
	fvec[i] =
          Double_val(
             caml_callback2(*ofunc, baparams,
caml_copy_double(my_x[i]))
          ) - my_y[i];
      }

      /* Should baparams be freed there? And if yes, how? */
    };

   /* MINPACK FORTRAN SUBROUTINE CALL */
   lmdif1_(*my_fcn, &m, &n,
	   my_params, fvec, &my_tol, &info, iwa, wa, &lwa);


  } else {
    if (Tag_val(func) == 1) {	/* CFitfunc of nativeint */
      f = (ffittable) Nativeint_val(Field(func, 0));

      /* Nested function definition: GCC EXTENSION */
      void my_fcn(int *m, int *n, double *params, double
*fvec, int *iflag){
	int i;
	for (i=0; i<(*m); i++){
	  fvec[i] = (*f)(my_x[i], params) - my_y[i];
	}
      };

   /* MINPACK FORTRAN SUBROUTINE CALL */
   lmdif1_(*my_fcn, &m, &n, my_params, fvec, &my_tol, &info,
iwa, wa, &lwa);


    } else {
      assert(0);
    }
  }


  /* free what can be freed...*/
   CAMLreturn(Val_int(info));
}

Salutations

Matthieu Dubuget

Créez votre adresse électronique prenom.nom@laposte.net
1 Go d'espace de stockage, anti-spam et anti-virus intégrés.


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Caml-list] nonlinear fit function binding
  2007-05-25  7:54 nonlinear fit function binding matthieu.dubuget
@ 2007-05-31 11:42 ` Matthieu Dubuget
  0 siblings, 0 replies; 2+ messages in thread
From: Matthieu Dubuget @ 2007-05-31 11:42 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 680 bytes --]

Well. It seems my former message was unclear?

Here is a more precise question: should/could C allocated bigarrays
 be freed?

Context:

OCaml calls one C function M, at about 50
Hz.
In M,  a C function (let's call it A) is locally defined.
One pointer to A is given to another function, that
calls A more than once.

Function A wraps a C array it receives as a parameter
into a bigarray, and give it to OCaml through one callback.

The whole process is repeated, at about 50 Hz.

I do not know if the bigarrays allocated by M are garbage
collected in any way, and if they are not, how I could free
them in order to avoid any memory leak?

Thanks in advance
Salutations

Matthieu

[-- Attachment #2: Type: text/html, Size: 973 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2007-05-31 11:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-05-25  7:54 nonlinear fit function binding matthieu.dubuget
2007-05-31 11:42 ` [Caml-list] " Matthieu Dubuget

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).