File: math.5c

package info (click to toggle)
nickle 2.70-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 2,324 kB
  • ctags: 3,324
  • sloc: ansic: 31,410; yacc: 1,864; sh: 954; lex: 858; makefile: 238
file content (143 lines) | stat: -rw-r--r-- 3,225 bytes parent folder | download | duplicates (4)
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
/*
 * Nickle test suite
 *
 * Trig operator tests
 */

load "math-tables.5c"

int precision = 64;
int errors = 0;

real checked(real(real) f, real a) {
	try {
		real r = f(imprecise (a, precision));
		if (r > 1e10)
			return 9999;
		if (r < -1e10)
			return 9999;
		return r;
	} catch invalid_argument(string type, int i, real v) {
		return 10000;
	}
	return 0;
}

real checked2(real(real, real) f, real a, real b) {
	try {
		real r = f(imprecise(a, precision), imprecise(b, precision));

		/* Just return the same value for large magnitudes
		 * as small variations in input cause the sign to flip
		 */
		 
		if (r > 1e10)
			return 9999;
		if (r < -1e10)
			return 9999;
		return r;
	} catch invalid_argument(string type, int i, real v) {
		return 10000;
	}
	return 0;
}

void check(string op, real(real) f, real input, real correct)
{
	real	value = checked(f, input);
	
	if (is_number (value))
	{
		real	error = abs (value - correct);

		if (abs(correct) >= 1 && error < abs(correct) * 1e-8)
			return;
		if (abs(correct) < 1 && error < 1e-8)
			return;
		printf ("error %v value %v\n", error, value);
	}
	if (value != correct) {
		printf ("check failed %s(%v) (was %.-g, should be %.-g)",
			op, input, value, correct);
		errors++;
	}
}

void check2(string op, real(real, real) f, real input1, real input2, real correct)
{
	real	value = checked2(f, input1, input2);
	
	if (is_number (value))
	{
		real	error = abs (value - correct);

		if (abs(correct) >= 1 && error < abs(correct) * 1e-10)
			return;
		if (abs(correct) < 1 && error < 1e-10)
			return;
		printf ("error %v value %v\n", error, value);
	}
	if (value != correct) {
		printf ("check failed %s(%.-g, %.-g) (was %.-g, should be %.-g)",
			op, input1, input2, value, correct);
		errors++;
	}
}

void check_sin_cos()
{
	for (int i = 0; i < dim(sin_cos_table); i++) {
		real	angle = sin_cos_table[i].angle;
		real	sin_value = sin_cos_table[i].sin;
		real	cos_value = sin_cos_table[i].cos;
		check("sin", sin, angle, sin_value);
		check("cos", cos, angle, cos_value);
	}
	for (int i = 0; i < dim(asin_acos_table); i++) {
		real	ratio = asin_acos_table[i].ratio;
		real	asin_value = asin_acos_table[i].asin;
		real	acos_value = asin_acos_table[i].acos;
		check("asin", asin, ratio, asin_value);
		check("acos", acos, ratio, acos_value);
	}
}

void check_tan()
{
	for (int i = 0; i < dim(tan_table); i++) {
		real angle = tan_table[i].angle;
		real tan_value = tan_table[i].tan;
		check("tan", tan, angle, tan_value);
	}
	for (int i = 0; i < dim(atan_table); i++) {
		real ratio = atan_table[i].ratio;
		real atan_value = atan_table[i].atan;
		check("atan", atan, ratio, atan_value);
	}
	for (int i = 0; i < dim(atan2_table); i++) {
		real y = atan2_table[i].y;
		real x = atan2_table[i].x;
		real atan2_value = atan2_table[i].atan2;
		check2("atan2", atan2, y, x, atan2_value);
	}
}

void check_log()
{
	for (int i = 0; i < dim(log_table); i++) {
		real in = log_table[i].in;
		real log_value = log_table[i].log;
		check("log", log, in, log_value);
	}
	for (int i = 0; i < dim(exp_table); i++) {
		real in = exp_table[i].in;
		real exp_value = exp_table[i].exp;
		check("exp", exp, in, exp_value);
	}
}

check_sin_cos();
check_tan();
check_log();

exit (errors);