-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsupport.h
149 lines (131 loc) · 6.01 KB
/
support.h
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#ifndef LIKNORM_SUPPORT_H
#define LIKNORM_SUPPORT_H
#include <inttypes.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
static int __hope_errors = 0;
inline static int __hope_close(double actual, double desired, double rel_tol,
double abs_tol);
inline static void __hope_print_context(const char *file, int line)
{
fprintf(stderr, "\nAssertion error at %s:%d\n", file, line);
}
inline static void __hope_print_newline(void)
{
fprintf(stderr, "\n");
fflush(stderr);
}
#define __HOPE_REL_TOL(x) _Generic((x), float : 5e-05, double : 1e-09)
static inline void __hope_close2(double actual, double desired, double rel_tol,
double abs_tol, char const *file, int line)
{
double a = actual;
double d = desired;
if (__hope_close(a, d, rel_tol, abs_tol))
{
__hope_print_context(file, line);
fprintf(stderr, " Items are not close:\n");
fprintf(stderr, " ACTUAL : %.13f\n", (double)a);
fprintf(stderr, " DESIRED: %.13f\n", (double)d);
__hope_print_newline();
++__hope_errors;
}
}
#define __MAKE_EQ(S, T, F) \
static void __hope_eq_##S(T a, T d, char const *file, int line) \
{ \
if (!(a == d)) \
{ \
__hope_print_context(file, line); \
fprintf(stderr, " Items are not equal:\n"); \
fprintf(stderr, " ACTUAL : %" F "\n", a); \
fprintf(stderr, " DESIRED: %" F "\n", d); \
__hope_print_newline(); \
++__hope_errors; \
} \
}
#ifndef _WIN32
#define __hope_eq(actual, desired, file, line) \
_Generic((actual), \
unsigned char: __hope_eq_hhu, \
unsigned short: __hope_eq_hu, \
unsigned int: __hope_eq_u, \
unsigned long: __hope_eq_lu, \
unsigned long long: __hope_eq_llu, \
signed char: __hope_eq_hhd, \
short: __hope_eq_hd, \
int: __hope_eq_d, \
long: __hope_eq_ld, \
long long: __hope_eq_lld, \
char: __hope_eq_char, \
char *: __hope_eq_str, \
char const *: __hope_eq_str,\
FILE *: __hope_eq_file)((actual), (desired), file, line)
#else
/* Bug: https://is.gd/DWxyJO */
#define __hope_eq(actual, desired, file, line) \
_Generic((actual), \
unsigned short: __hope_eq_hu, \
unsigned int: __hope_eq_u, \
unsigned long: __hope_eq_lu, \
unsigned long long: __hope_eq_llu, \
short: __hope_eq_hd, \
int: __hope_eq_d, \
long: __hope_eq_ld, \
long long: __hope_eq_lld, \
char: __hope_eq_char, \
char *: __hope_eq_str, \
char const *: __hope_eq_str,\
FILE *: __hope_eq_file)((actual), (desired), file, line)
#endif
static inline void __hope_cond(char const *expr, int cond, char const *file,
int line)
{
if (cond)
{
__hope_print_context(file, line);
fprintf(stderr, " Condition evaluates to false:\n");
fprintf(stderr, " EXPRESSION: %s\n", expr);
__hope_print_newline();
++__hope_errors;
}
}
inline static int __hope_close(double actual, double desired, double rel_tol,
double abs_tol)
{
/* This implementation is basically a copy of the `math.isclose`
* implementation of the Python library plus returning 0 in case
* both values are NaN.
*/
if (actual == desired)
{
/* short circuit exact equality -- needed to catch two infinities of
* the same sign. And perhaps speeds things up a bit sometimes.
*/
return 0;
}
if (isnan(actual) && isnan(desired))
{
return 0;
}
/* This catches the case of two infinities of opposite sign, or
* one infinity and one finite number. Two infinities of opposite
* sign would otherwise have an infinite relative tolerance.
* Two infinities of the same sign are caught by the equality check
* above.
*/
if (isinf(actual) || isinf(desired))
{
return 1;
}
/* now do the regular computation
* this is essentially the "weak" test from the Boost library
*/
double diff = fabs(desired - actual);
return !(((diff <= fabs(rel_tol * desired)) ||
(diff <= fabs(rel_tol * actual))) ||
(diff <= abs_tol));
}
#endif