odr Subroutine

public impure subroutine odr(fcn, n, m, np, nq, beta, y, x, delta, we, wd, ifixb, ifixx, job, ndigit, taufac, sstol, partol, maxit, iprint, lunerr, lunrpt, stpb, stpd, sclb, scld, work, iwork, info, lower, upper)

Uses

  • proc~~odr~~UsesGraph proc~odr odr module~odrpack_core odrpack_core proc~odr->module~odrpack_core module~odrpack_kinds odrpack_kinds proc~odr->module~odrpack_kinds module~odrpack_reports odrpack_reports proc~odr->module~odrpack_reports module~odrpack_core->module~odrpack_kinds iso_fortran_env iso_fortran_env module~odrpack_kinds->iso_fortran_env module~odrpack_reports->module~odrpack_kinds

Driver routine for finding the weighted explicit or implicit orthogonal distance regression (ODR) or ordinary linear or nonlinear least squares (OLS) solution.

Arguments

Type IntentOptional Attributes Name
procedure(fcn_t) :: fcn

User-supplied subroutine for evaluating the model.

integer, intent(in) :: n

Number of observations.

integer, intent(in) :: m

Number of columns of data in the independent variable.

integer, intent(in) :: np

Number of function parameters.

integer, intent(in) :: nq

Number of responses per observation.

real(kind=wp), intent(inout) :: beta(:)

Function parameters. Shape: (np).

real(kind=wp), intent(in) :: y(:,:)

Dependent variable. Shape: (n, nq). Unused when the model is implicit.

real(kind=wp), intent(in) :: x(:,:)

Explanatory variable. Shape: (n, m).

real(kind=wp), intent(inout), optional :: delta(:,:)

Error in the x data. Shape: (n, m). Initial guess on input and estimated value on output.

real(kind=wp), intent(in), optional :: we(:,:,:)

epsilon weights. Shape: (1<=ldwe<=n, 1<=ld2we<=nq, nq). See p. 25.

real(kind=wp), intent(in), optional :: wd(:,:,:)

delta weights. Shape: (1<=ldwd<=n, 1<=ld2wd<=m, m). See p. 26.

integer, intent(in), optional :: ifixb(:)

Values designating whether the elements of beta are fixed at their input values or not. Shape: (np).

integer, intent(in), optional :: ifixx(:,:)

Values designating whether the elements of x are fixed at their input values or not. Shape: (1<=ldifx<=n, m). See p. 27.

integer, intent(in), optional :: job

Variable controlling problem initialization and computational method.

integer, intent(in), optional :: ndigit

Number of accurate digits in the function results, as supplied by the user.

real(kind=wp), intent(in), optional :: taufac

Factor used to compute the initial trust region diameter.

real(kind=wp), intent(in), optional :: sstol

Sum-of-squares convergence stopping tolerance.

real(kind=wp), intent(in), optional :: partol

Parameter convergence stopping tolerance.

integer, intent(in), optional :: maxit

Maximum number of iterations allowed.

integer, intent(in), optional :: iprint

Print control variable.

integer, intent(in), optional :: lunerr

Logical unit number for error messages. Available options are: 0 => no output. 6 => output to standard error. other => output to logical unit number lunerr.

integer, intent(in), optional :: lunrpt

Logical unit number for computation reports. Available options are: 0 => no output. 6 => output to standard error. other => output to logical unit number lunrpt.

real(kind=wp), intent(in), optional :: stpb(:)

Relative step for computing finite difference derivatives with respect to beta. Shape: (np).

real(kind=wp), intent(in), optional :: stpd(:,:)

Relative step for computing finite difference derivatives with respect to delta. Shape: (1<=ldstpd<=n, m). See p. 31.

real(kind=wp), intent(in), optional :: sclb(:)

Scaling values for beta. Shape: (np).

real(kind=wp), intent(in), optional :: scld(:,:)

Scaling values for delta. Shape: (1<=ldscld<=n, m). See p. 32.

real(kind=wp), intent(inout), optional, target :: work(:)

Real work space.

integer, intent(inout), optional, target :: iwork(:)

Integer work space.

integer, intent(out), optional :: info

Variable designating why the computations were stopped.

real(kind=wp), intent(in), optional :: lower(:)

