From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=disabled version=3.1.3 Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by yquem.inria.fr (Postfix) with ESMTP id EF9DEBC0A for ; Fri, 25 May 2007 09:54:39 +0200 (CEST) Received: from mx.laposte.net (mx.laposte.net [81.255.54.16]) by concorde.inria.fr (8.13.6/8.13.6) with ESMTP id l4P7sdLW012788 for ; Fri, 25 May 2007 09:54:39 +0200 Received: from smtp.laposte.net (10.150.9.42) by mx.laposte.net (7.2.060.1) id 461F7203015A582A for caml-list@inria.fr; Fri, 25 May 2007 09:54:39 +0200 Received: from smtpin.laposte.net (10.150.9.74) by smtp.laposte.net (7.3.118.3) id 4643105201BDED3A for caml-list@inria.fr; Fri, 25 May 2007 09:54:39 +0200 Received: from laposte.net (10.150.9.80) by smtpin.laposte.net (7.2.060.1) id 46532F980003925C for caml-list@inria.fr; Fri, 25 May 2007 09:54:39 +0200 Date: Fri, 25 May 2007 09:54:39 +0200 Message-Id: Subject: nonlinear fit function binding MIME-Version: 1.0 X-Sensitivity: 3 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable From: "matthieu.dubuget" To: "Caml List" X-XaM3-API-Version: 4.1 (B103) X-SenderIP: 127.0.0.1 X-j-chkmail-Score: MSGID : 4656963F.000 on concorde : j-chkmail score : XX : 5/20 0 0.000 -> 2 X-Miltered: at concorde with ID 4656963F.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; matthieu:01 dubuget:01 matthieu:01 dubuget:01 extern:01 tol:01 pointer:01 ocaml:01 bigarray:01 elt:01 bigarray:01 genarray:01 ocaml:01 nativeint:01 pointer:01 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 =3D (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 =3D float1darray -> float -> float (* Since I also want to be able to use directly C functions: *) type fitfunc =3D 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 =3D "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=3D1e-6) () =3D let () =3D 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 =3D NULL; value * ofunc =3D 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 =3D Data_bigarray_val(x); my_y =3D Data_bigarray_val(y); my_params =3D Data_bigarray_val(params0); /* Number of experimental data points */ m =3D Bigarray_val(x)->dim[0]; /* Number of parameters */ n =3D Bigarray_val(params0)->dim[0]; my_tol=3DDouble_val(tol); /*. ... Allocations of fvec, iwa, wa.... ... Initialisation lwa.... . */ if (Tag_val(func) =3D=3D 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 =3D caml_named_value( String_val(Field(Field(func,0), 0)) ); assert(ofunc); baparams =3D 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=3D0; i<(*m); i++){ fvec[i] =3D 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) =3D=3D 1) { /* CFitfunc of nativeint */ f =3D (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=3D0; i<(*m); i++){ fvec[i] =3D (*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=0A=0ACr=E9ez votre adresse =E9lectronique prenom.nom@lap= oste.net 1 Go d'espace de stockage, anti-spam et anti-virus int=E9gr=E9s.