Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/arm-optimized-routines/math/test/rtest/main.c
48375 views
1
/*
2
* main.c
3
*
4
* Copyright (c) 1999-2019, Arm Limited.
5
* SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6
*/
7
8
#include <assert.h>
9
#include <stdio.h>
10
#include <string.h>
11
#include <ctype.h>
12
#include <stdlib.h>
13
#include <time.h>
14
15
#include "intern.h"
16
17
void gencases(Testable *fn, int number);
18
void docase(Testable *fn, uint32 *args);
19
void vet_for_decline(Testable *fn, uint32 *args, uint32 *result, int got_errno_in);
20
void seed_random(uint32 seed);
21
22
int check_declines = 0;
23
int lib_fo = 0;
24
int lib_no_arith = 0;
25
int ntests = 0;
26
27
int nargs_(Testable* f) {
28
switch((f)->type) {
29
case args2:
30
case args2f:
31
case semi2:
32
case semi2f:
33
case t_ldexp:
34
case t_ldexpf:
35
case args1c:
36
case args1fc:
37
case args1cr:
38
case args1fcr:
39
case compare:
40
case comparef:
41
return 2;
42
case args2c:
43
case args2fc:
44
return 4;
45
default:
46
return 1;
47
}
48
}
49
50
static int isdouble(Testable *f)
51
{
52
switch (f->type) {
53
case args1:
54
case rred:
55
case semi1:
56
case t_frexp:
57
case t_modf:
58
case classify:
59
case t_ldexp:
60
case args2:
61
case semi2:
62
case args1c:
63
case args1cr:
64
case compare:
65
case args2c:
66
return 1;
67
case args1f:
68
case rredf:
69
case semi1f:
70
case t_frexpf:
71
case t_modff:
72
case classifyf:
73
case args2f:
74
case semi2f:
75
case t_ldexpf:
76
case comparef:
77
case args1fc:
78
case args1fcr:
79
case args2fc:
80
return 0;
81
default:
82
assert(0 && "Bad function type");
83
}
84
}
85
86
Testable *find_function(const char *func)
87
{
88
int i;
89
for (i = 0; i < nfunctions; i++) {
90
if (func && !strcmp(func, functions[i].name)) {
91
return &functions[i];
92
}
93
}
94
return NULL;
95
}
96
97
void get_operand(const char *str, Testable *f, uint32 *word0, uint32 *word1)
98
{
99
struct special {
100
unsigned dblword0, dblword1, sglword;
101
const char *name;
102
} specials[] = {
103
{0x00000000,0x00000000,0x00000000,"0"},
104
{0x3FF00000,0x00000000,0x3f800000,"1"},
105
{0x7FF00000,0x00000000,0x7f800000,"inf"},
106
{0x7FF80000,0x00000001,0x7fc00000,"qnan"},
107
{0x7FF00000,0x00000001,0x7f800001,"snan"},
108
{0x3ff921fb,0x54442d18,0x3fc90fdb,"pi2"},
109
{0x400921fb,0x54442d18,0x40490fdb,"pi"},
110
{0x3fe921fb,0x54442d18,0x3f490fdb,"pi4"},
111
{0x4002d97c,0x7f3321d2,0x4016cbe4,"3pi4"},
112
};
113
int i;
114
115
for (i = 0; i < (int)(sizeof(specials)/sizeof(*specials)); i++) {
116
if (!strcmp(str, specials[i].name) ||
117
((str[0] == '-' || str[0] == '+') &&
118
!strcmp(str+1, specials[i].name))) {
119
assert(f);
120
if (isdouble(f)) {
121
*word0 = specials[i].dblword0;
122
*word1 = specials[i].dblword1;
123
} else {
124
*word0 = specials[i].sglword;
125
*word1 = 0;
126
}
127
if (str[0] == '-')
128
*word0 |= 0x80000000U;
129
return;
130
}
131
}
132
133
sscanf(str, "%"I32"x.%"I32"x", word0, word1);
134
}
135
136
void dofile(FILE *fp, int translating) {
137
char buf[1024], sparebuf[1024], *p;
138
139
/*
140
* Command syntax is:
141
*
142
* - "seed <integer>" sets a random seed
143
*
144
* - "test <function> <ntests>" generates random test lines
145
*
146
* - "<function> op1=foo [op2=bar]" generates a specific test
147
* - "func=<function> op1=foo [op2=bar]" does the same
148
* - "func=<function> op1=foo result=bar" will just output the line as-is
149
*
150
* - a semicolon or a blank line is ignored
151
*/
152
while (fgets(buf, sizeof(buf), fp)) {
153
buf[strcspn(buf, "\r\n")] = '\0';
154
strcpy(sparebuf, buf);
155
p = buf;
156
while (*p && isspace(*p)) p++;
157
if (!*p || *p == ';') {
158
/* Comment or blank line. Only print if `translating' is set. */
159
if (translating)
160
printf("%s\n", buf);
161
continue;
162
}
163
if (!strncmp(buf, "seed ", 5)) {
164
seed_random(atoi(buf+5));
165
} else if (!strncmp(buf, "random=", 7)) {
166
/*
167
* Copy 'random=on' / 'random=off' lines unconditionally
168
* to the output, so that random test failures can be
169
* accumulated into a recent-failures-list file and
170
* still identified as random-in-origin when re-run the
171
* next day.
172
*/
173
printf("%s\n", buf);
174
} else if (!strncmp(buf, "test ", 5)) {
175
char *p = buf+5;
176
char *q;
177
int ntests, i;
178
q = p;
179
while (*p && !isspace(*p)) p++;
180
if (*p) *p++ = '\0';
181
while (*p && isspace(*p)) p++;
182
if (*p)
183
ntests = atoi(p);
184
else
185
ntests = 100; /* *shrug* */
186
for (i = 0; i < nfunctions; i++) {
187
if (!strcmp(q, functions[i].name)) {
188
gencases(&functions[i], ntests);
189
break;
190
}
191
}
192
if (i == nfunctions) {
193
fprintf(stderr, "unknown test `%s'\n", q);
194
}
195
} else {
196
/*
197
* Parse a specific test line.
198
*/
199
uint32 ops[8], result[8];
200
int got_op = 0; /* &1 for got_op1, &4 for got_op3 etc. */
201
Testable *f = 0;
202
char *q, *r;
203
int got_result = 0, got_errno_in = 0;
204
205
for (q = strtok(p, " \t"); q; q = strtok(NULL, " \t")) {
206
r = strchr(q, '=');
207
if (!r) {
208
f = find_function(q);
209
} else {
210
*r++ = '\0';
211
212
if (!strcmp(q, "func"))
213
f = find_function(r);
214
else if (!strcmp(q, "op1") || !strcmp(q, "op1r")) {
215
get_operand(r, f, &ops[0], &ops[1]);
216
got_op |= 1;
217
} else if (!strcmp(q, "op2") || !strcmp(q, "op1i")) {
218
get_operand(r, f, &ops[2], &ops[3]);
219
got_op |= 2;
220
} else if (!strcmp(q, "op2r")) {
221
get_operand(r, f, &ops[4], &ops[5]);
222
got_op |= 4;
223
} else if (!strcmp(q, "op2i")) {
224
get_operand(r, f, &ops[6], &ops[7]);
225
got_op |= 8;
226
} else if (!strcmp(q, "result") || !strcmp(q, "resultr")) {
227
get_operand(r, f, &result[0], &result[1]);
228
got_result |= 1;
229
} else if (!strcmp(q, "resulti")) {
230
get_operand(r, f, &result[4], &result[5]);
231
got_result |= 2;
232
} else if (!strcmp(q, "res2")) {
233
get_operand(r, f, &result[2], &result[3]);
234
got_result |= 4;
235
} else if (!strcmp(q, "errno_in")) {
236
got_errno_in = 1;
237
}
238
}
239
}
240
241
/*
242
* Test cases already set up by the input are not
243
* reprocessed by default, unlike the fplib tests. (This
244
* is mostly for historical reasons, because we used to
245
* use a very slow and incomplete internal reference
246
* implementation; now our ref impl is MPFR/MPC it
247
* probably wouldn't be such a bad idea, though we'd still
248
* have to make sure all the special cases came out
249
* right.) If translating==2 (corresponding to the -T
250
* command-line option) then we regenerate everything
251
* regardless.
252
*/
253
if (got_result && translating < 2) {
254
if (f)
255
vet_for_decline(f, ops, result, got_errno_in);
256
puts(sparebuf);
257
continue;
258
}
259
260
if (f && got_op==(1<<nargs_(f))-1) {
261
/*
262
* And do it!
263
*/
264
docase(f, ops);
265
}
266
}
267
}
268
}
269
270
int main(int argc, char **argv) {
271
int errs = 0, opts = 1, files = 0, translating = 0;
272
unsigned int seed = 1; /* in case no explicit seed provided */
273
274
seed_random(seed);
275
276
setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* stops incomplete lines being printed when out of time */
277
278
while (--argc) {
279
FILE *fp;
280
char *p = *++argv;
281
282
if (opts && *p == '-') {
283
if(*(p+1) == 0) { /* single -, read from stdin */
284
break;
285
} else if (!strcmp(p, "-t")) {
286
translating = 1;
287
} else if (!strcmp(p, "-T")) {
288
translating = 2;
289
} else if (!strcmp(p, "-c")) {
290
check_declines = 1;
291
} else if (!strcmp(p, "--")) {
292
opts = 0;
293
} else if (!strcmp(p,"--seed") && argc > 1 && 1==sscanf(*(argv+1),"%u",&seed)) {
294
seed_random(seed);
295
argv++; /* next in argv is seed value, so skip */
296
--argc;
297
} else if (!strcmp(p, "-fo")) {
298
lib_fo = 1;
299
} else if (!strcmp(p, "-noarith")) {
300
lib_no_arith = 1;
301
} else {
302
fprintf(stderr,
303
"rtest: ignoring unrecognised option '%s'\n", p);
304
errs = 1;
305
}
306
} else {
307
files = 1;
308
if (!errs) {
309
fp = fopen(p, "r");
310
if (fp) {
311
dofile(fp, translating);
312
fclose(fp);
313
} else {
314
perror(p);
315
errs = 1;
316
}
317
}
318
}
319
}
320
321
/*
322
* If no filename arguments, use stdin.
323
*/
324
if (!files && !errs) {
325
dofile(stdin, translating);
326
}
327
328
if (check_declines) {
329
fprintf(stderr, "Tests expected to run: %d\n", ntests);
330
fflush(stderr);
331
}
332
333
return errs;
334
}
335
336