Lower bound on beta. Shape: (np).

real(kind=wp), intent(in), optional :: upper(:)

Upper bound on beta. Shape: (np).


Calls

proc~~odr~~CallsGraph proc~odr odr proc~dodcnt dodcnt proc~odr->proc~dodcnt proc~dodpe1 dodpe1 proc~odr->proc~dodpe1 proc~dodphd dodphd proc~odr->proc~dodphd proc~workspace_dimensions workspace_dimensions proc~odr->proc~workspace_dimensions proc~doddrv doddrv proc~dodcnt->proc~doddrv interface~dcopy dcopy proc~doddrv->interface~dcopy interface~ddot ddot proc~doddrv->interface~ddot interface~dnrm2 dnrm2 proc~doddrv->interface~dnrm2 proc~derstep derstep proc~doddrv->proc~derstep proc~detaf detaf proc~doddrv->proc~detaf proc~dfctrw dfctrw proc~doddrv->proc~dfctrw proc~dflags dflags proc~doddrv->proc~dflags proc~diniwk diniwk proc~doddrv->proc~diniwk proc~diwinf diwinf proc~doddrv->proc~diwinf proc~djck djck proc~doddrv->proc~djck proc~dodchk dodchk proc~doddrv->proc~dodchk proc~dodmn dodmn proc~doddrv->proc~dodmn proc~dodper dodper proc~doddrv->proc~dodper proc~dpack dpack proc~doddrv->proc~dpack proc~dsetn dsetn proc~doddrv->proc~dsetn proc~dunpac dunpac proc~doddrv->proc~dunpac proc~dwght dwght proc~doddrv->proc~dwght proc~dwinf dwinf proc~doddrv->proc~dwinf proc~mbfb mbfb proc~doddrv->proc~mbfb proc~dhstep dhstep proc~derstep->proc~dhstep proc~dfctr dfctr proc~dfctrw->proc~dfctr proc~diniwk->interface~dcopy proc~diniwk->proc~dflags proc~dsclb dsclb proc~diniwk->proc~dsclb proc~dscld dscld proc~diniwk->proc~dscld proc~djck->proc~dhstep proc~djckm djckm proc~djck->proc~djckm proc~dodmn->interface~dcopy proc~dodmn->interface~ddot proc~dodmn->interface~dnrm2 proc~dodmn->proc~dflags proc~dodmn->proc~dpack proc~dodmn->proc~dunpac proc~dodmn->proc~dwght proc~dacces dacces proc~dodmn->proc~dacces proc~devjac devjac proc~dodmn->proc~devjac proc~dodlm dodlm proc~dodmn->proc~dodlm proc~dodpcr dodpcr proc~dodmn->proc~dodpcr proc~dodvcv dodvcv proc~dodmn->proc~dodvcv proc~dodper->proc~dodpe1 proc~dodper->proc~dodphd proc~dodpe2 dodpe2 proc~dodper->proc~dodpe2 proc~dodpe3 dodpe3 proc~dodper->proc~dodpe3 proc~dpack->interface~dcopy proc~dunpac->interface~dcopy proc~mbfb->proc~dhstep proc~dacces->proc~diwinf proc~dacces->proc~dwinf proc~devjac->interface~ddot proc~devjac->proc~dunpac proc~devjac->proc~dwght proc~difix difix proc~devjac->proc~difix proc~djaccd djaccd proc~devjac->proc~djaccd proc~djacfd djacfd proc~devjac->proc~djacfd proc~dfctr->interface~ddot proc~djckc djckc proc~djckm->proc~djckc proc~djckz djckz proc~djckm->proc~djckz proc~dpvb dpvb proc~djckm->proc~dpvb proc~dpvd dpvd proc~djckm->proc~dpvd proc~dodlm->interface~ddot proc~dodlm->interface~dnrm2 proc~dodlm->proc~dwght proc~dodstp dodstp proc~dodlm->proc~dodstp proc~dscale dscale proc~dodlm->proc~dscale proc~dodpcr->proc~dodphd proc~dodpcr->proc~dflags proc~dodpc1 dodpc1 proc~dodpcr->proc~dodpc1 proc~dodpc2 dodpc2 proc~dodpcr->proc~dodpc2 proc~dodpc3 dodpc3 proc~dodpcr->proc~dodpc3 dpodi dpodi proc~dodvcv->dpodi proc~dodvcv->proc~dodstp proc~djaccd->proc~derstep proc~djaccd->proc~dhstep proc~djacfd->proc~derstep proc~djacfd->proc~dhstep proc~djckc->proc~dpvb proc~djckc->proc~dpvd proc~djckf djckf proc~djckc->proc~djckf proc~djckz->proc~dpvb proc~djckz->proc~dpvd proc~dodpc1->proc~dhstep proc~dppt dppt proc~dodpc3->proc~dppt proc~dodstp->interface~dnrm2 proc~dodstp->proc~dwght proc~dodstp->proc~dfctr dchex dchex proc~dodstp->dchex dqrdc dqrdc proc~dodstp->dqrdc dqrsl dqrsl proc~dodstp->dqrsl dtrco dtrco proc~dodstp->dtrco dtrsl dtrsl proc~dodstp->dtrsl interface~drot drot proc~dodstp->interface~drot interface~drotg drotg proc~dodstp->interface~drotg interface~idamax idamax proc~dodstp->interface~idamax proc~desubi desubi proc~dodstp->proc~desubi proc~dsolve dsolve proc~dodstp->proc~dsolve proc~dvevtr dvevtr proc~dodstp->proc~dvevtr proc~djckf->proc~dpvb proc~djckf->proc~dpvd proc~dppnml dppnml proc~dppt->proc~dppnml proc~dsolve->interface~ddot interface~daxpy daxpy proc~dsolve->interface~daxpy proc~dvevtr->proc~dsolve

Called by

proc~~odr~~CalledByGraph proc~odr odr proc~odr_long_c odr_long_c proc~odr_long_c->proc~odr proc~odr_medium_c odr_medium_c proc~odr_medium_c->proc~odr proc~odr_short_c odr_short_c proc~odr_short_c->proc~odr program~example1 example1 program~example1->proc~odr program~example2 example2 program~example2->proc~odr program~example3 example3 program~example3->proc~odr program~example4 example4 program~example4->proc~odr program~example5 example5 program~example5->proc~odr

Variables

Type Visibility Attributes Name Initial
integer, public :: ldwe
integer, public :: ld2we
integer, public :: ldwd
integer, public :: ld2wd
integer, public :: ldifx
integer, public :: ldscld
integer, public :: ldstpd
integer, public :: job_
integer, public :: ndigit_
integer, public :: maxit_
integer, public :: iprint_
integer, public :: lunerr_
integer, public :: lunrpt_
integer, public :: info_
integer, public :: lwork
integer, public :: liwork
integer, public :: info1_
integer, public :: info2_
integer, public :: info3_
integer, public :: info4_
integer, public :: info5_
integer, public :: ifixb_(np)
integer, public :: ifixx_(n,m)
real(kind=wp), public :: taufac_
real(kind=wp), public :: sstol_
real(kind=wp), public :: partol_
real(kind=wp), public :: lower_(np)
real(kind=wp), public :: we_(n,nq,nq)
real(kind=wp), public :: wd_(n,m,m)
real(kind=wp), public :: stpb_(np)
real(kind=wp), public :: stpd_(n,m)
real(kind=wp), public :: sclb_(np)
real(kind=wp), public :: scld_(n,m)
real(kind=wp), public :: upper_(np)
real(kind=wp), public :: wd1(1,1,1)
real(kind=wp), public, allocatable :: tempret(:,:)
real(kind=wp), public, allocatable, target :: work_local(:)
real(kind=wp), public, pointer :: work_(:)
integer, public, allocatable, target :: iwork_local(:)
integer, public, pointer :: iwork_(:)
logical, public :: head
logical, public :: isodr
logical, public :: restart

