📄 vector_support.h
字号:
#ifndef CYGONCE_LIBM_VECTOR_SUPPORT_H
#define CYGONCE_LIBM_VECTOR_SUPPORT_H
//========================================================================
//
// vector_support.h
//
// Support for testing of the math library using test vectors
//
//========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): jlarmour
// Contributors: jlarmour
// Date: 1999-01-21
// Purpose:
// Description:
// Usage: #include "vectors/vector_support.h"
//
//####DESCRIPTIONEND####
//
//========================================================================
// CONFIGURATION
#include <pkgconf/libm.h> // Configuration header
#include <pkgconf/isoinfra.h> // CYGINT_ISO_MAIN_STARTUP
// INCLUDES
#include <cyg/infra/cyg_type.h> // Common type definitions and support
#include <cyg/infra/testcase.h> // Test infrastructure
#include <math.h> // Header for this package
#include <sys/ieeefp.h> // Cyg_libm_ieee_double_shape_type
#include <cyg/infra/diag.h>
#ifndef CYGSEM_LIBM_COMPAT_IEEE_ONLY
# include <errno.h> // For Cyg_ErrNo
#endif
// CONSTANTS
#define PROBLEM_THRESHOLD 10 // Number of test vectors allowed to fail
// before we give up completely
// HOW TO START TESTS
#if CYGINT_ISO_MAIN_STARTUP
# define START_TEST( test ) test(0)
#elif defined(CYGFUN_KERNEL_API_C)
# include <cyg/hal/hal_arch.h>
# include <cyg/kernel/kapi.h>
# define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
static cyg_uint8 stack[STACKSIZE];
static cyg_handle_t thr_handle;
static cyg_thread thr;
# define START_TEST( test ) CYG_MACRO_START \ cyg_thread_create( 4, &test, (cyg_addrword_t)0, "test", \ &stack[0], STACKSIZE, &thr_handle, &thr ); \ cyg_thread_resume( thr_handle ); \ cyg_scheduler_start(); \ CYG_MACRO_END
externC int main( int, char ** );
externC void
cyg_user_start( void )
{
(void) main(0, NULL);
} // cyg_user_start()
#else // !defined(CYGFUN_KERNEL_API_C)
externC int main( int, char ** );
externC void
cyg_user_start( void )
{
(void) main(0, NULL);
} // cyg_user_start()
# define START_TEST( test ) test(0)
#endif
// TYPE DEFINITIONS
typedef enum {
CYG_LIBM_TEST_VEC_NONE, // this indicates whether the "double"
CYG_LIBM_TEST_VEC_INT, // is being used to store a double, an
CYG_LIBM_TEST_VEC_DOUBLE, // int, or its not being used at all!
CYG_LIBM_TEST_VEC_INT_P, // int pointer
CYG_LIBM_TEST_VEC_DOUBLE_P // double pointer
} Cyg_libm_test_arg_type;
// Define a type for a test vector record
typedef struct {
cyg_ucount32 vector_num; // id number of this test vector record
// if any of the following arguments are ints rather than doubles, then
// use the lsw part to store it
cyg_uint32 arg1_msw; // first argument
cyg_uint32 arg1_lsw;
cyg_uint32 arg2_msw; // second argument
cyg_uint32 arg2_lsw;
cyg_uint32 result_msw; // expected return value
cyg_uint32 result_lsw;
#ifndef CYGSEM_LIBM_COMPAT_IEEE_ONLY
Cyg_ErrNo errno_val; // expected value of errno. 0==unchanged
#else
cyg_uint32 errno_val;
#endif
double tolerance; // relative amount that it is allowed
// to vary. i.e. the value should be
// plus or minus result*tolerance
int matherr_type; // if testing the matherr() function,
// what type should the exception be
} Cyg_libm_test_double_vec_t;
// types to cope with the different forms of function to be called by the
// test vector
typedef double (*ddfn)( double, double );
typedef double (*difn)( double, int );
typedef double (*dfn)( double );
typedef double (*ddpfn)( double, double *);
typedef double (*dipfn)( double, int *);
// STATIC FUNCTIONS
// equivalent of abs() for doubles. We want to be independent of fabs()
static double
my_abs_d( double x )
{
Cyg_libm_ieee_double_shape_type t;
t.value = x;
t.number.sign = 0;
return t.value;
} // my_abs_d()
static cyg_bool
checkErrorAcceptable( Cyg_libm_ieee_double_shape_type is,
Cyg_libm_ieee_double_shape_type shouldbe,
double tolerance) // _relative_ amount it can vary
{
Cyg_libm_ieee_double_shape_type temp_doub;
// first do a short-circuit check if its identical
if ( (is.parts.lsw == shouldbe.parts.lsw) &&
(is.parts.msw == shouldbe.parts.msw) )
return false;
// now check special cases
// +0 == -0
if ( (is.parts.lsw == 0) && (shouldbe.parts.lsw == 0) &&
((is.parts.msw & 0x7fffffff) == 0) &&
((shouldbe.parts.msw & 0x7fffffff) == 0) )
return false;
// +-infinity == +-infinity
if ((is.parts.lsw == 0) && (shouldbe.parts.lsw == 0) &&
(is.number.fraction0 == 0) && (shouldbe.number.fraction0 == 0) &&
(is.number.exponent == 2047) && (shouldbe.number.exponent == 2047))
{
return (is.number.sign != shouldbe.number.sign);
} // if
// both NaN. Assumes isnan works, but its pretty safe
if ( isnan(is.value) && isnan(shouldbe.value) )
return false;
else if (isnan(is.value) || isnan(shouldbe.value) )
return true;
// check same sign. Even around small values close to 0 we would want
// it to be on the right _side_ of 0
if ( is.number.sign != shouldbe.number.sign )
return true;
// okay, now work out what tolerance means for us
// find out what the difference is in the first place
temp_doub.value = my_abs_d( shouldbe.value - is.value );
// Check "both ways round" to deal with both under and overflow cases
if ( ((temp_doub.value / tolerance) < my_abs_d(shouldbe.value)) ||
(temp_doub.value < (my_abs_d(shouldbe.value) * tolerance)) )
return false;
else
return true; // so its not close enough
} // checkErrorAcceptable()
// This allows us to run through any test vectors of form:
// double = fn(double, double)
// double = fn(double)
// double = fn(double, int)
// double = fn(double, int *)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -