1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
/* ieee-utils/fp-gnuc99.c
*
* Copyright (C) 2003, 2004, 2007 Brian Gough
*
* This program 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 3 of the License, or (at
* your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define _GNU_SOURCE 1
#include <math.h>
#include <stdio.h>
#include <fenv.h>
#include <gsl/gsl_ieee_utils.h>
#include <gsl/gsl_errno.h>
int
gsl_ieee_set_mode (int precision, int rounding, int exception_mask)
{
int mode;
switch (precision)
{
case GSL_IEEE_SINGLE_PRECISION:
GSL_ERROR ("single precision rounding is not supported by <fenv.h>",
GSL_EUNSUP) ;
break ;
case GSL_IEEE_DOUBLE_PRECISION:
GSL_ERROR ("double precision rounding is not supported by <fenv.h>",
GSL_EUNSUP) ;
break ;
case GSL_IEEE_EXTENDED_PRECISION:
GSL_ERROR ("extended precision rounding is not supported by <fenv.h>",
GSL_EUNSUP) ;
break ;
}
switch (rounding)
{
case GSL_IEEE_ROUND_TO_NEAREST:
#ifdef FE_TONEAREST
fesetround (FE_TONEAREST) ;
#else
GSL_ERROR ("round-to-nearest is not supported by <fenv.h>", GSL_EUNSUP) ;
#endif
break ;
case GSL_IEEE_ROUND_DOWN:
#ifdef FE_DOWNWARD
fesetround (FE_DOWNWARD) ;
#else
GSL_ERROR ("round-down is not supported by <fenv.h>", GSL_EUNSUP) ;
#endif
break ;
case GSL_IEEE_ROUND_UP:
#ifdef FE_UPWARD
fesetround (FE_UPWARD) ;
#else
GSL_ERROR ("round-up is not supported by <fenv.h>", GSL_EUNSUP) ;
#endif
break ;
case GSL_IEEE_ROUND_TO_ZERO:
#ifdef FE_TOWARDZERO
fesetround (FE_TOWARDZERO) ;
#else
GSL_ERROR ("round-toward-zero is not supported by <fenv.h>", GSL_EUNSUP) ;
#endif
break ;
default:
#ifdef FE_TONEAREST
fesetround (FE_TONEAREST) ;
#else
GSL_ERROR ("default round-to-nearest mode is not supported by <fenv.h>", GSL_EUNSUP) ;
#endif
}
/* Turn on all the exceptions apart from 'inexact' */
mode = 0;
#ifdef FE_INVALID
mode |= FE_INVALID;
#endif
#ifdef FE_DIVBYZERO
mode |= FE_DIVBYZERO;
#endif
#ifdef FE_OVERFLOW
mode |= FE_OVERFLOW ;
#endif
#ifdef FE_UNDERFLOW
mode |= FE_UNDERFLOW ;
#endif
if (exception_mask & GSL_IEEE_MASK_INVALID)
{
#ifdef FE_INVALID
mode &= ~ FE_INVALID ;
#else
GSL_ERROR ("invalid operation exception not supported by <fenv.h>",
GSL_EUNSUP);
#endif
}
if (exception_mask & GSL_IEEE_MASK_DENORMALIZED)
{
/* do nothing */
}
else
{
GSL_ERROR ("denormalized operand exception not supported by <fenv.h>. "
"Use 'mask-denormalized' to work around this.", GSL_EUNSUP) ;
}
if (exception_mask & GSL_IEEE_MASK_DIVISION_BY_ZERO)
{
#ifdef FE_DIVBYZERO
mode &= ~ FE_DIVBYZERO ;
#else
GSL_ERROR ("division by zero exception not supported by <fenv.h>",
GSL_EUNSUP);
#endif
}
if (exception_mask & GSL_IEEE_MASK_OVERFLOW)
{
#ifdef FE_OVERFLOW
mode &= ~ FE_OVERFLOW ;
#else
GSL_ERROR ("overflow exception not supported by <fenv.h>", GSL_EUNSUP);
#endif
}
if (exception_mask & GSL_IEEE_MASK_UNDERFLOW)
{
#ifdef FE_UNDERFLOW
mode &= ~ FE_UNDERFLOW ;
#else
GSL_ERROR ("underflow exception not supported by <fenv.h>", GSL_EUNSUP);
#endif
}
if (exception_mask & GSL_IEEE_TRAP_INEXACT)
{
#ifdef FE_INEXACT
mode |= FE_INEXACT ;
#else
GSL_ERROR ("inexact exception not supported by <fenv.h>", GSL_EUNSUP);
#endif
}
else
{
#ifdef FE_INEXACT
mode &= ~ FE_INEXACT ;
#else
/* do nothing */
#endif
}
#if HAVE_DECL_FEENABLEEXCEPT
feenableexcept (mode) ;
#elif HAVE_DECL_FESETTRAPENABLE
fesettrapenable (mode);
#else
GSL_ERROR ("unknown exception trap method", GSL_EUNSUP)
#endif
return GSL_SUCCESS ;
}
|