43 #include "../base/base_uses.f90"
49 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'minimax_exp'
51 INTEGER,
PARAMETER :: mm_k15 = 0, mm_k53 = 1
101 INTEGER,
INTENT(IN) :: k
102 REAL(kind=
dp),
INTENT(IN) :: rc
103 INTEGER,
INTENT(OUT) :: ierr
109 IF (k .GT.
k_max) ierr = -1
127 INTEGER,
INTENT(IN) :: k
128 REAL(kind=
dp),
INTENT(IN) :: rc
129 REAL(kind=
dp),
DIMENSION(2*k),
INTENT(OUT) :: aw
130 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: mm_error
131 INTEGER,
INTENT(OUT),
OPTIONAL :: which_coeffs
137 IF (ierr .EQ. 1)
THEN
138 CALL get_minimax_coeff_k53(k, rc, aw, mm_error)
139 IF (
PRESENT(which_coeffs)) which_coeffs = mm_k53
141 cpassert(ierr .EQ. 0)
143 IF (
PRESENT(which_coeffs)) which_coeffs = mm_k15
145 ELSEIF (k .LE. 53)
THEN
146 CALL get_minimax_coeff_k53(k, rc, aw, mm_error)
147 IF (
PRESENT(which_coeffs)) which_coeffs = mm_k53
149 cpabort(
"No minimax approximations available for k = "//cp_to_string(k))
162 SUBROUTINE get_minimax_coeff_k53(k, Rc, aw, mm_error)
163 INTEGER,
INTENT(IN) :: k
164 REAL(kind=
dp),
INTENT(IN) :: rc
165 REAL(kind=
dp),
DIMENSION(2*k),
INTENT(OUT) :: aw
166 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: mm_error
170 CALL get_best_minimax_approx_k53(k, rc, i_mm)
174 END SUBROUTINE get_minimax_coeff_k53
184 SUBROUTINE get_best_minimax_approx_k53(k, Rc, i_mm, ge_Rc)
185 INTEGER,
INTENT(IN) :: k
186 REAL(kind=
dp),
INTENT(IN) :: rc
187 INTEGER,
INTENT(OUT) :: i_mm
188 LOGICAL,
INTENT(IN),
OPTIONAL :: ge_rc
190 INTEGER :: i, i_k, i_l, i_r
191 REAL(kind=
dp) :: error_l, error_r, r_k_max, r_k_min
192 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: aw
194 cpassert(k .LE.
k_max)
198 DO WHILE (
k_mm(
k_p(i_k)) .LT. k)
201 cpassert(
k_mm(
k_p(i_k)) .EQ. k)
204 r_k_max =
r_mm(
k_p(i_k + 1) - 1)
206 IF (rc .GE. r_k_max)
THEN
207 i_mm =
k_p(i_k + 1) - 1
208 ELSE IF (rc .LE. r_k_min)
THEN
212 DO WHILE (rc .GT.
r_mm(i))
218 IF (
PRESENT(ge_rc))
THEN
225 ALLOCATE (aw(2*
k_mm(i_r)))
229 ALLOCATE (aw(2*
k_mm(i_l)))
233 i_mm = merge(i_r, i_l, error_l .LE. error_r)
236 END SUBROUTINE get_best_minimax_approx_k53
246 INTEGER,
INTENT(IN) :: n_r, iw
248 INTEGER :: i_mm, i_r, ierr, k, which_coeffs
250 REAL(kind=
dp) :: dr, mm_error, r, ref_error
251 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: aw
254 WRITE (iw,
'(//T2,A)') &
255 "Unit tests for minimax 1/x ~ SUM_{i}^{K} w_i EXP(-a_i * x) for x belonging to [1:Rc]"
256 WRITE (iw,
'(T2,84("*"))')
260 WRITE (iw,
'(/T2,A)') &
261 "1) checking numerical error against tabulated error at tabulated values Rc"
262 WRITE (iw,
'(/T2,A)') &
263 "which coeffs, K, Rc, num. error, ref. error, rel. diff (num. error - ref. error)/(ref. error)"
264 WRITE (iw,
'(T2,54("-"))')
270 IF (ierr .EQ. 0)
THEN
275 IF (iw > 0)
WRITE (iw,
'(T2,A4, I3, ES10.1, ES12.3, ES12.3, ES12.3)') &
276 merge(
"k15",
"k53", which_coeffs .EQ. mm_k15), k, r, &
277 mm_error, ref_error, (mm_error - ref_error)/ref_error
278 cpassert(mm_error .LE. ref_error*1.05_dp + 1.0e-15_dp)
280 IF (iw > 0)
WRITE (iw,
'(T2,A4, I3, ES10.1, 3X, A)')
"k15", k, r,
"missing"
285 CALL get_minimax_coeff_k53(k, r, aw, mm_error)
288 IF (iw > 0)
WRITE (iw,
'(T2,A4,I3, ES10.1, ES12.3, ES12.3, ES12.3)') &
289 "k53", k, r, mm_error, ref_error, (mm_error - ref_error)/ref_error
290 IF (mm_error .GT. ref_error*1.05_dp + 1.0e-15_dp)
THEN
291 cpabort(
"Test 1 failed: numerical error is larger than tabulated error")
296 IF (iw > 0 .AND. n_r .GT. 0)
THEN
297 WRITE (iw,
'(T2,54("-"))')
298 WRITE (iw,
'(/T2,A)')
"Test 1 OK"
299 WRITE (iw,
'(/T2,A)') &
300 "2) checking numerical error against tabulated error at arbitrary values Rc"
301 WRITE (iw,
'(/T2,A)') &
302 "which coeffs, K, Rc, num. error, ref. error, rel. diff (num. error - ref. error)/(ref. error)"
303 WRITE (iw,
'(T2,54("-"))')
305 dr =
r_max**(1.0_dp/n_r)
313 CALL get_best_minimax_approx_k53(k, r, i_mm, ge_rc=.true.)
314 IF (r .GT.
r_mm(i_mm))
THEN
319 IF (iw > 0)
WRITE (iw,
'(T2, A4, I3, ES10.1, ES12.3, ES12.3, ES12.3)') &
320 merge(
"k15",
"k53", which_coeffs .EQ. mm_k15), k, r, &
321 mm_error, ref_error, (mm_error - ref_error)/ref_error
322 IF (mm_error .GT. ref_error*1.05_dp + 1.0e-15_dp)
THEN
323 cpabort(
"Test 2 failed: numerical error is larger than tabulated error")
330 WRITE (iw,
'(T2,54("-"))')
331 WRITE (iw,
'(/T2,A)')
"Test 2 OK"
various routines to log and control the output. The idea is that decisions about where to log should ...
Defines the basic variable types.
integer, parameter, public dp
Routines to calculate the minimax coefficients in order to approximate 1/x as a sum over exponential ...
subroutine, public get_minimax_coeff_k15(k, Rc, aw, mm_error)
Get minimax coefficients: k15 implementation (coefficients up to k=15 terms). All a_i and w_i have be...
subroutine, public check_range_k15(k, Rc, ierr)
Check that the range for the minimax approximation is not too small for the chosen number of integrat...
real(kind=dp) function, public get_minimax_numerical_error(Rc, aw)
Sample numerical error and return its maximum.
Routines to calculate the minimax coefficients in order to approximate 1/x as a sum over exponential ...
subroutine, public get_minimax_coeff_low(i, aw)
...
integer, parameter, public k_max
integer, dimension(n_approx), parameter, public k_mm
real(kind=dp), parameter, public r_max
integer, parameter, public n_approx
real(kind=dp), dimension(n_approx), parameter, public r_mm
integer, dimension(n_k+1), parameter, public k_p
real(kind=dp), dimension(n_approx), parameter, public err_mm
Routines to calculate the minimax coefficients in order to approximate 1/x as a sum over exponential ...
subroutine, public get_exp_minimax_coeff(k, Rc, aw, mm_error, which_coeffs)
Get best minimax approximation for given input parameters. Automatically chooses the most exact set o...
subroutine, public check_exp_minimax_range(k, Rc, ierr)
Check that a minimax approximation is available for given input k, Rc. ierr == 0: everything ok ierr ...
subroutine, public validate_exp_minimax(n_R, iw)
Unit test checking that numerical error of minimax approximations generated using any k15 or k53 coef...