From 93a12a972a0a5f41b692b0dcb85f04112ca7d861 Mon Sep 17 00:00:00 2001 From: HugoMVale <57530119+HugoMVale@users.noreply.github.com> Date: Mon, 24 Jun 2024 22:56:52 +0200 Subject: [PATCH] finish odr_short_c --- c/example/example5.c | 44 ++++-- include/odrpack/odrpack.h | 293 +++++++++++++++++++++++++++----------- src/odrpack_c.f90 | 88 ++++++++++-- 3 files changed, 317 insertions(+), 108 deletions(-) diff --git a/c/example/example5.c b/c/example/example5.c index 8a1c85a..d530eb4 100644 --- a/c/example/example5.c +++ b/c/example/example5.c @@ -60,27 +60,41 @@ int main() double x[M][N] = {{0.982, 1.998, 4.978, 6.01}}; double y[NQ][N] = {{2.7, 7.4, 148.0, 403.0}}; - // odr_short_c(fcn, &n, &m, &np, &nq, beta, (double *)y, (double *)x, &job, lower, upper); + // odr_basic_c(fcn, &n, &m, &np, &nq, beta, (double *)y, (double *)x, lower, upper, &job); - int ifixb[NP] = {1, 1}; - int ndigit = -1; - double taufac = -1.0; - double sstol = -1.0; - double partol = -1.0; - int maxint = -1; + int ldwe = 1; + int ld2we = 1; + int ldwd = 1; + int ld2wd = 1; + double we[NQ][1][1] = {-1.0}; + double wd[M][1][1] = {-1.0}; int iprint = 1001; int lunerr = -1; int lunrpt = -1; int info = 0; - double *stpb = NULL; - double *sclb = NULL; - odr_c(fcn, &n, &m, &np, &nq, beta, (double *)y, (double *)x, - ifixb, - &job, &ndigit, &taufac, &sstol, &partol, &maxint, &iprint, &lunerr, &lunrpt, - stpb, sclb, - &info, - lower, upper); + // int ifixb[NP] = {1, 1}; + // int ndigit = -1; + // double taufac = -1.0; + // double sstol = -1.0; + // double partol = -1.0; + // int maxint = -1; + // double *stpb = NULL; + // double *sclb = NULL; + + odr_short_c(fcn, &n, &m, &np, &nq, beta, (double *)y, (double *)x, + (double *)we, &ldwe, &ld2we, + (double *)wd, &ldwd, &ld2wd, + lower, upper, + &job, &iprint, &lunerr, &lunrpt, + &info); + + // odr_basic_c(fcn, &n, &m, &np, &nq, beta, (double *)y, (double *)x, + // ifixb, + // &job, &ndigit, &taufac, &sstol, &partol, &maxint, &iprint, &lunerr, &lunrpt, + // stpb, sclb, + // &info, + // lower, upper); return 0; } diff --git a/include/odrpack/odrpack.h b/include/odrpack/odrpack.h index 5a9cbbb..3d8d603 100644 --- a/include/odrpack/odrpack.h +++ b/include/odrpack/odrpack.h @@ -24,35 +24,38 @@ ODRPACK_EXTERN void open_file( /** * @brief Close a file associated with a specified logical unit number. * - * @param lun Logical unit number. + * @param lun Logical unit number. + * @param ierr Error code. */ -ODRPACK_EXTERN void close_file(int *lun); +ODRPACK_EXTERN void close_file( + const int *lun, + int *ierr); /** * @brief User-supplied function for evaluating the model, computing predicted values and their Jacobians. * - * @param n Number of observations. - * @param m Number of columns of data in the independent variable. - * @param np Number of function parameters. - * @param nq Number of responses per observation. - * @param ldn Leading dimension declarator for `n`, `ldn >= n`. - * @param ldm Leading dimension declarator for `m`, `ldm >= m`. - * @param ldnp Leading dimension declarator for `np`, `ldnp >= np`. - * @param beta Input array [np] of current parameter values. - * @param xplusd Input array [m][ldn] of current explanatory variable values, i.e., `x + delta`. - * @param ifixb Input array [np] of indicators for fixing parameters `beta`. - * @param ifixx Input array [m][ldifx] of indicators for fixing explanatory variable `x`. - * @param ldifx Leading dimension of array `ifixx`. - * @param ideval Indicator for selecting computation to be performed. - * @param f Output array [nq][ldn] for predicted function values. - * @param fjacb Output array [nq][ldnp][ldn] for Jacobian with respect to `beta`. - * @param fjacd Output array [nq][ldm][ldn] for Jacobian with respect to errors `delta`. - * @param istop Output integer for stopping condition. Values: + * @param n ==> Number of observations. + * @param m ==> Number of columns of data in the independent variable. + * @param np ==> Number of function parameters. + * @param nq ==> Number of responses per observation. + * @param ldn ==> Leading dimension declarator for `n`, `ldn >= n`. + * @param ldm ==> Leading dimension declarator for `m`, `ldm >= m`. + * @param ldnp ==> Leading dimension declarator for `np`, `ldnp >= np`. + * @param beta ==> Array [np] of current parameter values. + * @param xplusd ==> Array [m][ldn] of current explanatory variable values, i.e., `x + delta`. + * @param ifixb ==> Array [np] of indicators for fixing parameters `beta`. + * @param ifixx ==> Array [m][ldifx] of indicators for fixing explanatory variable `x`. + * @param ldifx ==> Leading dimension of array `ifixx`. + * @param ideval ==> Indicator for selecting computation to be performed. + * @param f <== Array [nq][ldn] for predicted function values. + * @param fjacb <== Array [nq][ldnp][ldn] for Jacobian with respect to `beta`. + * @param fjacd <== Array [nq][ldm][ldn] for Jacobian with respect to errors `delta`. + * @param istop <== Integer for stopping condition. Values: * 0 - current `beta` and `x+delta` were acceptable and values were computed successfully, * 1 - current `beta` and `x+delta` are not acceptable; ODRPACK95 should select values closer to most recently used values if possible, * -1 - current `beta` and `x+delta` are not acceptable; ODRPACK95 should stop. */ -typedef void (*odrpack_fcn_callback)( +typedef void (*odrpack_fcn)( int *n, int *m, int *np, @@ -60,10 +63,10 @@ typedef void (*odrpack_fcn_callback)( int *ldn, int *ldm, int *ldnp, - double *beta, // const - double *xplusd, // const - int *ifixb, // const - int *ifixx, // const + double *beta, + double *xplusd, + int *ifixb, + int *ifixx, int *ldifx, int *ideval, double *f, @@ -72,34 +75,23 @@ typedef void (*odrpack_fcn_callback)( int *istop); /** - * @brief Wrapper for the ODR routine including only mandatory arguments. + * @brief Basic wrapper for the ODR routine including only mandatory arguments and very few + * optional arguments. * - * @param fcn User-supplied subroutine for evaluating the model. - * @param n Number of observations. - * @param m Number of columns of data in the independent variable. - * @param np Number of function parameters. - * @param nq Number of responses per observation. - * @param beta Input/output array [np] of function parameters. - * @param y Input array [nq][n] of dependent variable. Unused when the model is implicit. - * @param x Input array [m][n] of explanatory variable. - * @param ifixb Input array [np] of indicators for fixing parameters `beta`. - * @param job Variable controlling problem initialization and computational method. - * @param ndigit Number of accurate digits in the function results, as supplied by the user. - * @param taufac Factor used to compute the initial trust region diameter. - * @param sstol Sum-of-squares convergence stopping tolerance. - * @param partol Parameter convergence stopping tolerance. - * @param maxint Maximum number of iterations allowed. - * @param iprint Print control variable. - * @param lunerr Logical unit number for error messages. - * @param lunrpt Logical unit number for computation reports. - * @param stpb Input array [np] with relative step for computing finite difference derivatives with respect to `beta`. - * @param sclb Input array [np] with scaling values for `beta`. - * @param info Variable designating why the computations were stopped. - * @param lower Input array [np] with lower bound on `beta`. - * @param upper Input array [np] with upper bound on `beta`. + * @param fcn ==> User-supplied subroutine for evaluating the model. + * @param n ==> Number of observations. + * @param m ==> Number of columns of data in the independent variable. + * @param np ==> Number of function parameters. + * @param nq ==> Number of responses per observation. + * @param beta <=> Array [np] of function parameters. + * @param y ==> Array [nq][n] of dependent variable. Unused when the model is implicit. + * @param x ==> Array [m][n] of explanatory variable. + * @param job ==> Optional variable controlling initialization and computational method. + * @param lower ==> Optional array [np] with lower bound on `beta`. + * @param upper ==> Optional array [np] with upper bound on `beta`. */ -ODRPACK_EXTERN void odr_c( - odrpack_fcn_callback fcn, +ODRPACK_EXTERN void odr_basic_c( + odrpack_fcn fcn, const int *n, const int *m, const int *np, @@ -107,42 +99,38 @@ ODRPACK_EXTERN void odr_c( double *beta, const double *y, const double *x, - const int *ifixb, - - const int *job, - const int *ndigit, - const double *taufac, - const double *sstol, - const double *partol, - const int *maxint, - const int *iprint, - const int *lunerr, - const int *lunrpt, - - const double *stpb, - const double *sclb, - - int *info, const double *lower, - const double *upper); + const double *upper, + const int *job); /** - * @brief Short wrapper for the ODR routine including only mandatory arguments. + * @brief Wrapper for the ODR routine including mandatory arguments and most commonly used + * optional arguments. Similar to the short-call statement of the original ODRPACK `DODR`. * - * @param fcn User-supplied subroutine for evaluating the model. - * @param n Number of observations. - * @param m Number of columns of data in the independent variable. - * @param np Number of function parameters. - * @param nq Number of responses per observation. - * @param beta Input/output array [np] of function parameters. - * @param y Input array [nq][n] of dependent variable. Unused when the model is implicit. - * @param x Input array [m][n] of explanatory variable. - * @param job Variable controlling problem initialization and computational method. - * @param lower Input array [np] with lower bound on `beta`. - * @param upper Input array [np] with upper bound on `beta`. + * @param fcn ==> User-supplied subroutine for evaluating the model. + * @param n ==> Number of observations. + * @param m ==> Number of columns of data in the independent variable. + * @param np ==> Number of function parameters. + * @param nq ==> Number of responses per observation. + * @param beta <=> Array [np] of function parameters. + * @param y ==> Array [nq][n] of dependent variable. Unused when the model is implicit. + * @param x ==> Array [m][n] of explanatory variable. + * @param we ==> Array [nq][ld2we][ldwe] with `epsilon` weights. + * @param ldwe ==> Leading dimension of array `we`. + * @param ld2we ==> Second dimension of array `we`. + * @param wd ==> Array [m][ld2wd][ldwd] with `delta` weights. + * @param ldwd ==> Leading dimension of array `wd`. + * @param ld2wd ==> Second dimension of array `wd`. + * @param lower ==> Optional array [np] with lower bound on `beta`. + * @param upper ==> Optional array [np] with upper bound on `beta`. + * @param job ==> Optional variable controlling initialization and computational method. + * @param iprint ==> Optional print control variable. + * @param lunerr ==> Optional logical unit number for error messages. + * @param lunrpt ==> Optional logical unit number for computation reports. + * @param info <== Optional variable designating why the computations were stopped. */ ODRPACK_EXTERN void odr_short_c( - odrpack_fcn_callback fcn, + odrpack_fcn fcn, const int *n, const int *m, const int *np, @@ -150,8 +138,147 @@ ODRPACK_EXTERN void odr_short_c( double *beta, const double *y, const double *x, - int *job, + const double *we, + const int *ldwe, + const int *ld2we, + const double *wd, + const int *ldwd, + const int *ld2wd, const double *lower, - const double *upper); + const double *upper, + const int *job, + const int *iprint, + const int *lunerr, + const int *lunrpt, + int *info); + +// * @param stpb Input array [np] with relative step for computing finite difference +// * derivatives with respect to `beta`. +// * @param sclb Input array [np] with scaling values for `beta`. + +/** + * @brief Set storage locations within real work space. + * + * @param n ==> Number of observations. + * @param m ==> Number of columns of data in the explanatory variable. + * @param np ==> Number of function parameters. + * @param nq ==> Number of responses per observation. + * @param ldwe ==> Leading dimension of array `we`. + * @param ld2we ==> Second dimension of array `we`. + * @param isodr <== Variable designating whether the solution is by ODR (`isodr=.true.`) or + * by OLS (`isodr=.false.`). + * @param deltai <== Starting location in array `work` of array `delta`. + * @param epsi <== Starting location in array `work` of array `eps`. + * @param xplusi <== Starting location in array `work` of array `xplusd`. + * @param fni <== Starting location in array `work` of array `fn`. + * @param sdi <== Starting location in array `work` of array `sd`. + * @param vcvi <== Starting location in array `work` of array `vcv`. + * @param rvari <== Location in array `work` of variable `rvar`. + * @param wssi <== Location in array `work` of variable `wss`. + * @param wssdei <== Location in array `work` of variable `wssdel`. + * @param wssepi <== Location in array `work` of variable `wsep`. + * @param rcondi <== Location in array `work` of variable `rcond`. + * @param etai <== Location in array `work` of variable `eta`. + * @param olmavi <== Location in array `work` of variable `olmavg`. + * @param taui <== Location in array `work` of variable `tau`. + * @param alphai <== Location in array `work` of variable `alpha`. + * @param actrsi <== Location in array `work` of variable `actrs`. + * @param pnormi <== Location in array `work` of variable `pnorm`. + * @param rnorsi <== Location in array `work` of variable `rnorms`. + * @param prersi <== Location in array `work` of variable `prers`. + * @param partli <== Location in array `work` of variable `partol`. + * @param sstoli <== Location in array `work` of variable `sstol`. + * @param taufci <== Location in array `work` of variable `taufac`. + * @param epsmai <== Location in array `work` of variable `epsmac`. + * @param beta0i <== Starting location in array `work` of array `beta0`. + * @param betaci <== Starting location in array `work` of array `betac`. + * @param betasi <== Starting location in array `work` of array `betas`. + * @param betani <== Starting location in array `work` of array `betan`. + * @param si <== Starting location in array `work` of array `s`. + * @param ssi <== Starting location in array `work` of array `ss`. + * @param ssfi <== Starting location in array `work` of array `ssf`. + * @param qrauxi <== Starting location in array `work` of array `qraux`. + * @param ui <== Starting location in array `work` of array `u`. + * @param fsi <== Starting location in array `work` of array `fs`. + * @param fjacbi <== Starting location in array `work` of array `fjacb`. + * @param we1i <== Location in array `work` of variable `we1`. + * @param diffi <== Starting location in array `work` of array `diff`. + * @param deltsi <== Starting location in array `work` of array `deltas`. + * @param deltni <== Starting location in array `work` of array `deltan`. + * @param ti <== Starting location in array `work` of array `t`. + * @param tti <== Starting location in array `work` of array `tt`. + * @param omegai <== Starting location in array `work` of array `omega`. + * @param fjacdi <== Starting location in array `work` of array `fjacd`. + * @param wrk1i <== Starting location in array `work` of array `wrk1`. + * @param wrk2i <== Starting location in array `work` of array `wrk2`. + * @param wrk3i <== Starting location in array `work` of array `wrk3`. + * @param wrk4i <== Starting location in array `work` of array `wrk4`. + * @param wrk5i <== Starting location in array `work` of array `wrk5`. + * @param wrk6i <== Starting location in array `work` of array `wrk6`. + * @param wrk7i <== Starting location in array `work` of array `wrk7`. + * @param loweri <== Starting location in array `work` of array `lower`. + * @param upperi <== Starting location in array `work` of array `upper`. + * @param lwkmn <== Minimum acceptable length of vector `work`. + */ +ODRPACK_EXTERN void dwinf_c( + const int *n, + const int *m, + const int *np, + const int *nq, + const int *ldwe, + const int *ld2we, + int *isodr, + int *deltai, + int *epsi, + int *xplusi, + int *fni, + int *sdi, + int *vcvi, + int *rvari, + int *wssi, + int *wssdei, + int *wssepi, + int *rcondi, + int *etai, + int *olmavi, + int *taui, + int *alphai, + int *actrsi, + int *pnormi, + int *rnorsi, + int *prersi, + int *partli, + int *sstoli, + int *taufci, + int *epsmai, + int *beta0i, + int *betaci, + int *betasi, + int *betani, + int *si, + int *ssi, + int *ssfi, + int *qrauxi, + int *ui, + int *fsi, + int *fjacbi, + int *we1i, + int *diffi, + int *deltsi, + int *deltni, + int *ti, + int *tti, + int *omegai, + int *fjacdi, + int *wrk1i, + int *wrk2i, + int *wrk3i, + int *wrk4i, + int *wrk5i, + int *wrk6i, + int *wrk7i, + int *loweri, + int *upperi, + int *lwkmn); -#endif // ODRPACK_H \ No newline at end of file +#endif // ODRPACK_H diff --git a/src/odrpack_c.f90 b/src/odrpack_c.f90 index 6a8b943..d3b163e 100644 --- a/src/odrpack_c.f90 +++ b/src/odrpack_c.f90 @@ -10,7 +10,7 @@ module odrpack_c abstract interface subroutine fcn_tc(n, m, np, nq, ldn, ldm, ldnp, beta, xplusd, ifixb, ifixx, ldifx, & ideval, f, fjacb, fjacd, istop) bind(C) - !! User-supplied subroutine for evaluating the model. + !! User-supplied subroutine for evaluating the model. import :: c_int, c_double integer(c_int), intent(in) :: n integer(c_int), intent(in) :: m @@ -34,8 +34,9 @@ subroutine fcn_tc(n, m, np, nq, ldn, ldm, ldnp, beta, xplusd, ifixb, ifixx, ldif contains - subroutine odr_short_c(fcn, n, m, np, nq, beta, y, x, job, lower, upper) bind(C) - !! "Short" wrapper for the ODR routine including only principal arguments. + subroutine odr_basic_c(fcn, n, m, np, nq, beta, y, x, lower, upper, job) bind(C) + !! Wrapper for the ODR routine including mandatory arguments and very few optional + !! arguments. procedure(fcn_tc) :: fcn !! User-supplied subroutine for evaluating the model. integer(c_int), intent(in) :: n @@ -52,14 +53,79 @@ subroutine odr_short_c(fcn, n, m, np, nq, beta, y, x, job, lower, upper) bind(C) !! Dependent variable. Unused when the model is implicit. real(c_double), intent(in) :: x(n, m) !! Explanatory variable. - integer(c_int), intent(in), optional :: job - !! Variable controlling problem initialization and computational method. real(c_double), intent(in), optional :: lower(np) !! Lower bound on `beta`. real(kind=wp), intent(in), optional :: upper(np) !! Upper bound on `beta`. + integer(c_int), intent(in), optional :: job + !! Variable controlling initialization and computational method. + + call odr(fcn, n, m, np, nq, beta, y, x, lower=lower, upper=upper, job=job) + + end subroutine odr_basic_c - call odr(fcn, n, m, np, nq, beta, y, x, job=job, lower=lower, upper=upper) + + subroutine odr_short_c( & + fcn, & + n, m, np, nq, & + beta, y, x, & + we, ldwe, ld2we, & + wd, ldwd, ld2wd, & + lower, upper, & + job, & + iprint, lunerr, lunrpt, & + info) bind(C) + !! Wrapper for the ODR routine including mandatory arguments and most commonly used + !! optional arguments. Similar to the short-call statement of the original ODRPACK `DODR`. + procedure(fcn_tc) :: fcn + !! User-supplied subroutine for evaluating the model. + integer(c_int), intent(in) :: n + !! Number of observations. + integer(c_int), intent(in) :: m + !! Number of columns of data in the independent variable. + integer(c_int), intent(in) :: np + !! Number of function parameters. + integer(c_int), intent(in) :: nq + !! Number of responses per observation. + real(c_double), intent(inout) :: beta(np) + !! Function parameters. + real(c_double), intent(in) :: y(n, nq) + !! Dependent variable. Unused when the model is implicit. + real(c_double), intent(in) :: x(n, m) + !! Explanatory variable. + real(c_double), intent(in) :: we(ldwe, ld2we, nq) + !! `epsilon` weights. + integer(c_int), intent(in) :: ldwe + !! Leading dimension of array `we`. + integer(c_int), intent(in) :: ld2we + !! Second dimension of array `we`. + real(c_double), intent(in) :: wd(ldwd, ld2wd, m) + !! `delta` weights. + integer(c_int), intent(in) :: ldwd + !! Leading dimension of array `wd`. + integer(c_int), intent(in) :: ld2wd + !! Second dimension of array `wd`. + real(c_double), intent(in), optional :: lower(np) + !! Lower bound on `beta`. + real(kind=wp), intent(in), optional :: upper(np) + !! Upper bound on `beta`. + integer(c_int), intent(in), optional :: job + !! Variable controlling initialization and computational method. + integer(c_int), intent(in), optional :: iprint + !! Print control variable. + integer(c_int), intent(in), optional :: lunerr + !! Logical unit number for error messages. + integer(c_int), intent(in), optional :: lunrpt + !! Logical unit number for computation reports. + integer(c_int), intent(out), optional :: info + !! Logical unit number for computation reports. + + call odr(fcn, n, m, np, nq, beta, y, x, & + we=we, wd=wd, & + lower=lower, upper=upper, & + job=job, & + iprint=iprint, lunerr=lunerr, lunrpt=lunrpt, & + info=info) end subroutine odr_short_c @@ -185,11 +251,13 @@ subroutine open_file(lun, fn, fnlen, ierr) bind(C) end subroutine open_file - subroutine close_file(lun) bind(C) + subroutine close_file(lun, ierr) bind(C) !! Close a file associated with a specified logical unit number. integer(c_int), intent(in) :: lun !! Logical unit number. - close (unit=lun) + integer(c_int), intent(out) :: ierr + !! Error code returned by `iostat`. + close (unit=lun, iostat=ierr) end subroutine close_file subroutine dwinf_c( & @@ -218,7 +286,7 @@ subroutine dwinf_c( & integer(c_int), intent(in) :: ld2we !! Second dimension of array `we`. integer(c_int), intent(out) :: isodr - !! Variable designating whether the solution is by ODR (isodr=.true.) or by OLS (isodr=.false.). + !! Variable designating whether the solution is by ODR (`isodr=.true.`) or by OLS (`isodr=.false.`). integer(c_int), intent(out) :: deltai !! Starting location in array `work` of array `delta. integer(c_int), intent(out) :: epsi @@ -322,7 +390,7 @@ subroutine dwinf_c( & integer(c_int), intent(out) :: upperi !! Starting location in array `work` of array `upper`. integer(c_int), intent(out) :: lwkmn - !! Minimum acceptable length of vector work. + !! Minimum acceptable length of vector `work`. external :: dwinf