Skip to content

Commit 1db5c72

Browse files
committed
add Measurement tests
1 parent 11f136d commit 1db5c72

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

numericalnim.nimble

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ task testDeps, "Install external dependencies required for tests":
1616
exec "nimble install https://github.com/SciNim/Measuremancer.git"
1717

1818
task test, "Run all tests":
19-
exec "nim c -r --experimental:unicodeOperators tests/test_integrate.nim"
19+
exec "nim c -r tests/test_integrate.nim"
2020
exec "nim c -r tests/test_interpolate.nim"
2121
exec "nim c -r tests/test_ode.nim"
2222
exec "nim c -r tests/test_optimize.nim"

tests/test_integrate.nim

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,3 +441,64 @@ test "cumGauss":
441441
correct.add optional["a"] * sin(x[i])
442442
for i in 0..correct.high:
443443
check abs(spline[i] - correct[i]) < 1e-6
444+
445+
import measuremancer
446+
suite "External integration tests: Measurement (Measuremancer) - integrating a complex type":
447+
## tests integration of a complex type, in this case `Measurement[T]`.
448+
449+
# define two procedure we can integrate over with different algorithms
450+
proc foo[T; U](x: U, ctx: NumContext[T, U]): T =
451+
result = exp(x / ctx["a"])
452+
453+
proc sinFo[T; U](x: U, ctx: NumContext[T, U]): T = sin(x)
454+
455+
# define a `Measurement`
456+
let a = measurement(4.71, 0.01) # we construct it with the proc instead of `±` to avoid having to
457+
# compile with `--experimental:unicodeOperators`, which is only available
458+
# from nim version 1.6
459+
type T = typeof(a) # its type for convenience
460+
var ctx = newNumContext[T, float]()
461+
ctx["a"] = a
462+
463+
var exp = measurement(14.995, 0.031231)
464+
template genTest(fn: untyped): untyped =
465+
test "Measurement: " & $astToStr(fn):
466+
let res = fn[T](foo, 1, 7, ctx = ctx)
467+
# very rough comparison is fine for this test. It's supposed to test functionality, not
468+
# exactness of the integration methods
469+
check abs(res.value - exp.value) < 1e-3
470+
check abs(res.error - exp.error) < 1e-3
471+
472+
genTest(simpson)
473+
genTest(trapz)
474+
genTest(romberg)
475+
genTest(gaussQuad)
476+
genTest(adaptiveSimpson)
477+
genTest(adaptiveGaussLocal)
478+
479+
test "Measurement: adaptiveGauss":
480+
# adaptive requires 2 generics
481+
let res = adaptiveGauss[T, float](foo, 1, 7, ctx = ctx)
482+
check abs(res.value - exp.value) < 1e-3
483+
check abs(res.error - exp.error) < 1e-3
484+
485+
486+
test "Measurement: adaptiveGauss in `Measurement` range":
487+
let b = measurement(6.42, 0.03)
488+
block SameVar:
489+
# we integrate from `b` to `b`, that means (due to the nature of
490+
# sin) our uncertainty should vanish. The value of the integration
491+
# is =~= 0 too of course
492+
let res = adaptiveGauss[T, T](sinFo, -b, b)
493+
let exp = measurement(7.23e-17, 1.0065e-18)
494+
check abs(res.value - exp.value) < 1e-16
495+
check abs(res.error - exp.error) < 1e-16
496+
497+
block DifferentVar:
498+
# for two *different* variables, the errors are correlated though. That
499+
# means while the integration result is still =~= 0, the uncertainty isn't
500+
let b2 = measurement(6.42, 0.03)
501+
let res = adaptiveGauss[T, T](sinFo, -b, b2)
502+
let exp = measurement(7.2390e-17, 0.0057865)
503+
check abs(res.value - exp.value) < 1e-16
504+
check abs(res.error - exp.error) < 1e-4

0 commit comments

Comments
 (0)