Source Code

   impure subroutine odr &
      (fcn, &
       n, m, np, nq, &
       beta, &
       y, x, &
       delta, &
       we, wd, &
       ifixb, ifixx, &
       job, ndigit, taufac, &
       sstol, partol, maxit, &
       iprint, lunerr, lunrpt, &
       stpb, stpd, &
       sclb, scld, &
       work, iwork, &
       info, &
       lower, upper)
   !! Driver routine for finding the weighted explicit or implicit orthogonal distance
   !! regression (ODR) or ordinary linear or nonlinear least squares (OLS) solution.
      ! Date Written:   860529   (YYMMDD)
      ! Revision Date:  20040301 (YYYYMMDD)
      ! Category No.:  G2E,I1B1
      ! Keywords:  Orthogonal distance regression,
      !   Nonlinear least squares,
      !   Measurement error models,
      !   Errors in variables
      ! Authors:
      !   Boggs, Paul T.
      !     Applied and Computational Mathematics Division
      !     National Institute of Standards and Technology
      !     Gaithersburg, MD 20899
      !   Byrd, Richard H.
      !     Department of Computer Science
      !     University of Colorado, Boulder, CO 80309
      !   Rogers, Janet E.
      !     Applied and Computational Mathematics Division
      !     National Institute of Standards and Technology
      !     Boulder, CO 80303-3328
      !   Schnabel, Robert B.
      !     Department of Computer Science
      !     University of Colorado, Boulder, CO 80309
      !     and
      !     Applied and Computational Mathematics Division
      !     National Institute of Standards and Technology
      !     Boulder, CO 80303-3328
      ! Purpose:  REAL(wp) driver routine for finding the weighted explicit or implicit
      !   orthogonal distance regression (ODR) or ordinary linear or nonlinear least squares (OLS)
      !   solution (long call statement)
      ! Description:
      !   For details, see ODRPACK95 User's Reference Guide.
      ! References:
      !   Boggs, P. T., R. H. Byrd, J. R. Donaldson, and R. B. Schnabel (1989),
      !     "Algorithm 676 --- ODRPACK: Software for Weighted Orthogonal Distance Regression,"
      !     ACM Trans. Math. Software., 15(4):348-364.
      !       Boggs, P. T., R. H. Byrd, J. E. Rogers, and
      !   R. B. Schnabel (1992),
      !     "User's Reference Guide for ODRPACK Version 2.01,
      !     Software for Weighted Orthogonal Distance Regression,"
      !     National Institute of Standards and Technology
      !     Internal Report Number 92-4834.
      !  Boggs, P. T., R. H. Byrd, and R. B. Schnabel (1987),
      !    "A Stable and Efficient Algorithm for Nonlinear Orthogonal Distance Regression,"
      !    SIAM J. Sci. Stat. Comput., 8(6):1052-1078.

      use odrpack_kinds, only: negone, zero
      use odrpack_core, only: fcn_t
      use odrpack_reports, only: dodphd, dodpe1

      procedure(fcn_t) :: fcn
         !! User-supplied subroutine for evaluating the model.
      integer, intent(in) :: n
         !! Number of observations.
      integer, intent(in) :: m
         !! Number of columns of data in the independent variable.
      integer, intent(in) :: np
         !! Number of function parameters.
      integer, intent(in) :: nq
         !! Number of responses per observation.
      real(wp), intent(inout) :: beta(:)
         !! Function parameters. `Shape: (np)`.
      real(wp), intent(in) :: y(:, :)
         !! Dependent variable. `Shape: (n, nq)`. Unused when the model is implicit.
      real(wp), intent(in) :: x(:, :)
         !! Explanatory variable. `Shape: (n, m)`.
      real(wp), intent(inout), optional :: delta(:, :)
         !! Error in the `x` data. `Shape: (n, m)`. Initial guess on input and estimated value
         !! on output.
      real(wp), intent(in), optional :: we(:, :, :)
         !! `epsilon` weights. `Shape: (1<=ldwe<=n, 1<=ld2we<=nq, nq)`. See p. 25.
      real(wp), intent(in), optional :: wd(:, :, :)
         !! `delta` weights. `Shape: (1<=ldwd<=n, 1<=ld2wd<=m, m)`. See p. 26.
      integer, intent(in), optional :: ifixb(:)
         !! Values designating whether the elements of `beta` are fixed at their input values
         !! or not. `Shape: (np)`.
      integer, intent(in), optional :: ifixx(:, :)
         !! Values designating whether the elements of `x` are fixed at their input values
         !! or not. `Shape: (1<=ldifx<=n, m)`. See p. 27.
      integer, intent(in), optional :: job
         !! Variable controlling problem initialization and computational method.
      integer, intent(in), optional :: ndigit
         !! Number of accurate digits in the function results, as supplied by the user.
      real(wp), intent(in), optional :: taufac
         !! Factor used to compute the initial trust region diameter.
      real(wp), intent(in), optional :: sstol
         !! Sum-of-squares convergence stopping tolerance.
      real(wp), intent(in), optional :: partol
      !! Parameter convergence stopping tolerance.
      integer, intent(in), optional :: maxit
         !! Maximum number of iterations allowed.
      integer, intent(in), optional :: iprint
         !! Print control variable.
      integer, intent(in), optional :: lunerr
         !! Logical unit number for error messages. Available options are:
         !!   0 => no output. 
         !!   6 => output to standard error.
         !!   other => output to logical unit number `lunerr`.  
      integer, intent(in), optional :: lunrpt
         !! Logical unit number for computation reports. Available options are:
         !!   0 => no output. 
         !!   6 => output to standard error.
         !!   other => output to logical unit number `lunrpt`.  
      real(wp), intent(in), optional :: stpb(:)
         !! Relative step for computing finite difference derivatives with respect to `beta`.
         !! `Shape: (np)`.
      real(wp), intent(in), optional :: stpd(:, :)
         !! Relative step for computing finite difference derivatives with respect to `delta`.
         !! `Shape: (1<=ldstpd<=n, m)`. See p. 31.
      real(wp), intent(in), optional :: sclb(:)
      !! Scaling values for `beta`. `Shape: (np)`.
      real(wp), intent(in), optional :: scld(:, :)
         !! Scaling values for `delta`. `Shape: (1<=ldscld<=n, m)`. See p. 32.
      real(wp), intent(inout), optional, target :: work(:)
         !! Real work space.
      integer, intent(inout), optional, target :: iwork(:)
         !! Integer work space.
      integer, intent(out), optional :: info
         !! Variable designating why the computations were stopped.
      real(wp), intent(in), optional :: lower(:)
         !! Lower bound on `beta`. `Shape: (np)`.
      real(wp), intent(in), optional :: upper(:)
         !! Upper bound on `beta`. `Shape: (np)`.

      ! Local variables
      integer :: ldwe, ld2we, ldwd, ld2wd, ldifx, ldscld, ldstpd, job_, ndigit_, maxit_, &
                 iprint_, lunerr_, lunrpt_, info_, lwork, liwork, info1_, info2_, info3_, &
                 info4_, info5_
      integer :: ifixb_(np), ifixx_(n, m)
      real(wp) :: taufac_, sstol_, partol_
      real(wp) :: lower_(np), we_(n, nq, nq), wd_(n, m, m), stpb_(np), stpd_(n, m), &
                  sclb_(np), scld_(n, m), upper_(np), wd1(1, 1, 1)
      real(wp), allocatable :: tempret(:, :)

      real(wp), allocatable, target :: work_local(:)
      real(wp), pointer :: work_(:)
      integer, allocatable, target :: iwork_local(:)
      integer, pointer :: iwork_(:)

      logical :: head, isodr, restart

      ! Set LINFO to zero indicating no errors have been found thus far
      info_ = 0
      info1_ = 0
      info2_ = 0
      info3_ = 0
      info4_ = 0
      info5_ = 0

      ! Set all scalar variable defaults except JOB
      ldwe = 1
      ld2we = 1
      ldwd = 1
      ld2wd = 1
      ldifx = 1
      ldscld = 1
      ldstpd = 1
      iprint_ = -1
      lunerr_ = 6
      lunrpt_ = 6
      maxit_ = -1
      ndigit_ = -1
      partol_ = negone
      sstol_ = negone
      taufac_ = negone
      head = .true.

      !  Check for the option arguments for printing (so error messages can be
      !  printed appropriately from here on out
      if (present(iprint)) then
         iprint_ = iprint
      end if

      if (present(lunrpt)) then
         lunrpt_ = lunrpt
      end if
      if (lunrpt_ == 6) then
         lunrpt_ = output_unit
      end if

      if (present(lunerr)) then
         lunerr_ = lunerr
      end if
      if (lunerr_ == 6) then
         lunerr_ = error_unit
      end if

      ! Ensure the problem size is valid
      if (n <= 0) then
         info5_ = 1
         info4_ = 1
      end if

      if (m <= 0) then
         info5_ = 1
         info3_ = 1
      end if

      if (np <= 0) then
         info5_ = 1
         info2_ = 1
      end if

      if (nq <= 0) then
         info5_ = 1
         info1_ = 1
      end if

      if (info5_ /= 0) then
         info_ = 10000*info5_ + 1000*info4_ + 100*info3_ + 10*info2_ + info1_
         if (lunerr_ /= 0 .and. iprint_ /= 0) then
            call dodphd(head, lunrpt_)
            call dodpe1( &
               lunerr_, info_, info5_, info4_, info3_, info2_, info1_, &
               n, m, nq, &
               ldscld, ldstpd, ldwe, ld2we, ldwd, ld2wd, &
               lwork, liwork)
         end if
         if (present(info)) then
            info = info_
         end if
         return
      end if

      ! Define LJOB and check that necessary arguments are passed for JOB
      if (present(job)) then
         job_ = job
         if (mod(job, 10000)/1000 >= 1) then
            if (.not. present(delta)) then
               info5_ = 7
               info4_ = 1
            end if
         end if
         if (job >= 10000) then
            if (.not. present(iwork)) then
               info5_ = 7
               info2_ = 1
            end if
            if (.not. present(work)) then
               info5_ = 7
               info3_ = 1
            end if
         end if
      else
         job_ = -1
      end if

      if (info5_ /= 0) then
         info_ = 10000*info5_ + 1000*info4_ + 100*info3_ + 10*info2_ + info1_
         if (lunerr_ /= 0 .and. iprint_ /= 0) then
            call dodphd(head, lunrpt_)
            call dodpe1( &
               lunerr_, info_, info5_, info4_, info3_, info2_, info1_, &
               n, m, nq, &
               ldscld, ldstpd, ldwe, ld2we, ldwd, ld2wd, &
               lwork, liwork)
         end if
         if (present(info)) then
            info = info_
         end if
         return
      end if

      ! Determine the size of the work arrays
      isodr = (job_ < 0 .or. mod(job_, 10) <= 1)
      call workspace_dimensions(n, m, np, nq, isodr, lwork, liwork)
      
      ! Allocate the local work arrays, if not provided by user
      ! The complementary case is treated below, because of the way the info flags are designed 
      if (.not. present(iwork)) then
         allocate (iwork_local(liwork), stat=info2_)
         iwork_ => iwork_local
      end if

      if (.not. present(work)) then
         allocate (work_local(lwork), stat=info3_)
         work_ => work_local
      end if
     
      allocate (tempret(max(n, np), max(nq, m)), stat=info4_)

      if (info4_ /= 0 .or. info3_ /= 0 .or. info2_ /= 0) then
         info5_ = 8
      end if

      if (info5_ /= 0) then
         info_ = 10000*mod(info5_, 10) + 1000*mod(info4_, 10) + &
                 100*mod(info3_, 10) + 10*mod(info2_, 10) + mod(info1_, 10)
         if (lunerr_ /= 0 .and. iprint_ /= 0) then
            call dodphd(head, lunrpt_)
            call dodpe1( &
               lunerr_, info_, info5_, info4_, info3_, info2_, info1_, &
               n, m, nq, &
               ldscld, ldstpd, ldwe, ld2we, ldwd, ld2wd, &
               lwork, liwork)
         end if
         if (present(info)) then
            info = info_
         end if
         return
      end if

      ! Set internal array variable defaults except IWORK and WORK
      ifixb_(1) = -1
      ifixx_(1, 1) = -1
      lower_(1:np) = -huge(zero)
      sclb_(1) = negone
      scld_(1, 1) = negone
      stpb_(1) = negone
      stpd_(1, 1) = negone
      upper_(1:np) = huge(zero)
      we_(1, 1, 1) = negone
      wd_(1, 1, 1) = negone

      ! Check the size of required arguments and return errors if they are too small
      if (size(beta) < np) then
         info1_ = info1_ + 1
      end if

      if (any(size(y) < [n, nq])) then
         info1_ = info1_ + 2
      end if

      if (any(size(x) < [n, m])) then
         info1_ = info1_ + 4
      end if

      ! Check the presence of optional arguments and copy their values internally or
      ! report errors as necessary
      if (present(ifixb)) then
         if (size(ifixb) < np) then
            info1_ = info1_ + 64
         end if
         if (ifixb(1) < 0) then
            ifixb_(1) = ifixb(1)
         else
            ifixb_(1:np) = ifixb(1:np)
         end if
      end if

      if (present(ifixx)) then
         ldifx = size(ifixx, 1)
         if (any(size(ifixx) <= [0, 0])) then
            info1_ = info1_ + 128
         end if
         if (.not. (ifixx(1, 1) < 0 .or. ldifx == 1 .or. ldifx >= n) &
             .or. size(ifixx, 2) < m) then
            info1_ = info1_ + 128
         end if
         if (ldifx > n) then
            ldifx = n
         end if
         if (ifixx(1, 1) < 0) then
            ifixx_(1, 1) = ifixx(1, 1)
         else
            ifixx_(1:ldifx, 1:m) = ifixx(1:ldifx, 1:m)
         end if
      end if
    
      if (present(iwork)) then
         if (size(iwork) >= liwork) then
            iwork_ => iwork(1:liwork)
         else
             info1_ = info1_ + 8192           
         end if
      end if

      if (present(maxit)) then
         maxit_ = maxit
      end if

      if (present(ndigit)) then
         ndigit_ = ndigit
      end if

      if (present(partol)) then
         partol_ = partol
      end if

      if (present(sclb)) then
         if (size(sclb) < np) then
            info1_ = info1_ + 1024
         end if
         if (sclb(1) <= zero) then
            sclb_(1) = sclb(1)
         else
            sclb_(1:np) = sclb(1:np)
         end if
      end if

      if (present(scld)) then
         ldscld = size(scld, 1)
         if (any(size(scld) <= [0, 0])) then
            info1_ = info1_ + 2048
         end if
         if (.not. (scld(1, 1) <= zero .or. ldscld == 1 .or. ldscld >= n) &
             .or. size(scld, 2) < m) then
            info1_ = info1_ + 2048
         end if
         if (ldscld > n) then
            ldscld = n
         end if
         if (scld(1, 1) <= zero) then
            scld_(1, 1) = scld(1, 1)
         else
            scld_(1:ldscld, 1:m) = scld(1:ldscld, 1:m)
         end if
      end if

      if (present(sstol)) then
         sstol_ = sstol
      end if

      if (present(stpb)) then
         if (size(stpb) < np) then
            info1_ = info1_ + 256
         end if
         if (stpb(1) <= zero) then
            stpb_(1) = stpb(1)
         else
            stpb_(1:np) = stpb(1:np)
         end if
      end if

      if (present(stpd)) then
         ldstpd = size(stpd, 1)
         if (any(size(stpd) <= [0, 0])) then
            info1_ = info1_ + 512
         end if
         if (.not. (stpd(1, 1) <= zero .or. ldstpd == 1 .or. ldstpd >= n) &
             .or. size(stpd, 2) < m) then
            info1_ = info1_ + 512
         end if
         if (ldstpd > n) then
            ldstpd = n
         end if
         if (stpd(1, 1) <= zero) then
            stpd_(1, 1) = stpd(1, 1)
         else
            stpd_(1:ldstpd, 1:m) = stpd(1:ldstpd, 1:m)
         end if
      end if

      if (present(taufac)) then
         taufac_ = taufac
      end if

      if (present(we)) then
         ldwe = size(we, 1)
         ld2we = size(we, 2)
         if (any(size(we) <= [0, 0, 0])) then
            info1_ = info1_ + 16
         end if
         if (.not. (we(1, 1, 1) < zero .or. &
                    ((ldwe == 1 .or. ldwe >= n) .and. &
                     (ld2we == 1 .or. ld2we >= nq))) .or. size(we, 3) < nq) then
            info1_ = info1_ + 16
         end if
         if (ldwe > n) then
            ldwe = n
         end if
         if (ld2we > nq) then
            ld2we = nq
         end if
         if (we(1, 1, 1) < zero) then
            we_(1, 1, 1) = we(1, 1, 1)
         else
            we_(1:ldwe, 1:ld2we, 1:nq) = we(1:ldwe, 1:ld2we, 1:nq)
         end if
      end if

      if (present(wd)) then
         ldwd = size(wd, 1)
         ld2wd = size(wd, 2)
         if (any(size(wd) <= [0, 0, 0])) then
            info1_ = info1_ + 32
         end if
         if (.not. (wd(1, 1, 1) < zero .or. &
                    ((ldwd == 1 .or. ldwd >= n) .and. &
                     (ld2wd == 1 .or. ld2wd >= m))) .or. size(wd, 3) < m) then
            info1_ = info1_ + 32
         end if
         if (ldwd > n) then
            ldwd = n
         end if
         if (ld2wd > m) then
            ld2wd = m
         end if
         if (wd(1, 1, 1) <= zero) then
            wd_(1, 1, 1) = wd(1, 1, 1)
         else
            wd_(1:ldwd, 1:ld2wd, 1:m) = wd(1:ldwd, 1:ld2wd, 1:m)
         end if
      end if

      if (present(work)) then
         if (size(work) >= lwork) then
            work_ => work(1:lwork)
         else
            info1_ = info1_ + 4096
         end if
      end if

      restart = (mod(job_/10000, 10) >= 1)
      if (.not. restart) then
         work_ = zero
         iwork_ = 0
      end if

      if (present(delta) .and. (.not. restart)) then
         if (any(shape(delta) < [n, m])) then
            info1_ = info1_ + 8
         end if
         work_(1:n*m) = reshape(delta(1:n, 1:m), [n*m])
      end if

      if (present(lower)) then
         if (size(lower) < np) then
            info1_ = info1_ + 32768
         end if
         lower_(1:np) = lower(1:np)
      end if

      if (present(upper)) then
         if (size(upper) < np) then
            info1_ = info1_ + 16384
         end if
         upper_(1:np) = upper(1:np)
      end if

      ! Report an error if any of the array sizes didn't match.
      if (info1_ /= 0) then
         info_ = 100000 + info1_
         info1_ = 0
         if (lunerr_ /= 0 .and. iprint_ /= 0) then
            call dodphd(head, lunrpt_)
            call dodpe1( &
               lunerr_, info_, info5_, info4_, info3_, info2_, info1_, &
               n, m, nq, &
               ldscld, ldstpd, ldwe, ld2we, ldwd, ld2wd, &
               lwork, liwork)
         end if
         if (present(info)) then
            info = info_
         end if
         return
      end if

      if (wd_(1, 1, 1) /= 0) then
         call dodcnt &
            (fcn, &
             n, m, np, nq, &
             beta(1:np), &
             y(1:n, 1:nq), n, x(1:n, 1:m), n, &
             we_(1:ldwe, 1:ld2we, 1:nq), ldwe, ld2we, &
             wd_(1:ldwd, 1:ld2wd, 1:m), ldwd, ld2wd, &
             ifixb_, ifixx_(1:ldifx, 1:m), ldifx, &
             job_, ndigit_, taufac_, &
             sstol_, partol_, maxit_, &
             iprint_, lunerr_, lunrpt_, &
             stpb_, stpd_(1:ldstpd, 1:m), ldstpd, &
             sclb_, scld_(1:ldscld, 1:m), ldscld, &
             work_, lwork, tempret, iwork_, liwork, &
             info_, &
             lower_, upper_)
      else
         wd1(1, 1, 1) = negone
         call dodcnt &
            (fcn, &
             n, m, np, nq, &
             beta(1:np), &
             y(1:n, 1:nq), n, x(1:n, 1:m), n, &
             we_(1:ldwe, 1:ld2we, 1:nq), ldwe, ld2we, &
             wd1, 1, 1, &
             ifixb_, ifixx_(1:ldifx, 1:m), ldifx, &
             job_, ndigit_, taufac_, &
             sstol_, partol_, maxit_, &
             iprint_, lunerr_, lunrpt_, &
             stpb_, stpd_(1:ldstpd, 1:m), ldstpd, &
             sclb_, scld_(1:ldscld, 1:m), ldscld, &
             work_, lwork, tempret, iwork_, liwork, &
             info_, &
             lower_, upper_)
      end if

      if (present(delta)) then
         delta(1:n, 1:m) = reshape(work_(1:n*m), [n, m])
      end if

      if (present(info)) then
         info = info_
      end if

   end subroutine odr