@@ -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]) < 1 e-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) < 1 e-3
470+ check abs (res.error - exp.error) < 1 e-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) < 1 e-3
483+ check abs (res.error - exp.error) < 1 e-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.23 e-17 , 1.0065 e-18 )
494+ check abs (res.value - exp.value) < 1 e-16
495+ check abs (res.error - exp.error) < 1 e-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.2390 e-17 , 0.0057865 )
503+ check abs (res.value - exp.value) < 1 e-16
504+ check abs (res.error - exp.error) < 1 e-4
0 commit comments