|
|
//
// Copyright (c) 2000, Intel Corporation
// All rights reserved.
//
// Contributed 2/2/2000 by John Harrison, Ted Kubaska, Bob Norin, Shane Story, James
// Edwards, and Ping Tak Peter Tang of the Computational Software Lab, Intel Corporation.
//
// WARRANTY DISCLAIMER
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Intel Corporation is the author of this code, and requests that all
// problem reports or change requests be submitted to it directly at
// http://developer.intel.com/opensource.
//
// History
//==============================================================
// 2/02/00: Initial version.
// 2/12/01: Updated to be NT double precision specific.
#include <errno.h>
#include <stdio.h>
#include "libm_support.h"
/************************************************************/ /* matherrX function pointers and setusermatherrX functions */ /************************************************************/ int (*_pmatherr)(struct EXC_DECL_D*) = MATHERR_D;
/***********************************************/ /* error-handling function, libm_error_support */ /***********************************************/ void __libm_error_support(void *arg1,void *arg2,void *retval,error_types input_tag) {
struct _exception exc;
const char double_inf[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x7F}; const char double_huge[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x7F}; const char double_zero[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; const char double_neg_inf[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF}; const char double_neg_huge[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF}; const char double_neg_zero[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80};
#define RETVAL_HUGE_VALD *(double *)retval = *(double *) double_inf
#define RETVAL_NEG_HUGE_VALD *(double *)retval = *(double *) double_neg_inf
#define RETVAL_HUGED *(double *)retval = (double) *(float *)float_huge
#define RETVAL_NEG_HUGED *(double *)retval = (double) *(float *) float_neg_huge
#define RETVAL_ZEROD *(double *)retval = *(double *)double_zero
#define RETVAL_NEG_ZEROD *(double *)retval = *(double *)double_neg_zero
#define RETVAL_ONED *(double *)retval = 1.0
#define NOT_MATHERRD exc.arg1=*(double *)arg1;exc.arg2=*(double *)arg2;exc.retval=*(double *)retval;if(!_pmatherr(&exc))
#define NAMED exc.name
//
// These should work OK for MS because they are ints -
// leading underbars are not necessary.
//
#define DOMAIN 1
#define SING 2
#define OVERFLOW 3
#define UNDERFLOW 4
#define TLOSS 5
#define PLOSS 6
#define SINGD exc.type = SING
#define DOMAIND exc.type = DOMAIN
#define OVERFLOWD exc.type = OVERFLOW
#define UNDERFLOWD exc.type = UNDERFLOW
#define TLOSSD exc.type = TLOSS
#define INPUT_XD (exc.arg1=*(double*)arg1)
#define INPUT_YD (exc.arg1=*(double*)arg2)
#define INPUT_RESD (*(double *)retval)
#define WRITED_LOG_ZERO fputs("log: SING error\n",stderr)
#define WRITED_LOG_NEGATIVE fputs("log: DOMAIN error\n",stderr)
#define WRITED_LOG10_ZERO fputs("log10: SING error\n",stderr)
#define WRITED_LOG10_NEGATIVE fputs("log10: DOMAIN error\n",stderr)
#define WRITED_POW_ZERO_TO_ZERO fputs("pow(0,0): DOMAIN error\n",stderr)
#define WRITED_POW_ZERO_TO_NEGATIVE fputs("pow(0,negative): DOMAIN error\n",stderr)
#define WRITED_POW_NEG_TO_NON_INTEGER fputs("pow(negative,non-integer): DOMAIN error\n",stderr)
switch(input_tag) { case log_zero: /* log(0) */ { SINGD; NAMED="log"; NOT_MATHERRD {ERRNO_RANGE;} *(double *)retval = exc.retval; break; } case log_negative: /* log(x < 0) */ { DOMAIND; NAMED="log"; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case log10_zero: /* log10(0) */ { SINGD; NAMED="log10"; NOT_MATHERRD {ERRNO_RANGE;} *(double *)retval = exc.retval; break; } case log10_negative: /* log10(x < 0) */ { DOMAIND; NAMED="log10"; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case exp_overflow: /* exp overflow */ { OVERFLOWD; NAMED="exp"; NOT_MATHERRD {ERRNO_RANGE;} *(double *)retval = exc.retval; break; } case exp_underflow: /* exp underflow */ { UNDERFLOWD; NAMED="exp"; NOT_MATHERRD {} *(double *)retval = exc.retval; break; } case pow_zero_to_zero: /* pow 0**0 */ { DOMAIND; NAMED="pow"; RETVAL_ONED; break; } case pow_overflow: /* pow(x,y) overflow */ { OVERFLOWD; NAMED = "pow"; NOT_MATHERRD {ERRNO_RANGE;} *(double *)retval = exc.retval; break; } case pow_underflow: /* pow(x,y) underflow */ { UNDERFLOWD; NAMED = "pow"; NOT_MATHERRD {} *(double *)retval = exc.retval; break; } case pow_zero_to_negative: /* 0**neg */ { SINGD; NAMED = "pow"; NOT_MATHERRD {ERRNO_RANGE;} *(double *)retval = exc.retval; break; } case pow_neg_to_non_integer: /* neg**non_integral */ { DOMAIND; NAMED = "pow"; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case pow_nan_to_zero: /* pow(NaN,0.0) */ /* Special Error */ { DOMAIND; NAMED = "pow"; INPUT_XD; INPUT_YD; *(double *)retval = *(double *)arg1 * 1.0; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case log2_zero: /* log2(0) */ { SINGD; NAMED="log2"; NOT_MATHERRD {ERRNO_RANGE;} *(double *)retval = exc.retval; break; } case log2_negative: /* log2(negative) */ { DOMAIND; NAMED="log2"; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case exp2_underflow: /* exp2 underflow */ { UNDERFLOWD; NAMED="exp2"; NOT_MATHERRD {ERRNO_RANGE;} *(double *)retval = exc.retval; break; } case exp2_overflow: /* exp2 overflow */ { OVERFLOWD; NAMED="exp2"; NOT_MATHERRD {ERRNO_RANGE;} *(double *)retval = exc.retval; break; } case exp10_overflow: /* exp10 overflow */ { OVERFLOWD; NAMED="exp10"; NOT_MATHERRD {ERRNO_RANGE;} *(double *)retval = exc.retval; break; } case log_nan: /* log(NaN) */ { DOMAIND; NAMED="log"; *(double *)retval = *(double *)arg1 * 1.0; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case log10_nan: /* log10(NaN) */ { DOMAIND; NAMED="log10"; *(double *)retval = *(double *)arg1 * 1.0; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case exp_nan: /* exp(NaN) */ { DOMAIND; NAMED="exp"; *(double *)retval = *(double *)arg1 * 1.0; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case atan_nan: /* atan(NaN) */ { DOMAIND; NAMED="atan"; *(double *)retval = *(double *)arg1 * 1.0; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case ceil_nan: /* ceil(NaN) */ { DOMAIND; NAMED="ceil"; *(double *)retval = *(double *)arg1 * 1.0; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case floor_nan: /* floor(NaN) */ { DOMAIND; NAMED="floor"; *(double *)retval = *(double *)arg1 * 1.0; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case pow_nan: /* pow(NaN,*) or pow(*,NaN) */ { DOMAIND; NAMED="pow"; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } case modf_nan: /* modf(NaN) */ { DOMAIND; NAMED="modf"; *(double *)retval = *(double *)arg1 * 1.0; NOT_MATHERRD {ERRNO_DOMAIN;} *(double *)retval = exc.retval; break; } } return; }
|