1- module types
2- implicit none
3- private
4- public dp
5-
6- integer , parameter :: dp= kind (0d0 )
7-
8- end module
9-
101module find_fit_module
112
12- ! This module contains a general function find_fit() for a nonlinear least
13- ! squares fitting. The function can fit any nonlinear expression to any data.
3+ ! ! This module contains a general function find_fit() for a nonlinear least
4+ ! ! squares fitting. The function can fit any nonlinear expression to any data.
5+
6+ use minpack_module, only: wp, lmdif1
147
15- use minpack_module, only: lmdif1
16- use types, only: dp
178implicit none
9+
1810private
19- public find_fit
11+
12+ abstract interface
13+ function expr_f (x , pars ) result(y)
14+ import :: wp
15+ implicit none
16+ real (wp), intent (in ) :: x(:)
17+ real (wp), intent (in ) :: pars(:)
18+ real (wp) :: y(size (x))
19+ end function expr_f
20+ end interface
21+
22+ public :: find_fit
2023
2124contains
2225
@@ -26,71 +29,68 @@ subroutine find_fit(data_x, data_y, expr, pars)
2629! parameters 'pars' and it must return the evaluated expression on the
2730! array 'x'. The arrays 'data_x' and 'data_y' must have the same
2831! length.
29- real (dp), intent (in ) :: data_x(:), data_y(:)
30- interface
31- function expr (x , pars ) result(y)
32- use types, only: dp
33- implicit none
34- real (dp), intent (in ) :: x(:), pars(:)
35- real (dp) :: y(size (x))
36- end function
37- end interface
38- real (dp), intent (inout ) :: pars(:)
32+ real (wp), intent (in ) :: data_x(:)
33+ real (wp), intent (in ) :: data_y(:)
34+ procedure (expr_f) :: expr
35+ real (wp), intent (inout ) :: pars(:)
3936
40- real (dp ) :: tol, fvec(size (data_x))
37+ real (wp ) :: tol, fvec(size (data_x))
4138integer :: iwa(size (pars)), info, m, n
42- real (dp ), allocatable :: wa(:)
39+ real (wp ), allocatable :: wa(:)
4340
44- tol = sqrt (epsilon (1._dp ))
41+ tol = sqrt (epsilon (1.0_wp ))
4542m = size (fvec)
4643n = size (pars)
4744allocate (wa(m* n + 5 * n + m))
4845call lmdif1(fcn, m, n, pars, fvec, tol, info, iwa, wa, size (wa))
49- if (info /= 1 ) stop " failed to converge"
46+ if (info /= 1 ) error stop " failed to converge"
5047
5148contains
5249
53- subroutine fcn (m , n , x , fvec , iflag )
54- integer , intent (in ) :: m, n
55- integer , intent (inout ) :: iflag
56- real (dp) , intent (in ) :: x(n)
57- real (dp ), intent (out ) :: fvec(m )
58- ! Suppress compiler warning:
59- fvec(1 ) = iflag
60- fvec = data_y - expr(data_x, x)
61- end subroutine
50+ subroutine fcn (m , n , x , fvec , iflag )
51+ integer , intent (in ) :: m
52+ integer , intent (in ) :: n
53+ integer , intent (inout ) :: iflag
54+ real (wp ), intent (in ) :: x(n )
55+ real (wp), intent ( out ) :: fvec(m)
56+ fvec(1 ) = iflag ! Suppress compiler warning:
57+ fvec = data_y - expr(data_x, x)
58+ end subroutine fcn
6259
63- end subroutine
64-
65- end module
60+ end subroutine find_fit
6661
62+ end module find_fit_module
6763
6864program example_primes
6965
70- ! Find a nonlinear fit of the form a*x*log(b + c*x) to a list of primes.
66+ ! ! Find a nonlinear fit of the form ` a*x*log(b + c*x)` to a list of primes.
7167
7268use find_fit_module, only: find_fit
73- use types, only: dp
69+ use minpack_module, only: wp
70+ use iso_fortran_env, only: nwrite = > output_unit
71+
7472implicit none
7573
76- real (dp ) :: pars(3 )
77- real (dp ), parameter :: y(* ) = [2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , &
78- 37 , 41 , 43 , 47 , 53 , 59 , 61 , 67 , 71 ]
74+ real (wp ) :: pars(3 )
75+ real (wp ), parameter :: y(* ) = real ( [2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , &
76+ 37 , 41 , 43 , 47 , 53 , 59 , 61 , 67 , 71 ], wp)
7977integer :: i
80- pars = [1._dp , 1._dp , 1._dp ]
81- call find_fit([(real (i, dp), i= 1 ,size (y))], y, expression, pars)
82- print * , pars
78+ pars = [1.0_wp , 1.0_wp , 1.0_wp ]
79+ call find_fit([(real (i, wp), i= 1 ,size (y))], y, expression, pars)
80+
81+ write (nwrite, ' (1p,5x,a/(5x,3e15.7))' ) ' pars: ' ,pars
8382
8483contains
8584
8685function expression (x , pars ) result(y)
87- real (dp), intent (in ) :: x(:), pars(:)
88- real (dp) :: y(size (x))
89- real (dp) :: a, b, c
86+ real (wp), intent (in ) :: x(:)
87+ real (wp), intent (in ) :: pars(:)
88+ real (wp) :: y(size (x))
89+ real (wp) :: a, b, c
9090a = pars(1 )
9191b = pars(2 )
9292c = pars(3 )
9393y = a* x* log (b + c* x)
94- end function
94+ end function expression
9595
96- end program
96+ end program example_primes
0 commit comments