|
4 | 4 |
|
5 | 5 | module test_stdlib_math
|
6 | 6 | use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test
|
7 |
| - use stdlib_math, only: clip |
| 7 | + use stdlib_math, only: clip, is_close, all_close |
8 | 8 | use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp
|
9 | 9 | implicit none
|
10 | 10 |
|
@@ -32,6 +32,14 @@ contains
|
32 | 32 | new_unittest("clip-real-double-bounds", test_clip_rdp_bounds), &
|
33 | 33 | new_unittest("clip-real-quad", test_clip_rqp), &
|
34 | 34 | new_unittest("clip-real-quad-bounds", test_clip_rqp_bounds) &
|
| 35 | + |
| 36 | + !> Tests for `is_close` and `all_close` |
| 37 | + #:for k1 in REAL_KINDS |
| 38 | + , new_unittest("is_close-real-${k1}$", test_is_close_real_${k1}$) & |
| 39 | + , new_unittest("is_close-cmplx-${k1}$", test_is_close_cmplx_${k1}$) & |
| 40 | + , new_unittest("all_close-real-${k1}$", test_all_close_real_${k1}$) & |
| 41 | + , new_unittest("all_close-cmplx-${k1}$", test_all_close_cmplx_${k1}$) & |
| 42 | + #:endfor |
35 | 43 | ]
|
36 | 44 |
|
37 | 45 | end subroutine collect_stdlib_math
|
@@ -203,6 +211,89 @@ contains
|
203 | 211 | #:endif
|
204 | 212 |
|
205 | 213 | end subroutine test_clip_rqp_bounds
|
| 214 | + |
| 215 | + #:for k1 in REAL_KINDS |
| 216 | + subroutine test_is_close_real_${k1}$(error) |
| 217 | + type(error_type), allocatable, intent(out) :: error |
| 218 | + real(${k1}$) :: x, NAN |
| 219 | + x = -3; NAN = sqrt(x) |
| 220 | + |
| 221 | + call check(error, is_close(2.5_${k1}$, 2.5_${k1}$), .true.) |
| 222 | + if (allocated(error)) return |
| 223 | + call check(error, is_close(0.0_${k1}$, -0.0_${k1}$), .true.) |
| 224 | + if (allocated(error)) return |
| 225 | + call check(error, is_close(2.5_${k1}$, 1.2_${k1}$), .false.) |
| 226 | + if (allocated(error)) return |
| 227 | + call check(error, is_close(NAN, NAN), .false.) |
| 228 | + if (allocated(error)) return |
| 229 | + call check(error, is_close(NAN, 0.0_${k1}$), .false.) |
| 230 | + if (allocated(error)) return |
| 231 | + call check(error, is_close(NAN, NAN, equal_nan=.true.), .true.) |
| 232 | + |
| 233 | + end subroutine test_is_close_real_${k1}$ |
| 234 | + |
| 235 | + subroutine test_is_close_cmplx_${k1}$(error) |
| 236 | + type(error_type), allocatable, intent(out) :: error |
| 237 | + real(${k1}$) :: x, NAN |
| 238 | + x = -3; NAN = sqrt(x) |
| 239 | + |
| 240 | + call check(error, is_close((2.5_${k1}$, 1.5_${k1}$), (2.5_${k1}$, 1.5_${k1}$)), .true.) |
| 241 | + if (allocated(error)) return |
| 242 | + call check(error, is_close((2.5_${k1}$, 1.2_${k1}$), (2.5_${k1}$, 1.5_${k1}$)), .false.) |
| 243 | + if (allocated(error)) return |
| 244 | + call check(error, is_close(cmplx(NAN, NAN, ${k1}$), cmplx(NAN, NAN, ${k1}$)), .false.) |
| 245 | + if (allocated(error)) return |
| 246 | + call check(error, is_close(cmplx(NAN, NAN, ${k1}$), cmplx(NAN, 0.0_${k1}$, ${k1}$)), .false.) |
| 247 | + if (allocated(error)) return |
| 248 | + call check(error, is_close(cmplx(NAN, NAN, ${k1}$), cmplx(NAN, NAN, ${k1}$), equal_nan=.true.), .true.) |
| 249 | + if (allocated(error)) return |
| 250 | + call check(error, is_close(cmplx(NAN, 1.2_${k1}$, ${k1}$), cmplx(NAN, 1.2_${k1}$, ${k1}$), equal_nan=.true.), .true.) |
| 251 | + |
| 252 | + end subroutine test_is_close_cmplx_${k1}$ |
| 253 | + |
| 254 | + subroutine test_all_close_real_${k1}$(error) |
| 255 | + type(error_type), allocatable, intent(out) :: error |
| 256 | + real(${k1}$) :: x(2, 2), eps, NAN |
| 257 | + x = 1; eps = -3; NAN = sqrt(eps) |
| 258 | + |
| 259 | + eps = sqrt(epsilon(1.0_${k1}$)) |
| 260 | + |
| 261 | + call check(error, all_close(x, x), .true.) |
| 262 | + if (allocated(error)) return |
| 263 | + call check(error, all_close(x + x*eps + 1.0e-6, x), .false.) |
| 264 | + if (allocated(error)) return |
| 265 | + call check(error, all_close(x + NAN, x), .false.) |
| 266 | + if (allocated(error)) return |
| 267 | + call check(error, all_close(x + NAN, x, equal_nan=.true.), .false.) |
| 268 | + if (allocated(error)) return |
| 269 | + call check(error, all_close(x + NAN, x + NAN), .false.) |
| 270 | + if (allocated(error)) return |
| 271 | + call check(error, all_close(x + NAN, x + NAN, equal_nan=.true.), .true.) |
| 272 | + |
| 273 | + end subroutine test_all_close_real_${k1}$ |
| 274 | + |
| 275 | + subroutine test_all_close_cmplx_${k1}$(error) |
| 276 | + type(error_type), allocatable, intent(out) :: error |
| 277 | + real(${k1}$) :: eps, NAN |
| 278 | + complex(${k1}$) :: x(2, 2) |
| 279 | + x = (1, 1); eps = -3; NAN = sqrt(eps) |
| 280 | + |
| 281 | + eps = sqrt(epsilon(1.0_${k1}$)) |
| 282 | + |
| 283 | + call check(error, all_close(x, x), .true.) |
| 284 | + if (allocated(error)) return |
| 285 | + call check(error, all_close(x + x*eps + 1.0e-6, x), .false.) |
| 286 | + if (allocated(error)) return |
| 287 | + call check(error, all_close(x + cmplx(NAN, NAN, ${k1}$), x), .false.) |
| 288 | + if (allocated(error)) return |
| 289 | + call check(error, all_close(x + cmplx(NAN, NAN, ${k1}$), x, equal_nan=.true.), .false.) |
| 290 | + if (allocated(error)) return |
| 291 | + call check(error, all_close(x + cmplx(NAN, NAN, ${k1}$), x + cmplx(NAN, NAN, ${k1}$), equal_nan=.true.), .true.) |
| 292 | + if (allocated(error)) return |
| 293 | + call check(error, all_close(x + cmplx(NAN, NAN, ${k1}$), x + cmplx(NAN, NAN, ${k1}$)), .false.) |
| 294 | + |
| 295 | + end subroutine test_all_close_cmplx_${k1}$ |
| 296 | + #:endfor |
206 | 297 |
|
207 | 298 | end module test_stdlib_math
|
208 | 299 |
|
|
0 commit comments