File: testtool.h

package info (click to toggle)
libcerf 3.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 760 kB
  • sloc: ansic: 4,905; f90: 250; makefile: 18
file content (93 lines) | stat: -rw-r--r-- 3,180 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/* Library libcerf:
 *   Compute complex error functions, based on a new implementation of
 *   Faddeeva's w_of_z. Also provide Dawson and Voigt functions.
 *
 * File testtool.h
 *   Auxiliary functions and preprocessor macros for numeric tests.
 *
 * Copyright:
 *   (C) 2012 Massachusetts Institute of Technology
 *   (C) 2013 Forschungszentrum Jülich GmbH
 *
 * Licence:
 *   ../LICENSE
 *
 * Authors:
 *   Steven G. Johnson, Massachusetts Institute of Technology, 2012
 *   Joachim Wuttke, Forschungszentrum Jülich, 2013
 *
 * Website:
 *   http://apps.jcns.fz-juelich.de/libcerf
 *
 * Revision history:
 *   ../CHANGELOG
 */

#ifdef __cplusplus
#include <cassert>
#include <cmath>
using std::isfinite;
#else
#include <assert.h>
#include <math.h>
#endif
#include <float.h>
#include <stdio.h>
#include "defs.h" // defines _cerf_cmplx, CMPLX, NaN, Inf


typedef struct {
    int failed;
    int total;
} result_t;

// Compute relative error |b-a|/|b+offs|, handling case of NaN and Inf.
// The tiny offset offs ensures a resonable return value for a=(almost underflowing), b=0.
static double relerr(double a, double b)
{
    if (!isfinite(a))
        return !isfinite(b) ? 0 : Inf;
    if (!isfinite(b)) {
        assert(isfinite(a)); // implied by the above
        return Inf;
    }
   return fabs((b - a)) / (fabs(b) + 1e-300);
}

// Test whether real numbers 'computed' and 'expected' agree within relative error bound 'limit'
void rtest(result_t* result, double limit, double computed, double expected, const char* name)
{
    ++result->total;
    const double re = relerr(computed, expected);
    if (re > limit) {
        printf("failure in subtest %i: %s\n", result->total, name);
        printf("- fct value %20.15g\n", computed);
        printf("- expected  %20.15g\n", expected);
        printf("=> error %6.2g above limit %6.2g\n", re, limit);
        ++result->failed;
    }
}

// Test whether complex numbers 'computed' and 'expected' agree within relative error bound 'limit'
void ztest(
    result_t* result, double limit, _cerf_cmplx computed, _cerf_cmplx expected, const char* name)
{
    ++result->total;
    const double re_r = relerr(creal(computed), creal(expected));
    const double re_i = relerr(cimag(computed), cimag(expected));
    if (re_r > limit || re_i > limit) {
        printf("failure in subtest %i: %s\n", result->total, name);
        printf("- fct value %20.15g%+20.15g\n", creal(computed), cimag(computed));
        printf("- expected  %20.15g%+20.15g\n", creal(expected), cimag(expected));
        printf("=> error %6.2g or %6.2g above limit %6.2g\n", re_r, re_i, limit);
        ++result->failed;
    }
}

// Wrap rtest; use preprocessor stringification to print the calling 'function_val' verbatim
#define RTEST(result, limit, function_val, expected_val)                                           \
    rtest(&result, limit, function_val, expected_val, #function_val);

// Wrap ztest; use preprocessor stringification to print the calling 'function_val' verbatim
#define ZTEST(result, limit, function_val, expected_val)                                           \
    ztest(&result, limit, function_val, expected_val, #function_val);