Add functions for checking underflow

This commit is contained in:
Andreas Fabri 2011-08-17 14:02:29 +00:00
parent f5419ffe4e
commit 9d19f67d5c
4 changed files with 208 additions and 0 deletions

View File

@ -0,0 +1,68 @@
// Copyright (c) 2010-2011 GeometryFactory Sarl (France)
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Laurent Rineau
// The main goal of FPU.h is to define functions or macros to modify the
// control word of the FPU, to:
// - set the precision to 53 bits of mantissa,
// - get/set the rounding mode.
//
// The goal of FPU_extension.h is to define inline functions similar to
// feclearexcept and fetestexcept of C99.
//
// For the moment, only i386 and x64 processors are supported, with MSVC,
// gcc, or the Intel compiler suite. Otherwise, the non-inline functions of
// C99 are used.
#ifndef CGAL_FPU_EXTENSION_H
#define CGAL_FPU_EXTENSION_H
#if __i386__ && !defined __PGI && !defined __SUNPRO_CC
# ifdef CGAL_SAFE_SSE2
# include <CGAL/FPU_gcc_i386_sse2.h>
# else
# include <CGAL/FPU_gcc_i386.h>
# endif
#elif defined _MSC_VER
# include <CGAL/FPU_msvc.h>
#else
// generic functions, using C99
extern "C" {
# include <fenv.h>
}
namespace CGAL {
inline int
feclearexcept(int exceptions) {
return ::feclearexcept(exceptions);
}
inline int
fetestexcept(int exceptions) {
return ::fetestexcept(exceptions);
}
} // end namespace CGAL
#endif // use fenv
#endif // CGAL_FPU_EXTENSION_H

View File

@ -0,0 +1,41 @@
// Copyright (c) 2010-2011 GeometryFactory Sarl (France)
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Laurent Rineau
extern "C" {
#include <fenv.h>
}
namespace CGAL {
// brute-force replacement for C99 (which does not require an inline-function)
inline int
feclearexcept(int exceptions) {
// TODO: clear only given exceptions
asm volatile("fnclex");
return 0;
}
inline int
fetestexcept(int exceptions) {
int status;
asm volatile("fnstsw %0" : "=m" (status));
return status & exceptions;
}
} // end namespace CGAL

View File

@ -0,0 +1,44 @@
// Copyright (c) 2010-2011 GeometryFactory Sarl (France)
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Laurent Rineau
extern "C" {
#include <fenv.h>
}
namespace CGAL {
// replacement for C99
inline int
feclearexcept(int exceptions) {
int mxcsr;
asm volatile("stmxcsr %0" : "=m" (mxcsr) );
mxcsr &= ~exceptions;
asm volatile("ldmxcsr %0" : : "m" (mxcsr) );
return 0;
}
inline int
fetestexcept(int exceptions) {
int status;
asm volatile("stmxcsr %0" : "=m" (status) );
return status & exceptions;
}
} // end namespace CGAL

View File

@ -0,0 +1,55 @@
// Copyright (c) 2010-2011 GeometryFactory Sarl (France)
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Laurent Rineau
#include <cfloat>
#ifndef FE_INVALID
# define FE_INEXACT _EM_INEXACT
# define FE_UNDERFLOW _EM_UNDERFLOW
# define FE_OVERFLOW _EM_OVERFLOW
# define FE_DIVBYZERO _EM_ZERODIVIDE
# define FE_INVALID _EM_INVALID
#endif
namespace CGAL {
// replacement for C99 functions
inline int
feclearexcept(int exceptions) {
_clearfp();
return 0;
}
inline int
fetestexcept(int exceptions)
{
#if defined(_M_IX86) && _M_IX86_FP > 0
// On x86/x64 processors, when SSE is used.
unsigned int i1;
unsigned int i2;
_statusfp2(&i1, &i2);
return (i1 & exceptions) | (i2 & exceptions);
#else
// On x86 processors without SSE, or on other processors supported by MSVC
return _statusfp() & exceptions;
#endif
}
} // end namespace CGAL