1 /**
2 Internal test utilities.
3 Use flags -unittest -debug=libcerf to receive debug info.
4 
5 Copyright:
6     © 2012 Massachusetts Institute of Technology,    
7     © 2013 Forschungszentrum Jülich GmbH,
8     © 2014 Ilya Yaroshenko
9  
10 Authors:
11     Steven G. Johnson, core author;
12     Joachim Wuttke, C package maintainer;
13     $(LINK2 http://plus.google.com/+IlyaYaroshenko, Ilya Yaroshenko), D package maintainer
14 
15 License: 
16     Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
17 */
18 module libcerf.testutils;
19 
20 import std.complex;
21 import std.math : isNaN, isInfinity, isFinite;
22 import core.stdc.math : fabs;
23 
24 debug(libcerf)
25 {
26     import std.traits : fullyQualifiedName;
27     import std.stdio : writefln;
28 }
29 
30 import core.stdc.math : pow, erfc;
31 
32 package:
33 
34 ///
35 bool relativeErrorCheck(double a, double b)
36 @safe nothrow @nogc
37 {
38     if(a.isNaN)
39     {
40         return b.isNaN;
41     }
42     if(a.isInfinity)
43     {
44         return b == a;
45     }
46     if(a == 0)
47     {
48         return fabs(b) < 1e-13;
49     }
50     return fabs((b-a) / a) < 1e-13;
51 }
52 
53 ///
54 bool relativeErrorCheck(Complex!double a, Complex!double b)
55 @safe nothrow @nogc
56 {
57     return relativeErrorCheck(a.re, b.re) && relativeErrorCheck(a.im, b.im);
58 }
59 
60 ///
61 void commonTest(alias cfun)(in Complex!double[] Z, in Complex!double[] W)
62 {
63     debug(libcerf){
64         enum name = fullyQualifiedName!cfun;
65         writefln("%s common tests...", name);
66         scope (success)
67         writefln("%s common tests success", name);
68     }
69     assert(W.length == Z.length);   
70     foreach(i; 0..Z.length) {
71         immutable z = Z[i];
72         immutable w = W[i];
73         immutable f = cfun(z);
74         auto e = f-w;
75         e.re /= w.re;
76         e.im /= w.im;
77         debug(libcerf) 
78             writefln("%s(%s) = %s, vs. %s, rel. err. = %s)", name, z, f, w, e);
79         assert(relativeErrorCheck(w, f));
80     }
81 }
82 
83 ///
84 void specialTest(alias cfun, alias fun, double C)()
85 {
86     debug(libcerf){
87         enum name = fullyQualifiedName!cfun;
88         writefln("%s special tests...", name);
89         scope (success)
90         writefln("%s special tests success", name);
91     }
92     foreach (i; 0..10000) 
93     {
94         immutable x = pow(10., -300. + i * 600. / (10000 - 1));
95         assert(relativeErrorCheck(fun(+x), cfun(Complex!double(+x,x*C)).re));
96         assert(relativeErrorCheck(fun(-x), cfun(Complex!double(-x,x*C)).re));
97     }
98     assert(relativeErrorCheck(fun(double.infinity), cfun(Complex!double(double.infinity,0.)).re));
99     assert(relativeErrorCheck(fun(-double.infinity), cfun(Complex!double(-double.infinity,0.)).re));
100     assert(relativeErrorCheck(fun(double.nan), cfun(Complex!double(double.nan,0.)).re));
101 }