What goes in stdlib and what is separate?

OK so maybe what I did is somewhat opinionated. :slight_smile:

If you look more closely, you will see that brentq is not designed to be called directly. It鈥檚 only called though the higher-level class method solve (part of the root_solver class). opt-lib/stdlib_root_core.F90 at 0ce2825f87d511bc33764e0aadd3f3061c9c8ca6 路 jacobwilliams/opt-lib 路 GitHub
(the intent being not to duplicate code that is common to all methods).

What you are looking for is already there: opt-lib/stdlib_root_core.F90 at 0ce2825f87d511bc33764e0aadd3f3061c9c8ca6 路 jacobwilliams/opt-lib 路 GitHub

    subroutine root_scalar(method,fun,ax,bx,xzero,fzero,iflag,&
                           ftol,rtol,atol,maxiter,fax,fbx,bisect_on_failure)

    implicit none

    character(len=*),intent(in)   :: method   !! the method to use
    procedure(func2)              :: fun      !! user function to find the root of
    real(wp),intent(in)           :: ax       !! left endpoint of initial interval
    real(wp),intent(in)           :: bx       !! right endpoint of initial interval
    real(wp),intent(out)          :: xzero    !! abscissa approximating a zero of `f` in the interval `ax`,`bx`
    real(wp),intent(out)          :: fzero    !! value of `f` at the root (`f(xzero)`)
    integer,intent(out)           :: iflag    !! status flag (`-1`=error, `0`=root found, `-999`=invalid method)
    real(wp),intent(in),optional  :: ftol     !! absolute tolerance for `f=0`
    real(wp),intent(in),optional  :: rtol     !! relative tol for x
    real(wp),intent(in),optional  :: atol     !! absolute tol for x
    integer,intent(in),optional   :: maxiter  !! maximum number of iterations
    real(wp),intent(in),optional  :: fax      !! if `f(ax)` is already known, it can be input here
    real(wp),intent(in),optional  :: fbx      !! if `f(ax)` is already known, it can be input here
    logical,intent(in),optional   :: bisect_on_failure  !! if true, then if the specified method fails,
                                                        !! it will be retried using the bisection method.
                                                        !! (default is False). Note that this can use up
                                                        !! to `maxiter` additional function evaluations.

Which is called like so:

call root_scalar('brentq', func, ...)

So, this is the interface you want, I think. But notice that it is simply a wrapper to the object-oriented interface (and not vice versa). To me, the object-oriented interface is the real one, and this one is just a simple wrapper (that has some compromises under the hood since there is a class allocation that is happening, as well as a string comparison and case statement).

My intent is to add a speed test to the unit tests to see what the runtime overhead of this is and we can decide if it is OK or not. Nothing is set in stone right now.