📄 float3.c
字号:
/* 10-13-2000
// Sample application to demonstrate the use of the Borland/Turbo C++
// floating point arithmetic in an embedded application. The key functions
// defined in this module are matherr(), the user-customizable exception
// handler for math run-time library errors, and MyFPHandler(), which
// handles intrinsic floating point exceptions.
*/
#include <signal.h> /* signal(), raise() prototypes */
#include <setjmp.h> /* setjmp(), longjmp() prototypes */
#include <math.h> /* Trig, exponential function prototypes */
#include <float.h> /* Low-level floating point definitions */
#include <string.h> /* Prototypes used in matherr() */
#include "586.h"
#define ERR_LIMIT 0.000001 /* Error delta for examples */
jmp_buf jbuf ; /* Exception position data */
float f1, f2 ;
double d1, d2 ;
unsigned errors ;
void ftest(void);
unsigned char ledd;
int i;
void main(void)
{
sc_init();
ledd=0;
while(1)
{
led(ledd);
for(i=0;i<50;i++)
{
ftest();
}
ledd=~ledd;
}
}
void ftest(void)
{
/* Initialize the error count and set the default handler */
// errors = 0 ;
// signal(SIGFPE, SIG_DFL) ;
for(i=0;i<1000;i++)
{
/* Check that sin(x)^2 + cos(x)^2 = 1 where x is PI/2 */
f1 = M_PI_2 ;
f2 = pow(sin(f1), 2.0) + pow(cos(f1), 2.0) ;
if (fabs(f2 - 1.0) > ERR_LIMIT)
errors++ ;
/* Check that ln(e^2) = 2 */
d1 = M_E ;
d2 = log(pow(d1, 2.0)) ;
if (fabs(d2 - 2.0) > ERR_LIMIT)
errors++ ;
/* Force an error and see that matherr() catches and fixes it */
d1 = 4.999;
// d1 = -4.0 ;
d2 = sqrt(d1) ;
}
/* Install a new floating point exception handler */
// signal(SIGFPE, MyFPHandler) ;
/* Force an intrinsic error and verify it is intercepted */
// if (setjmp(jbuf) == 0)
// raise(SIGFPE) ;
// else
// errors++ ; /* This code should also execute */
// /* Force an intrinsic error and verify it is intercepted */
// if (setjmp(jbuf) == 0) {
// d1 = 0.1 ;
// d1 = 0.0 ;
// d2 = 1.0 ;
// d2 = d2 / d1 ;
// }
// else {
// d2 = M_PI ; /* This code should also execute */
// errors++ ;
// }
/* Verify that the correct number of errors were detected */
// f1 = (errors != 2) ? -1.0 : 1.0 ;
}
/*
// Function: MyFPHandler
//
// This function gains control of floating point exceptions caused by
// intrinsic floating point operations.
*/
void MyFPHandler(
int sig, /* SIGFPE */
int type /* Floating point subtype */
)
{
/* Reset the math coprocessor */
_fpreset() ;
/* Restore the intercept for this signal */
signal(sig, MyFPHandler) ;
longjmp(jbuf, type) ;
}
/*
// Function: matherr()
//
// When exceptions are detected in the math library then a call is made
// to _matherr() with all the available information. _matherr() does very
// little, except to map the exception "why" into either ERANGE or EDOMAIN
// in errno. Its main purpose is to act as a focal point for changes in
// error handling.
//
// The default version of the Borland/Turbo C++ matherr() routine masks
// underflow and precision errors; others errors are considered
// fatal. The rationale for masking underflow and precision errors
// is that these are not errors according to the ANSI C spec. Consequently,
// you will get
// exp(-1000) = 0
// sin(1e100) = NAN
// without any error or warning, even though there is a total
// loss of precision in both cases. You can trap these errors
// by modifying matherr().
//
// The possible errors are DOMAIN, SING, OVERFLOW, UNDERFLOW, TLOSS,
// PLOSS and are listed in <math.h>. As explained above, UNDERFLOW and
// TLOSS are masked by the default matherr(). PLOSS is not
// supported by Borland/Turbo C++ and is not generated by any library
// functions. The remaining errors, DOMAIN, SING, and OVERFLOW, are
// fatal with the default matherr().
//
// You can modify matherr() to be a custom error handling routine (such
// as one that catches and resolves certain type of errors); the modified
// matherr() should return 0 if it failed to resolve the error, or non-zero
// if the error was resolved. When matherr() returns non-zero, no error
// message is printed, and errno is not changed.
//
// The default return value for matherr() is simply 0. matherr() can
// also modify e->retval, which propagates through _matherr() back to
// the original caller. When matherr() returns 0, (indicating that it
// was not able to resolve the error) _matherr() sets errno and prints
// an error message. When matherr() returns non-zero, (indicating that
// it was able to resolve the error), errno is not set and no output is
// generated messages are printed.
//
// The important thing is that we don't know what error handling you want,
/ but you are assured that all errors will arrive at matherr() with all
// the information you need to design a custom exception handler.
*/
int matherr(
struct exception *e /* Exception structure */
)
{
switch (e->type) {
case DOMAIN:
/* Handle the square root of a negative number */
if (stricmp(e->name, "sqrt") == 0) {
e->retval = sqrt(fabs(e->arg1)) ;
return 1 ;
}
break ;
case UNDERFLOW:
/* Flush underflow to 0 */
e->retval = 0 ;
return 1 ;
}
/* Return the code showing the exception hasn't been handled */
return 0 ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -