OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [language/] [c/] [libm/] [v2_0/] [tests/] [vectors/] [vector_support.h] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
#ifndef CYGONCE_LIBM_VECTOR_SUPPORT_H
2
#define CYGONCE_LIBM_VECTOR_SUPPORT_H
3
//========================================================================
4
//
5
//      vector_support.h
6
//
7
//      Support for testing of the math library using test vectors
8
//
9
//========================================================================
10
//####ECOSGPLCOPYRIGHTBEGIN####
11
// -------------------------------------------
12
// This file is part of eCos, the Embedded Configurable Operating System.
13
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
14
//
15
// eCos is free software; you can redistribute it and/or modify it under
16
// the terms of the GNU General Public License as published by the Free
17
// Software Foundation; either version 2 or (at your option) any later version.
18
//
19
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
20
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
21
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
22
// for more details.
23
//
24
// You should have received a copy of the GNU General Public License along
25
// with eCos; if not, write to the Free Software Foundation, Inc.,
26
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27
//
28
// As a special exception, if other files instantiate templates or use macros
29
// or inline functions from this file, or you compile this file and link it
30
// with other works to produce a work based on this file, this file does not
31
// by itself cause the resulting work to be covered by the GNU General Public
32
// License. However the source code for this file must still be made available
33
// in accordance with section (3) of the GNU General Public License.
34
//
35
// This exception does not invalidate any other reasons why a work based on
36
// this file might be covered by the GNU General Public License.
37
//
38
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
39
// at http://sources.redhat.com/ecos/ecos-license/
40
// -------------------------------------------
41
//####ECOSGPLCOPYRIGHTEND####
42
//========================================================================
43
//#####DESCRIPTIONBEGIN####
44
//
45
// Author(s):     jlarmour
46
// Contributors:  jlarmour
47
// Date:          1999-01-21
48
// Purpose:     
49
// Description: 
50
// Usage:         #include "vectors/vector_support.h"
51
//
52
//####DESCRIPTIONEND####
53
//
54
//========================================================================
55
 
56
// CONFIGURATION
57
 
58
#include <pkgconf/libm.h>      // Configuration header
59
#include <pkgconf/isoinfra.h>  // CYGINT_ISO_MAIN_STARTUP
60
 
61
// INCLUDES
62
 
63
#include <cyg/infra/cyg_type.h>   // Common type definitions and support
64
#include <cyg/infra/testcase.h>   // Test infrastructure
65
#include <math.h>                 // Header for this package
66
#include <sys/ieeefp.h>           // Cyg_libm_ieee_double_shape_type
67
#include <cyg/infra/diag.h>
68
 
69
#ifndef CYGSEM_LIBM_COMPAT_IEEE_ONLY
70
# include <errno.h>                // For Cyg_ErrNo
71
#endif
72
 
73
// CONSTANTS
74
 
75
#define PROBLEM_THRESHOLD 10      // Number of test vectors allowed to fail
76
                                  // before we give up completely
77
 
78
// HOW TO START TESTS
79
 
80
#if CYGINT_ISO_MAIN_STARTUP
81
 
82
# define START_TEST( test ) test(0)
83
 
84
#elif defined(CYGFUN_KERNEL_API_C)
85
 
86
# include <cyg/hal/hal_arch.h>
87
# include <cyg/kernel/kapi.h>
88
 
89
# define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
90
 
91
static cyg_uint8 stack[STACKSIZE];
92
static cyg_handle_t thr_handle;
93
static cyg_thread thr;
94
 
95
# define START_TEST( test ) CYG_MACRO_START \
96
    cyg_thread_create( 4, &test, (cyg_addrword_t)0, "test", \
97
                       &stack[0],  STACKSIZE, &thr_handle, &thr ); \
98
    cyg_thread_resume( thr_handle ); \
99
    cyg_scheduler_start(); \
100
    CYG_MACRO_END
101
 
102
externC int main( int, char ** );
103
 
104
externC void
105
cyg_user_start( void )
106
{
107
    (void) main(0, NULL);
108
} // cyg_user_start()
109
 
110
#else // !defined(CYGFUN_KERNEL_API_C)
111
 
112
externC int main( int, char ** );
113
 
114
externC void
115
cyg_user_start( void )
116
{
117
    (void) main(0, NULL);
118
} // cyg_user_start()
119
 
120
# define START_TEST( test ) test(0)
121
 
122
#endif
123
 
124
// TYPE DEFINITIONS
125
 
126
 
127
typedef enum {
128
    CYG_LIBM_TEST_VEC_NONE,         // this indicates whether the "double"
129
    CYG_LIBM_TEST_VEC_INT,          // is being used to store a double, an
130
    CYG_LIBM_TEST_VEC_DOUBLE,       // int, or its not being used at all!
131
    CYG_LIBM_TEST_VEC_INT_P,        // int pointer
132
    CYG_LIBM_TEST_VEC_DOUBLE_P      // double pointer
133
} Cyg_libm_test_arg_type;
134
 
135
 
136
// Define a type for a test vector record
137
 
138
typedef struct {
139
    cyg_ucount32 vector_num;        // id number of this test vector record
140
 
141
    // if any of the following arguments are ints rather than doubles, then
142
    // use the lsw part to store it
143
 
144
    cyg_uint32 arg1_msw;   // first argument
145
    cyg_uint32 arg1_lsw;
146
    cyg_uint32 arg2_msw;   // second argument
147
    cyg_uint32 arg2_lsw;
148
    cyg_uint32 result_msw; // expected return value
149
    cyg_uint32 result_lsw;
150
 
151
#ifndef CYGSEM_LIBM_COMPAT_IEEE_ONLY
152
    Cyg_ErrNo errno_val;           // expected value of errno. 0==unchanged
153
#else
154
    cyg_uint32 errno_val;
155
#endif
156
 
157
    double tolerance;              // relative amount that it is allowed
158
                                   // to vary. i.e. the value should be
159
                                   // plus or minus result*tolerance
160
 
161
    int matherr_type;              // if testing the matherr() function,
162
                                   // what type should the exception be
163
} Cyg_libm_test_double_vec_t;
164
 
165
 
166
// types to cope with the different forms of function to be called by the
167
// test vector
168
 
169
typedef double (*ddfn)( double, double );
170
typedef double (*difn)( double, int );
171
typedef double (*dfn)( double );
172
typedef double (*ddpfn)( double, double *);
173
typedef double (*dipfn)( double, int *);
174
 
175
 
176
// STATIC FUNCTIONS
177
 
178
// equivalent of abs() for doubles. We want to be independent of fabs()
179
 
180
static double
181
my_abs_d( double x )
182
{
183
    Cyg_libm_ieee_double_shape_type t;
184
 
185
    t.value = x;
186
 
187
    t.number.sign = 0;
188
 
189
    return t.value;
190
} // my_abs_d()
191
 
192
 
193
static cyg_bool
194
checkErrorAcceptable( Cyg_libm_ieee_double_shape_type is,
195
                      Cyg_libm_ieee_double_shape_type shouldbe,
196
                      double tolerance) // _relative_ amount it can vary
197
{
198
    Cyg_libm_ieee_double_shape_type temp_doub;
199
 
200
    // first do a short-circuit check if its identical
201
    if ( (is.parts.lsw == shouldbe.parts.lsw) &&
202
         (is.parts.msw == shouldbe.parts.msw) )
203
        return false;
204
 
205
    // now check special cases
206
 
207
    // +0 == -0
208
    if ( (is.parts.lsw == 0) && (shouldbe.parts.lsw == 0) &&
209
         ((is.parts.msw & 0x7fffffff) == 0) &&
210
         ((shouldbe.parts.msw & 0x7fffffff) == 0) )
211
        return false;
212
 
213
    // +-infinity == +-infinity
214
    if ((is.parts.lsw == 0) && (shouldbe.parts.lsw == 0) &&
215
        (is.number.fraction0 == 0) && (shouldbe.number.fraction0 == 0) &&
216
        (is.number.exponent == 2047) && (shouldbe.number.exponent == 2047))
217
    {
218
        return (is.number.sign != shouldbe.number.sign);
219
    } // if
220
 
221
    // both NaN. Assumes isnan works, but its pretty safe
222
    if ( isnan(is.value) && isnan(shouldbe.value) )
223
        return false;
224
    else if (isnan(is.value) || isnan(shouldbe.value) )
225
        return true;
226
 
227
    // check same sign. Even around small values close to 0 we would want
228
    // it to be on the right _side_ of 0
229
    if ( is.number.sign != shouldbe.number.sign )
230
        return true;
231
 
232
    // okay, now work out what tolerance means for us
233
 
234
    // find out what the difference is in the first place
235
    temp_doub.value = my_abs_d( shouldbe.value - is.value );
236
 
237
    // Check "both ways round" to deal with both under and overflow cases
238
    if ( ((temp_doub.value / tolerance) < my_abs_d(shouldbe.value)) ||
239
         (temp_doub.value < (my_abs_d(shouldbe.value) * tolerance)) )
240
        return false;
241
    else
242
        return true; // so its not close enough
243
 
244
} // checkErrorAcceptable()
245
 
246
 
247
// This allows us to run through any test vectors of form:
248
// double = fn(double, double)
249
// double = fn(double)
250
// double = fn(double, int)
251
// double = fn(double, int *)
252
// double = fn(double, double *)
253
//
254
// result type being non-double is left as a future enhancement
255
//
256
// This returns true if the tests all succeeded and false if any failed
257
//
258
static cyg_bool
259
doTestVec( CYG_ADDRESS func_ptr,
260
           Cyg_libm_test_arg_type arg1_type,
261
           Cyg_libm_test_arg_type arg2_type,
262
           Cyg_libm_test_arg_type result_type,
263
           const Cyg_libm_test_double_vec_t *vectors,
264
           cyg_ucount32 num_vectors )
265
{
266
    cyg_ucount32 problems=0;
267
    cyg_ucount32 i;
268
    Cyg_libm_ieee_double_shape_type arg1, arg2, result_wanted, ret;
269
    cyg_ucount32 alive_count = num_vectors / 10;
270
 
271
    if ((arg1_type != CYG_LIBM_TEST_VEC_DOUBLE) ||
272
        (result_type != CYG_LIBM_TEST_VEC_DOUBLE) ) {
273
        CYG_TEST_FAIL("Test vector arguments are not correct type!");
274
        return false;
275
    } // if
276
 
277
    switch (arg2_type) {
278
    case CYG_LIBM_TEST_VEC_DOUBLE:
279
 
280
        {
281
            ddfn fn = (ddfn) func_ptr;
282
 
283
            for (i=0;
284
                 (i < num_vectors) && (problems < PROBLEM_THRESHOLD);
285
                 i++) {
286
 
287
                if (0 == i % alive_count)
288
                    CYG_TEST_STILL_ALIVE(i, "Still crunching, please wait...");
289
 
290
                arg1.parts.msw = vectors[i].arg1_msw;
291
                arg1.parts.lsw = vectors[i].arg1_lsw;
292
 
293
                arg2.parts.msw = vectors[i].arg2_msw;
294
                arg2.parts.lsw = vectors[i].arg2_lsw;
295
 
296
                result_wanted.parts.msw = vectors[i].result_msw;
297
                result_wanted.parts.lsw = vectors[i].result_lsw;
298
 
299
                ret.value = (*fn)( arg1.value, arg2.value );
300
 
301
                if ((vectors[i].errno_val) != 0) {
302
 
303
#ifndef CYGSEM_LIBM_COMPAT_IEEE_ONLY
304
                    // In IEEE-mode we can't check the answer if this
305
                    // is an error case
306
 
307
                    if ((cyg_libm_get_compat_mode() !=
308
                        CYGNUM_LIBM_COMPAT_IEEE) &&
309
                        (errno != vectors[i].errno_val)) {
310
 
311
                        ++problems;
312
                        diag_printf("Vector #%d\n", i+1);
313
                        CYG_TEST_FAIL( "error not set correctly");
314
 
315
                    } // if
316
#endif
317
 
318
                    continue; // no point checking value in an error case
319
                } // if
320
                if (checkErrorAcceptable( ret, result_wanted,
321
                                          vectors[i].tolerance) ) {
322
                    ++problems;
323
                    diag_printf("Vector #%d\n", i+1);
324
                    CYG_TEST_FAIL( "Result out of tolerance");
325
                } // if
326
            } // for
327
 
328
        } // compound
329
 
330
        break;
331
 
332
    case CYG_LIBM_TEST_VEC_INT:
333
 
334
        {
335
            difn fn = (difn) func_ptr;
336
 
337
            for (i=0;
338
                 (i < num_vectors) && (problems < PROBLEM_THRESHOLD);
339
                 i++) {
340
 
341
                if (0 == i % alive_count)
342
                    CYG_TEST_STILL_ALIVE(i, "Still crunching, please wait...");
343
 
344
                arg1.parts.msw = vectors[i].arg1_msw;
345
                arg1.parts.lsw = vectors[i].arg1_lsw;
346
 
347
                result_wanted.parts.msw = vectors[i].result_msw;
348
                result_wanted.parts.lsw = vectors[i].result_lsw;
349
 
350
                ret.value = (*fn)( arg1.value, vectors[i].arg2_lsw );
351
                if (checkErrorAcceptable( ret, result_wanted,
352
                                          vectors[i].tolerance) ) {
353
                    ++problems;
354
                    diag_printf("Vector #%d\n", i+1);
355
                    CYG_TEST_FAIL( "Result out of tolerance");
356
                } // if
357
            } // for
358
 
359
        } // compound
360
 
361
        break;
362
 
363
    case CYG_LIBM_TEST_VEC_INT_P:
364
 
365
        {
366
            dipfn fn = (dipfn) func_ptr;
367
            int my_int;
368
            Cyg_libm_ieee_double_shape_type my_doub1, my_doub2;
369
 
370
            for (i=0;
371
                 (i < num_vectors) && (problems < PROBLEM_THRESHOLD);
372
                 i++) {
373
 
374
                if (0 == i % alive_count)
375
                    CYG_TEST_STILL_ALIVE(i, "Still crunching, please wait...");
376
 
377
                arg1.parts.msw = vectors[i].arg1_msw;
378
                arg1.parts.lsw = vectors[i].arg1_lsw;
379
 
380
 
381
                result_wanted.parts.msw = vectors[i].result_msw;
382
                result_wanted.parts.lsw = vectors[i].result_lsw;
383
 
384
                ret.value = (*fn)( arg1.value, &my_int );
385
                if (checkErrorAcceptable( ret, result_wanted,
386
                                          vectors[i].tolerance) ) {
387
                    ++problems;
388
                    diag_printf("Vector #%d\n", i+1);
389
                    CYG_TEST_FAIL( "Result out of tolerance");
390
                } // if
391
 
392
                my_doub1.value = (double) my_int;
393
                my_doub2.value = (double) (signed)vectors[i].arg2_lsw;
394
 
395
                if (checkErrorAcceptable( my_doub1, my_doub2,
396
                                          vectors[i].tolerance) ) {
397
                    ++problems;
398
                    diag_printf("Vector #%d\n", i+1);
399
                    CYG_TEST_FAIL( "Integer result out of tolerance");
400
                } // if
401
 
402
 
403
            } // for
404
 
405
        } // compound
406
 
407
        break;
408
 
409
    case CYG_LIBM_TEST_VEC_DOUBLE_P:
410
 
411
        {
412
            ddpfn fn = (ddpfn) func_ptr;
413
            Cyg_libm_ieee_double_shape_type my_doub1;
414
 
415
            for (i=0;
416
                 (i < num_vectors) && (problems < PROBLEM_THRESHOLD);
417
                 i++) {
418
 
419
                if (0 == i % alive_count)
420
                    CYG_TEST_STILL_ALIVE(i, "Still crunching, please wait...");
421
 
422
                arg1.parts.msw = vectors[i].arg1_msw;
423
                arg1.parts.lsw = vectors[i].arg1_lsw;
424
 
425
                arg2.parts.msw = vectors[i].arg2_msw;
426
                arg2.parts.lsw = vectors[i].arg2_lsw;
427
 
428
 
429
                result_wanted.parts.msw = vectors[i].result_msw;
430
                result_wanted.parts.lsw = vectors[i].result_lsw;
431
 
432
                ret.value = (*fn)( arg1.value, &my_doub1.value );
433
                if (checkErrorAcceptable( ret, result_wanted,
434
                                          vectors[i].tolerance) ) {
435
                    ++problems;
436
                    diag_printf("Vector #%d\n", i+1);
437
                    CYG_TEST_FAIL( "Result out of tolerance");
438
                } // if
439
 
440
                if (checkErrorAcceptable( my_doub1, arg2,
441
                                          vectors[i].tolerance) ) {
442
                    ++problems;
443
                    diag_printf("Vector #%d\n", i+1);
444
                    CYG_TEST_FAIL( "Returned double result out of "
445
                                   "tolerance");
446
                } // if
447
 
448
 
449
            } // for
450
 
451
        } // compound
452
 
453
        break;
454
 
455
    case CYG_LIBM_TEST_VEC_NONE:
456
 
457
        {
458
            dfn fn = (dfn) func_ptr;
459
 
460
            for (i=0;
461
                 (i < num_vectors) && (problems < PROBLEM_THRESHOLD);
462
                 i++) {
463
 
464
                if (0 == i % alive_count)
465
                    CYG_TEST_STILL_ALIVE(i, "Still crunching, please wait...");
466
 
467
                arg1.parts.msw = vectors[i].arg1_msw;
468
                arg1.parts.lsw = vectors[i].arg1_lsw;
469
 
470
                result_wanted.parts.msw = vectors[i].result_msw;
471
                result_wanted.parts.lsw = vectors[i].result_lsw;
472
 
473
                ret.value = (*fn)( arg1.value );
474
                if (checkErrorAcceptable( ret, result_wanted,
475
                                          vectors[i].tolerance) ) {
476
                    ++problems;
477
                    diag_printf("Vector #%d\n", i+1);
478
                    CYG_TEST_FAIL( "Result out of tolerance");
479
                } // if
480
            } // for
481
 
482
        } // compound
483
 
484
        break;
485
 
486
    default:
487
        CYG_TEST_FAIL("Second argument of unknown type!");
488
        return false;
489
    } // switch
490
 
491
    if (problems != 0)
492
        return false;
493
    else
494
        return true;
495
 
496
} // doTestVec()
497
 
498
#endif // CYGONCE_LIBM_VECTOR_SUPPORT_H multiple inclusion protection
499
 
500
// EOF vector_support.h

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.