(j3.2006) Why we should have kept macros

Van Snyder Van.Snyder
Wed Aug 20 17:51:36 EDT 2008


Here's an example of why we should have kept macros.

Richard Maine remarked about ten years ago that integrating type
parameters and type bound procedures would be problematical.  It is, at
least for kind type parameters.

I'd like to build a nonlinear solver using Fortran 2003 facilities.  I'd
like to use deferred type-bound procedures for each of the
problem-specific things, such as evaluating the function and Jacobian,
factoring the Jacobian, solving for the Newton move, etc.

I'd like to use a type parameter to specify whether the real components
are default real or double precision real.  I'd have two solvers, one
for default real and one for double precision real, probably created
from a single file using INCLUDE after some named constants got the
appropriate values.

I'd like to start with these abstract procedure definitions for the
procedures called by the solver when it needs access to user code

  abstract interface
    subroutine Action_D ( Argument )
      class(nonlinear_Base_T(kind(0.0d0))), intent(inout) :: Argument
    end subroutine Action
    subroutine Action_S ( Argument )
      class(nonlinear_Base_T(kind(0.0e0))), intent(inout) :: Argument
    end subroutine Action
  end interface

and with this abstract base type:

  type, abstract :: Nonlinear_Base_T ( Kind )
    integer, kind :: Kind
    real(kind) :: Cos_DX_DXL    ! Cosine of angle between consecutive
                                ! Newton moves
    real(kind) :: Cos_G_DX      ! Cosine of angle between the Gradient
                                ! and the Newton move
    real(kind) :: Minimum_Norm  ! Norm of F not in column space of J
    real(kind) :: Residual_Norm ! Norm of F
  contains
    ! Specific bindings for double precision
    procedure(action_D), pass, deferred :: Evaluate_F_D
    procedure(action_D), pass, deferred :: Evaluate_J_D
    procedure(action_D), pass, deferred :: Solve_D
    procedure(action_D), pass, deferred :: Do_Newton_Move_D
    procedure(action_D), pass, deferred :: Do_Gradient_Move_D
    ! Specific bindings for single precision
    procedure(action_S), pass, deferred :: Evaluate_F_S
    procedure(action_S), pass, deferred :: Evaluate_J_S
    procedure(action_S), pass, deferred :: Solve_S
    procedure(action_S), pass, deferred :: Do_Newton_Move_S
    procedure(action_S), pass, deferred :: Do_Gradient_Move_S
    ! Generic bindings
    generic :: Evaluate_F => Evaluate_F_D, Evaluate_F_S ! and Residual_Norm
    generic :: Evaluate_J => Evaluate_J_D, Evaluate_J_S ! and Minimum_Norm
    generic :: Solve => Solve_D, Solve_S                ! for Newton Move
    generic :: Do_Newton_Move => Do_Newton_Move_D, Do_Newton_Move_S
    generic :: Do_Gradient_Move => Do_Gradient_Move_D, Do_Gradient_Move_S
  end type Nonlinear_Base_T

The problem is that when I tell the user "Extend the base type and
provide concrete bindings for the deferred procedures," he has to
provide bindings for both default real and double precision real
versions of all the bindings.

Either macros or generic modules would have solved this problem.

Instead, I'm inclined to ignore kind type parameters and provide two
base types, one with default real components, and one with double
precision real components.  Instead of macros or generic modules, I'll
end up making imaginative use of INCLUDE.

-- 
Van Snyder                    |  What fraction of Americans believe 
Van.Snyder at jpl.nasa.gov       |  Wrestling is real and NASA is fake?
Any alleged opinions are my own and have not been approved or
disapproved by JPL, CalTech, NASA, the President, or anybody else.




More information about the J3 mailing list