Fixed the god-awful indentation

This commit is contained in:
mathusummut
2018-05-06 00:01:36 +02:00
parent 643e3820f5
commit 35b7b1f1a6
459 changed files with 204893 additions and 217545 deletions

View File

@@ -13,7 +13,7 @@
#ifndef FPUCHECK_H
#define FPUCHECK_H
//#include "LogOutput.h"
//#include "LogOutput.h"
#include "util.h"
#include "../../include/platform/common/streflop_cond.h"
@@ -25,16 +25,16 @@
e.g. `assert(good_fpu_control_registers());'
For reference, the layout of the MXCSR register:
FZ:RC:RC:PM:UM:OM:ZM:DM:IM:Rsvd:PE:UE:OE:ZE:DE:IE
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
FZ:RC:RC:PM:UM:OM:ZM:DM:IM:Rsvd:PE:UE:OE:ZE:DE:IE
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Spring1: 0 0 0 1 1 1 0 1 0 0 0 0 0 0 0 0 = 0x1D00 = 7424
Spring2: 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 = 0x1F80 = 8064
Default: 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 = 0x1F80 = 8064
MaskRsvd:1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 = 0xFF80
And the layout of the 387 FPU control word register:
Rsvd:Rsvd:Rsvd:X:RC:RC:PC:PC:Rsvd:Rsvd:PM:UM:OM:ZM:DM:IM
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Rsvd:Rsvd:Rsvd:X:RC:RC:PC:PC:Rsvd:Rsvd:PM:UM:OM:ZM:DM:IM
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Spring1: 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 0 = 0x003A = 58
Spring2: 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 = 0x003F = 63
Default: 0 0 0 0 0 0 1 1 0 0 1 1 1 1 1 1 = 0x033F = 831
@@ -66,12 +66,11 @@ MaskRsvd: 0 0 0 1 1 1 1 1 0 0 1 1 1 1 1 1 = 0x1F3F
Source: Intel Architecture Software Development Manual, Volume 1, Basic Architecture
*/
static inline void good_fpu_control_registers(const char* text, const char *file=NULL, const char *classname=NULL, const int line=-1)
{
static inline void good_fpu_control_registers(const char* text, const char *file = NULL, const char *classname = NULL, const int line = -1) {
const char *outText = text;
char szBuf[256]="";
if(outText == NULL) {
sprintf(szBuf,"In [%s::%s Line: %d]",file=NULL, classname, line);
char szBuf[256] = "";
if (outText == NULL) {
sprintf(szBuf, "In [%s::%s Line: %d]", file = NULL, classname, line);
outText = &szBuf[0];
}
// We are paranoid.
@@ -80,38 +79,38 @@ static inline void good_fpu_control_registers(const char* text, const char *file
fenv_t fenv;
fegetenv(&fenv);
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML) // -fsignaling-nans
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML) // -fsignaling-nans
bool ret = ((fenv.sse_mode & 0xFF80) == (0x1937 & 0xFF80) || (fenv.sse_mode & 0xFF80) == (0x1925 & 0xFF80)) &&
((fenv.x87_mode & 0x1F3F) == (0x0072 & 0x1F3F) || (fenv.x87_mode & 0x1F3F) == 0x003F);
#else
((fenv.x87_mode & 0x1F3F) == (0x0072 & 0x1F3F) || (fenv.x87_mode & 0x1F3F) == 0x003F);
#else
bool ret = ((fenv.sse_mode & 0xFF80) == 0x1D00 || (fenv.sse_mode & 0xFF80) == 0x1F80) &&
((fenv.x87_mode & 0x1F3F) == 0x003A || (fenv.x87_mode & 0x1F3F) == 0x003F);
#endif
((fenv.x87_mode & 0x1F3F) == 0x003A || (fenv.x87_mode & 0x1F3F) == 0x003F);
#endif
if (!ret) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"Sync warning: MXCSR 0x%04X instead of 0x1D00 or 0x1F80 (\"%s\")", fenv.sse_mode, outText);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"Sync warning: FPUCW 0x%04X instead of 0x003A or 0x003F (\"%s\")", fenv.x87_mode, outText);
SystemFlags::OutputDebug(SystemFlags::debugSystem, "Sync warning: MXCSR 0x%04X instead of 0x1D00 or 0x1F80 (\"%s\")", fenv.sse_mode, outText);
SystemFlags::OutputDebug(SystemFlags::debugSystem, "Sync warning: FPUCW 0x%04X instead of 0x003A or 0x003F (\"%s\")", fenv.x87_mode, outText);
// Set single precision floating point math.
streflop_init<streflop::Simple>();
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
feraiseexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW));
#endif
#endif
}
#elif defined(STREFLOP_X87)
fenv_t fenv;
fegetenv(&fenv);
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
bool ret = (fenv & 0x1F3F) == 0x0072 || (fenv & 0x1F3F) == 0x003F;
#else
#else
bool ret = (fenv & 0x1F3F) == 0x003A || (fenv & 0x1F3F) == 0x003F;
#endif
#endif
if (!ret) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"Sync warning: FPUCW 0x%04X instead of 0x003A or 0x003F (\"%s\")", fenv, outText);
SystemFlags::OutputDebug(SystemFlags::debugSystem, "Sync warning: FPUCW 0x%04X instead of 0x003A or 0x003F (\"%s\")", fenv, outText);
// Set single precision floating point math.
streflop_init<streflop::Simple>();
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
feraiseexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW));
#endif
#endif
}
#endif
}

View File

@@ -1,13 +1,13 @@
/*
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2012 Mark Vejvoda
Code released according to the GNU Lesser General Public License
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2012 Mark Vejvoda
Code released according to the GNU Lesser General Public License
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Please read the history and copyright information in the documentation provided with the source code
Please read the history and copyright information in the documentation provided with the source code
*/
/*
@@ -53,13 +53,13 @@
namespace streflop {
// We do not use libm, so let's copy a few flags and C99 functions
// Give warning in case these flags would be defined already, this is indication
// of potential confusion!
// We do not use libm, so let's copy a few flags and C99 functions
// Give warning in case these flags would be defined already, this is indication
// of potential confusion!
#if defined(FE_INVALID) || defined(FE_DENORMAL) || defined(FE_DIVBYZERO) || defined(FE_OVERFLOW) || defined(FE_UNDERFLOW) || defined(FE_INEXACT) || defined(FE_DOWNWARD) || defined(FE_TONEAREST) || defined(FE_TOWARDZERO) || defined(FE_UPWARD)
#warning STREFLOP: FE_XXX flags were already defined and will be redefined! Check you do not use the system libm.
#warning STREFLOP : FE_XXX flags were already defined and will be redefined!Check you do not use the system libm.
#undef FE_INVALID
#undef FE_DENORMAL
#undef FE_DIVBYZERO
@@ -75,74 +75,74 @@ namespace streflop {
#endif // defined(FE_INVALID) || ...
// Flags for FPU exceptions
enum FPU_Exceptions {
// Flags for FPU exceptions
enum FPU_Exceptions {
// Invalid operation. If not signaling, gives NaN instead
FE_INVALID = 0x0001,
#define FE_INVALID FE_INVALID
// Invalid operation. If not signaling, gives NaN instead
FE_INVALID = 0x0001,
#define FE_INVALID FE_INVALID
// Extension: for x86 and SSE
// Denormal operand. If not signaling, use denormal arithmetic as usual
FE_DENORMAL = 0x0002,
#define FE_DENORMAL FE_DENORMAL
// Extension: for x86 and SSE
// Denormal operand. If not signaling, use denormal arithmetic as usual
FE_DENORMAL = 0x0002,
#define FE_DENORMAL FE_DENORMAL
// Division by zero. If not signaling, uses +/- infinity
FE_DIVBYZERO = 0x0004,
#define FE_DIVBYZERO FE_DIVBYZERO
// Division by zero. If not signaling, uses +/- infinity
FE_DIVBYZERO = 0x0004,
#define FE_DIVBYZERO FE_DIVBYZERO
// Overflow. If not signaling, round to nearest (including infinity) according to rounding mode
FE_OVERFLOW = 0x0008,
#define FE_OVERFLOW FE_OVERFLOW
// Overflow. If not signaling, round to nearest (including infinity) according to rounding mode
FE_OVERFLOW = 0x0008,
#define FE_OVERFLOW FE_OVERFLOW
// Underflow. If not signaling, use 0 instead
FE_UNDERFLOW = 0x0010,
#define FE_UNDERFLOW FE_UNDERFLOW
// Underflow. If not signaling, use 0 instead
FE_UNDERFLOW = 0x0010,
#define FE_UNDERFLOW FE_UNDERFLOW
// Rounding was not exact (ex: sqrt(2) is never exact) or when overflow causes rounding
FE_INEXACT = 0x0020,
#define FE_INEXACT FE_INEXACT
// Rounding was not exact (ex: sqrt(2) is never exact) or when overflow causes rounding
FE_INEXACT = 0x0020,
#define FE_INEXACT FE_INEXACT
// Combination of all the above
FE_ALL_EXCEPT = 0x003F
#define FE_ALL_EXCEPT FE_ALL_EXCEPT
};
// Combination of all the above
FE_ALL_EXCEPT = 0x003F
#define FE_ALL_EXCEPT FE_ALL_EXCEPT
};
// Flags for FPU rounding modes
enum FPU_RoundMode {
FE_TONEAREST = 0x0000,
#define FE_TONEAREST FE_TONEAREST
// Flags for FPU rounding modes
enum FPU_RoundMode {
FE_TONEAREST = 0x0000,
#define FE_TONEAREST FE_TONEAREST
FE_DOWNWARD = 0x0400,
#define FE_DOWNWARD FE_DOWNWARD
FE_DOWNWARD = 0x0400,
#define FE_DOWNWARD FE_DOWNWARD
FE_UPWARD = 0x0800,
#define FE_UPWARD FE_UPWARD
FE_UPWARD = 0x0800,
#define FE_UPWARD FE_UPWARD
FE_TOWARDZERO = 0x0C00
#define FE_TOWARDZERO FE_TOWARDZERO
};
FE_TOWARDZERO = 0x0C00
#define FE_TOWARDZERO FE_TOWARDZERO
};
/* Note: SSE control word, bits 0..15
0->5: Run-time status flags
6: DAZ (denormals are zero, i.e. don't use denormals if bit is 1)
7->12: Exception flags, same meaning as for the x87 ones
13,14: Rounding flags, same meaning as for the x87 ones
15: Flush to zero (FTZ) for automatic handling of underflow (default is NO)
*/
/* Note: SSE control word, bits 0..15
0->5: Run-time status flags
6: DAZ (denormals are zero, i.e. don't use denormals if bit is 1)
7->12: Exception flags, same meaning as for the x87 ones
13,14: Rounding flags, same meaning as for the x87 ones
15: Flush to zero (FTZ) for automatic handling of underflow (default is NO)
*/
// plan for portability
// plan for portability
#if defined(_MSC_VER)
#if _WIN64
// No fldcw intrinsics on Windows x64, punt to external asm
// Seems like using unsigned is better on windows x64: http://www.virtualdub.org/blog/pivot/entry.php?id=340
extern "C" { void streflop_winx64_fldcw(unsigned short mode); }
extern "C" { unsigned short streflop_winx64_fstcw(); }
extern "C" { void streflop_winx64_fclex(void); }
extern "C" { void streflop_winx64_stmxcsr(unsigned int mode); }
extern "C" { void streflop_winx64_ldmxcsr(unsigned int mode); }
extern "C" { void streflop_winx64_fldcw(unsigned short mode); }
extern "C" { unsigned short streflop_winx64_fstcw(); }
extern "C" { void streflop_winx64_fclex(void); }
extern "C" { void streflop_winx64_stmxcsr(unsigned int mode); }
extern "C" { void streflop_winx64_ldmxcsr(unsigned int mode); }
#define STREFLOP_FSTCW(cw) do { short tmp = 0; tmp = streflop_winx64_fstcw(); (cw) = tmp; } while (0)
#define STREFLOP_FLDCW(cw) do { short tmp = (cw); streflop_winx64_fldcw(tmp); } while (0)
@@ -172,381 +172,382 @@ extern "C" { void streflop_winx64_ldmxcsr(unsigned int mode); }
#if defined(STREFLOP_X87)
/// Raise exception for these flags
inline int feraiseexcept(FPU_Exceptions excepts) {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode &= ~( excepts ); // generate error for selection
STREFLOP_FLDCW(fpu_mode);
return 0;
}
inline int feraiseexcept(FPU_Exceptions excepts) {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode &= ~(excepts); // generate error for selection
STREFLOP_FLDCW(fpu_mode);
return 0;
}
/// Clear exceptions for these flags
inline int feclearexcept(int excepts) {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode |= excepts;
STREFLOP_FLDCW(fpu_mode);
return 0;
}
/// Clear exceptions for these flags
inline int feclearexcept(int excepts) {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode |= excepts;
STREFLOP_FLDCW(fpu_mode);
return 0;
}
/// Get current rounding mode
inline int fegetround() {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
return fpu_mode & 0x0C00;
}
/// Get current rounding mode
inline int fegetround() {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
return fpu_mode & 0x0C00;
}
/// Set a new rounding mode
inline int fesetround(FPU_RoundMode roundMode) {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode &= 0xF3FF; // clear current mode
fpu_mode |= roundMode; // sets new mode
STREFLOP_FLDCW(fpu_mode);
return 0;
}
/// Set a new rounding mode
inline int fesetround(FPU_RoundMode roundMode) {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode &= 0xF3FF; // clear current mode
fpu_mode |= roundMode; // sets new mode
STREFLOP_FLDCW(fpu_mode);
return 0;
}
typedef short int fenv_t;
typedef short int fenv_t;
/// Default env. Defined in Math.cpp to be 0, and initalized on first use to the permanent holder
extern fenv_t FE_DFL_ENV;
/// Default env. Defined in Math.cpp to be 0, and initalized on first use to the permanent holder
extern fenv_t FE_DFL_ENV;
/// Get FP env into the given structure
inline int fegetenv(fenv_t *envp) {
// check that default env exists, otherwise save it now
if (!FE_DFL_ENV) STREFLOP_FSTCW(FE_DFL_ENV);
// Now store env into argument
STREFLOP_FSTCW(*envp);
return 0;
}
/// Get FP env into the given structure
inline int fegetenv(fenv_t *envp) {
// check that default env exists, otherwise save it now
if (!FE_DFL_ENV) STREFLOP_FSTCW(FE_DFL_ENV);
// Now store env into argument
STREFLOP_FSTCW(*envp);
return 0;
}
/// Sets FP env from the given structure
inline int fesetenv(const fenv_t *envp) {
// check that default env exists, otherwise save it now
if (!FE_DFL_ENV) STREFLOP_FSTCW(FE_DFL_ENV);
// Now overwrite current env by argument
STREFLOP_FLDCW(*envp);
return 0;
}
/// Sets FP env from the given structure
inline int fesetenv(const fenv_t *envp) {
// check that default env exists, otherwise save it now
if (!FE_DFL_ENV) STREFLOP_FSTCW(FE_DFL_ENV);
// Now overwrite current env by argument
STREFLOP_FLDCW(*envp);
return 0;
}
/// get env and clear exceptions
inline int feholdexcept(fenv_t *envp) {
fegetenv(envp);
feclearexcept(FE_ALL_EXCEPT);
return 0;
}
/// get env and clear exceptions
inline int feholdexcept(fenv_t *envp) {
fegetenv(envp);
feclearexcept(FE_ALL_EXCEPT);
return 0;
}
template<typename T> inline void streflop_init() {
struct X {};
X Unknown_numeric_type;
// unknown types do not compile
T error = Unknown_numeric_type;
}
template<typename T> inline void streflop_init() {
struct X {
};
X Unknown_numeric_type;
// unknown types do not compile
T error = Unknown_numeric_type;
}
/// Initialize the FPU for the different types
/// this may also be called to switch between code sections using
/// different precisions
template<> inline void streflop_init<Simple>() {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode &= 0xFCFF; // 32 bits internal operations
STREFLOP_FLDCW(fpu_mode);
/// Initialize the FPU for the different types
/// this may also be called to switch between code sections using
/// different precisions
template<> inline void streflop_init<Simple>() {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode &= 0xFCFF; // 32 bits internal operations
STREFLOP_FLDCW(fpu_mode);
// Enable signaling nans if compiled with this option.
// Enable signaling nans if compiled with this option.
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
feraiseexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW));
feraiseexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW));
#endif
}
}
template<> inline void streflop_init<Double>() {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode &= 0xFCFF;
fpu_mode |= 0x0200; // 64 bits internal operations
STREFLOP_FLDCW(fpu_mode);
template<> inline void streflop_init<Double>() {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode &= 0xFCFF;
fpu_mode |= 0x0200; // 64 bits internal operations
STREFLOP_FLDCW(fpu_mode);
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
feraiseexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW));
feraiseexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW));
#endif
}
}
#if defined(Extended)
template<> inline void streflop_init<Extended>() {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode &= 0xFCFF;
fpu_mode |= 0x0300; // 80 bits internal operations
STREFLOP_FLDCW(fpu_mode);
template<> inline void streflop_init<Extended>() {
unsigned short fpu_mode;
STREFLOP_FSTCW(fpu_mode);
fpu_mode &= 0xFCFF;
fpu_mode |= 0x0300; // 80 bits internal operations
STREFLOP_FLDCW(fpu_mode);
#if defined(__SUPPORT_SNAN__) && !defined(USE_GML)
feraiseexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW));
feraiseexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW));
#endif
}
}
#endif // defined(Extended)
#elif defined(STREFLOP_SSE)
/// Raise exception for these flags
inline int feraiseexcept(FPU_Exceptions excepts) {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode &= ~( excepts ); // generate error for selection
STREFLOP_FLDCW(x87_mode);
inline int feraiseexcept(FPU_Exceptions excepts) {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode &= ~(excepts); // generate error for selection
STREFLOP_FLDCW(x87_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
sse_mode &= ~( excepts << 7 ); // generate error for selection
STREFLOP_LDMXCSR(sse_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
sse_mode &= ~(excepts << 7); // generate error for selection
STREFLOP_LDMXCSR(sse_mode);
return 0;
}
return 0;
}
/// Clear exceptions for these flags
inline int feclearexcept(int excepts) {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode |= excepts;
STREFLOP_FLDCW(x87_mode);
/// Clear exceptions for these flags
inline int feclearexcept(int excepts) {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode |= excepts;
STREFLOP_FLDCW(x87_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
sse_mode |= excepts << 7;
STREFLOP_LDMXCSR(sse_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
sse_mode |= excepts << 7;
STREFLOP_LDMXCSR(sse_mode);
return 0;
}
return 0;
}
/// Get current rounding mode
inline int fegetround() {
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
return (sse_mode>>3) & 0x00000C00;
}
/// Get current rounding mode
inline int fegetround() {
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
return (sse_mode >> 3) & 0x00000C00;
}
/// Set a new rounding mode
inline int fesetround(FPU_RoundMode roundMode) {
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
sse_mode &= 0xFFFF9FFF; // clear current mode
sse_mode |= roundMode<<3; // sets new mode
STREFLOP_LDMXCSR(sse_mode);
return 0;
}
/// Set a new rounding mode
inline int fesetround(FPU_RoundMode roundMode) {
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
sse_mode &= 0xFFFF9FFF; // clear current mode
sse_mode |= roundMode << 3; // sets new mode
STREFLOP_LDMXCSR(sse_mode);
return 0;
}
/// stores both x87 and SSE words
struct fenv_t {
int sse_mode;
short int x87_mode;
};
/// stores both x87 and SSE words
struct fenv_t {
int sse_mode;
short int x87_mode;
};
/// Default env. Defined in Math.cpp, structs are initialized to 0
extern fenv_t FE_DFL_ENV;
/// Default env. Defined in Math.cpp, structs are initialized to 0
extern fenv_t FE_DFL_ENV;
/// Get FP env into the given structure
inline int fegetenv(fenv_t *envp) {
// check that default env exists, otherwise save it now
if (!FE_DFL_ENV.x87_mode) STREFLOP_FSTCW(FE_DFL_ENV.x87_mode);
// Now store env into argument
STREFLOP_FSTCW(envp->x87_mode);
/// Get FP env into the given structure
inline int fegetenv(fenv_t *envp) {
// check that default env exists, otherwise save it now
if (!FE_DFL_ENV.x87_mode) STREFLOP_FSTCW(FE_DFL_ENV.x87_mode);
// Now store env into argument
STREFLOP_FSTCW(envp->x87_mode);
// For SSE
if (!FE_DFL_ENV.sse_mode) STREFLOP_STMXCSR(FE_DFL_ENV.sse_mode);
// Now store env into argument
STREFLOP_STMXCSR(envp->sse_mode);
return 0;
}
// For SSE
if (!FE_DFL_ENV.sse_mode) STREFLOP_STMXCSR(FE_DFL_ENV.sse_mode);
// Now store env into argument
STREFLOP_STMXCSR(envp->sse_mode);
return 0;
}
/// Sets FP env from the given structure
inline int fesetenv(const fenv_t *envp) {
// check that default env exists, otherwise save it now
if (!FE_DFL_ENV.x87_mode) STREFLOP_FSTCW(FE_DFL_ENV.x87_mode);
// Now overwrite current env by argument
STREFLOP_FLDCW(envp->x87_mode);
/// Sets FP env from the given structure
inline int fesetenv(const fenv_t *envp) {
// check that default env exists, otherwise save it now
if (!FE_DFL_ENV.x87_mode) STREFLOP_FSTCW(FE_DFL_ENV.x87_mode);
// Now overwrite current env by argument
STREFLOP_FLDCW(envp->x87_mode);
// For SSE
if (!FE_DFL_ENV.sse_mode) STREFLOP_STMXCSR(FE_DFL_ENV.sse_mode);
// Now overwrite current env by argument
STREFLOP_LDMXCSR(envp->sse_mode);
return 0;
}
// For SSE
if (!FE_DFL_ENV.sse_mode) STREFLOP_STMXCSR(FE_DFL_ENV.sse_mode);
// Now overwrite current env by argument
STREFLOP_LDMXCSR(envp->sse_mode);
return 0;
}
/// get env and clear exceptions
inline int feholdexcept(fenv_t *envp) {
fegetenv(envp);
feclearexcept(FE_ALL_EXCEPT);
return 0;
}
/// get env and clear exceptions
inline int feholdexcept(fenv_t *envp) {
fegetenv(envp);
feclearexcept(FE_ALL_EXCEPT);
return 0;
}
template<typename T> inline void streflop_init() {
// Do nothing by default, or for unknown types
}
template<typename T> inline void streflop_init() {
// Do nothing by default, or for unknown types
}
/// Initialize the FPU for the different types
/// this may also be called to switch between code sections using
/// different precisions
template<> inline void streflop_init<Simple>() {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode &= 0xFCFF; // 32 bits internal operations
STREFLOP_FLDCW(x87_mode);
/// Initialize the FPU for the different types
/// this may also be called to switch between code sections using
/// different precisions
template<> inline void streflop_init<Simple>() {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode &= 0xFCFF; // 32 bits internal operations
STREFLOP_FLDCW(x87_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
#if defined(STREFLOP_NO_DENORMALS)
sse_mode |= 0x8040; // set DAZ and FTZ
sse_mode |= 0x8040; // set DAZ and FTZ
#else
sse_mode &= 0xFFFF7FBF; // clear DAZ and FTZ
sse_mode &= 0xFFFF7FBF; // clear DAZ and FTZ
#endif
STREFLOP_LDMXCSR(sse_mode);
}
STREFLOP_LDMXCSR(sse_mode);
}
template<> inline void streflop_init<Double>() {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode &= 0xFCFF;
x87_mode |= 0x0200; // 64 bits internal operations
STREFLOP_FLDCW(x87_mode);
template<> inline void streflop_init<Double>() {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode &= 0xFCFF;
x87_mode |= 0x0200; // 64 bits internal operations
STREFLOP_FLDCW(x87_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
#if defined(STREFLOP_NO_DENORMALS)
sse_mode |= 0x8040; // set DAZ and FTZ
sse_mode |= 0x8040; // set DAZ and FTZ
#else
sse_mode &= 0xFFFF7FBF; // clear DAZ and FTZ
sse_mode &= 0xFFFF7FBF; // clear DAZ and FTZ
#endif
STREFLOP_LDMXCSR(sse_mode);
}
STREFLOP_LDMXCSR(sse_mode);
}
#if defined(Extended)
template<> inline void streflop_init<Extended>() {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode &= 0xFCFF;
x87_mode |= 0x0300; // 80 bits internal operations
STREFLOP_FLDCW(x87_mode);
template<> inline void streflop_init<Extended>() {
// Just in case the compiler would store a value on the st(x) registers
unsigned short x87_mode;
STREFLOP_FSTCW(x87_mode);
x87_mode &= 0xFCFF;
x87_mode |= 0x0300; // 80 bits internal operations
STREFLOP_FLDCW(x87_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
int sse_mode;
STREFLOP_STMXCSR(sse_mode);
#if defined(STREFLOP_NO_DENORMALS)
sse_mode |= 0x8040; // set DAZ and FTZ
sse_mode |= 0x8040; // set DAZ and FTZ
#else
sse_mode &= 0xFFFF7FBF; // clear DAZ and FTZ
sse_mode &= 0xFFFF7FBF; // clear DAZ and FTZ
#endif
STREFLOP_LDMXCSR(sse_mode);
}
STREFLOP_LDMXCSR(sse_mode);
}
#endif // defined(Extended)
#elif defined(STREFLOP_SOFT)
/// Raise exception for these flags
inline int feraiseexcept(FPU_Exceptions excepts) {
// Use positive logic
SoftFloat::float_exception_realtraps |= excepts;
return 0;
}
inline int feraiseexcept(FPU_Exceptions excepts) {
// Use positive logic
SoftFloat::float_exception_realtraps |= excepts;
return 0;
}
/// Clear exceptions for these flags
inline int feclearexcept(int excepts) {
// Use positive logic
SoftFloat::float_exception_realtraps &= ~( excepts );
return 0;
}
/// Clear exceptions for these flags
inline int feclearexcept(int excepts) {
// Use positive logic
SoftFloat::float_exception_realtraps &= ~(excepts);
return 0;
}
/// Get current rounding mode
inline int fegetround() {
// see softfloat.h for the definition
switch (SoftFloat::float_rounding_mode) {
case SoftFloat::float_round_down: return FE_DOWNWARD;
case SoftFloat::float_round_up: return FE_UPWARD;
case SoftFloat::float_round_to_zero: return FE_TOWARDZERO;
default:; // is also initial mode
}
// case SoftFloat::float_round_nearest_even:
return FE_TONEAREST;
}
/// Get current rounding mode
inline int fegetround() {
// see softfloat.h for the definition
switch (SoftFloat::float_rounding_mode) {
case SoftFloat::float_round_down: return FE_DOWNWARD;
case SoftFloat::float_round_up: return FE_UPWARD;
case SoftFloat::float_round_to_zero: return FE_TOWARDZERO;
default:; // is also initial mode
}
// case SoftFloat::float_round_nearest_even:
return FE_TONEAREST;
}
/// Set a new rounding mode
inline int fesetround(FPU_RoundMode roundMode) {
// see softfloat.h for the definition
switch (roundMode) {
case FE_DOWNWARD: SoftFloat::float_rounding_mode = SoftFloat::float_round_down; return 0;
case FE_UPWARD: SoftFloat::float_rounding_mode = SoftFloat::float_round_up; return 0;
case FE_TOWARDZERO: SoftFloat::float_rounding_mode = SoftFloat::float_round_to_zero; return 0;
case FE_TONEAREST: SoftFloat::float_rounding_mode = SoftFloat::float_round_nearest_even; return 0;
}
// Error, invalid mode
return 1;
}
/// Set a new rounding mode
inline int fesetround(FPU_RoundMode roundMode) {
// see softfloat.h for the definition
switch (roundMode) {
case FE_DOWNWARD: SoftFloat::float_rounding_mode = SoftFloat::float_round_down; return 0;
case FE_UPWARD: SoftFloat::float_rounding_mode = SoftFloat::float_round_up; return 0;
case FE_TOWARDZERO: SoftFloat::float_rounding_mode = SoftFloat::float_round_to_zero; return 0;
case FE_TONEAREST: SoftFloat::float_rounding_mode = SoftFloat::float_round_nearest_even; return 0;
}
// Error, invalid mode
return 1;
}
/// SoftFloat environment comprises non-volatile state variables
struct fenv_t {
char tininess;
char rounding_mode;
int exception_realtraps;
};
/// SoftFloat environment comprises non-volatile state variables
struct fenv_t {
char tininess;
char rounding_mode;
int exception_realtraps;
};
/// Default env. Defined in Math.cpp, initialized to some invalid value for detection
extern fenv_t FE_DFL_ENV;
/// Default env. Defined in Math.cpp, initialized to some invalid value for detection
extern fenv_t FE_DFL_ENV;
/// Get FP env into the given structure
inline int fegetenv(fenv_t *envp) {
// check that default env exists, otherwise save it now
if (FE_DFL_ENV.tininess==42) {
// First use: save default environment now
FE_DFL_ENV.tininess = SoftFloat::float_detect_tininess;
FE_DFL_ENV.rounding_mode = SoftFloat::float_rounding_mode;
FE_DFL_ENV.exception_realtraps = SoftFloat::float_exception_realtraps;
}
// Now get the current env in the given argument
envp->tininess = SoftFloat::float_detect_tininess;
envp->rounding_mode = SoftFloat::float_rounding_mode;
envp->exception_realtraps = SoftFloat::float_exception_realtraps;
return 0;
}
/// Get FP env into the given structure
inline int fegetenv(fenv_t *envp) {
// check that default env exists, otherwise save it now
if (FE_DFL_ENV.tininess == 42) {
// First use: save default environment now
FE_DFL_ENV.tininess = SoftFloat::float_detect_tininess;
FE_DFL_ENV.rounding_mode = SoftFloat::float_rounding_mode;
FE_DFL_ENV.exception_realtraps = SoftFloat::float_exception_realtraps;
}
// Now get the current env in the given argument
envp->tininess = SoftFloat::float_detect_tininess;
envp->rounding_mode = SoftFloat::float_rounding_mode;
envp->exception_realtraps = SoftFloat::float_exception_realtraps;
return 0;
}
/// Sets FP env from the given structure
inline int fesetenv(const fenv_t *envp) {
// check that default env exists, otherwise save it now
if (FE_DFL_ENV.tininess==42) {
// First use: save default environment now
FE_DFL_ENV.tininess = SoftFloat::float_detect_tininess;
FE_DFL_ENV.rounding_mode = SoftFloat::float_rounding_mode;
FE_DFL_ENV.exception_realtraps = SoftFloat::float_exception_realtraps;
}
// Now get the current env in the given argument
SoftFloat::float_detect_tininess = envp->tininess;
SoftFloat::float_rounding_mode = envp->rounding_mode;
SoftFloat::float_exception_realtraps = envp->exception_realtraps;
return 0;
}
/// Sets FP env from the given structure
inline int fesetenv(const fenv_t *envp) {
// check that default env exists, otherwise save it now
if (FE_DFL_ENV.tininess == 42) {
// First use: save default environment now
FE_DFL_ENV.tininess = SoftFloat::float_detect_tininess;
FE_DFL_ENV.rounding_mode = SoftFloat::float_rounding_mode;
FE_DFL_ENV.exception_realtraps = SoftFloat::float_exception_realtraps;
}
// Now get the current env in the given argument
SoftFloat::float_detect_tininess = envp->tininess;
SoftFloat::float_rounding_mode = envp->rounding_mode;
SoftFloat::float_exception_realtraps = envp->exception_realtraps;
return 0;
}
/// get env and clear exceptions
inline int feholdexcept(fenv_t *envp) {
fegetenv(envp);
feclearexcept(FE_ALL_EXCEPT);
return 0;
}
/// get env and clear exceptions
inline int feholdexcept(fenv_t *envp) {
fegetenv(envp);
feclearexcept(FE_ALL_EXCEPT);
return 0;
}
template<typename T> inline void streflop_init() {
// Do nothing by default, or for unknown types
}
template<typename T> inline void streflop_init() {
// Do nothing by default, or for unknown types
}
/// Initialize the FPU for the different types
/// this may also be called to switch between code sections using
/// different precisions
template<> inline void streflop_init<Simple>() {
}
template<> inline void streflop_init<Double>() {
}
template<> inline void streflop_init<Extended>() {
}
/// Initialize the FPU for the different types
/// this may also be called to switch between code sections using
/// different precisions
template<> inline void streflop_init<Simple>() {
}
template<> inline void streflop_init<Double>() {
}
template<> inline void streflop_init<Extended>() {
}
#else // defined(STREFLOP_X87)
#error STREFLOP: Invalid combination or unknown FPU type.

View File

@@ -1,13 +1,13 @@
/*
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2012 Mark Vejvoda
Code released according to the GNU Lesser General Public License
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2012 Mark Vejvoda
Code released according to the GNU Lesser General Public License
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Please read the history and copyright information in the documentation provided with the source code
Please read the history and copyright information in the documentation provided with the source code
*/
#ifndef STREFLOP_INTEGER_TYPES_H
@@ -27,113 +27,113 @@
// Avoid conflict with system types, if any
namespace streflop {
// Template meta-programming: this is the "program" which variables are types and constants are int template arguments
// Algorithm: provide an expected size, and recursively increase the integer types till the size match
template<typename int_type, int expected_size, bool final_recursion> struct SizedTypeMaker {
};
// Template meta-programming: this is the "program" which variables are types and constants are int template arguments
// Algorithm: provide an expected size, and recursively increase the integer types till the size match
template<typename int_type, int expected_size, bool final_recursion> struct SizedTypeMaker {
};
// start by long long to provide the recursion terminal condition
// start by long long to provide the recursion terminal condition
// false : the expected_size does not exist: do not define a type, there will be a compilation error
template<int expected_size> struct SizedTypeMaker<long long, expected_size, false> {
// Error: Integer type with expected size does not exist
};
// false : the expected_size does not exist: do not define a type, there will be a compilation error
template<int expected_size> struct SizedTypeMaker<long long, expected_size, false> {
// Error: Integer type with expected size does not exist
};
// true: end recursion by defining the correct type to be long long
template<int expected_size> struct SizedTypeMaker<long long, expected_size, true> {
typedef long long final_type;
};
// true: end recursion by defining the correct type to be long long
template<int expected_size> struct SizedTypeMaker<long long, expected_size, true> {
typedef long long final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<long, expected_size, false> {
typedef typename SizedTypeMaker<long long, expected_size, (sizeof(long long)==expected_size)>::final_type final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<long, expected_size, false> {
typedef typename SizedTypeMaker<long long, expected_size, (sizeof(long long) == expected_size)>::final_type final_type;
};
// true: end recursion by defining the correct type to be long
template<int expected_size> struct SizedTypeMaker<long, expected_size, true> {
typedef long final_type;
};
// true: end recursion by defining the correct type to be long
template<int expected_size> struct SizedTypeMaker<long, expected_size, true> {
typedef long final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<int, expected_size, false> {
typedef typename SizedTypeMaker<long, expected_size, (sizeof(long)==expected_size)>::final_type final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<int, expected_size, false> {
typedef typename SizedTypeMaker<long, expected_size, (sizeof(long) == expected_size)>::final_type final_type;
};
// true: end recursion by defining the correct type to be int
template<int expected_size> struct SizedTypeMaker<int, expected_size, true> {
typedef int final_type;
};
// true: end recursion by defining the correct type to be int
template<int expected_size> struct SizedTypeMaker<int, expected_size, true> {
typedef int final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<short, expected_size, false> {
typedef typename SizedTypeMaker<int, expected_size, (sizeof(int)==expected_size)>::final_type final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<short, expected_size, false> {
typedef typename SizedTypeMaker<int, expected_size, (sizeof(int) == expected_size)>::final_type final_type;
};
// true: end recursion by defining the correct type to be short
template<int expected_size> struct SizedTypeMaker<short, expected_size, true> {
typedef short final_type;
};
// true: end recursion by defining the correct type to be short
template<int expected_size> struct SizedTypeMaker<short, expected_size, true> {
typedef short final_type;
};
// Do it again for unsigned types
// Do it again for unsigned types
// false : the expected_size does not exist: do not define a type, there will be a compilation error
template<int expected_size> struct SizedTypeMaker<unsigned long long, expected_size, false> {
// Error: Integer type with expected size does not exist
};
// false : the expected_size does not exist: do not define a type, there will be a compilation error
template<int expected_size> struct SizedTypeMaker<unsigned long long, expected_size, false> {
// Error: Integer type with expected size does not exist
};
// true: end recursion by defining the correct type to be long long
template<int expected_size> struct SizedTypeMaker<unsigned long long, expected_size, true> {
typedef unsigned long long final_type;
};
// true: end recursion by defining the correct type to be long long
template<int expected_size> struct SizedTypeMaker<unsigned long long, expected_size, true> {
typedef unsigned long long final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<unsigned long, expected_size, false> {
typedef typename SizedTypeMaker<unsigned long long, expected_size, (sizeof(unsigned long long)==expected_size)>::final_type final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<unsigned long, expected_size, false> {
typedef typename SizedTypeMaker<unsigned long long, expected_size, (sizeof(unsigned long long) == expected_size)>::final_type final_type;
};
// true: end recursion by defining the correct type to be long
template<int expected_size> struct SizedTypeMaker<unsigned long, expected_size, true> {
typedef unsigned long final_type;
};
// true: end recursion by defining the correct type to be long
template<int expected_size> struct SizedTypeMaker<unsigned long, expected_size, true> {
typedef unsigned long final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<unsigned int, expected_size, false> {
typedef typename SizedTypeMaker<unsigned long, expected_size, (sizeof(unsigned long)==expected_size)>::final_type final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<unsigned int, expected_size, false> {
typedef typename SizedTypeMaker<unsigned long, expected_size, (sizeof(unsigned long) == expected_size)>::final_type final_type;
};
// true: end recursion by defining the correct type to be int
template<int expected_size> struct SizedTypeMaker<unsigned int, expected_size, true> {
typedef unsigned int final_type;
};
// true: end recursion by defining the correct type to be int
template<int expected_size> struct SizedTypeMaker<unsigned int, expected_size, true> {
typedef unsigned int final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<unsigned short, expected_size, false> {
typedef typename SizedTypeMaker<unsigned int, expected_size, (sizeof(unsigned int)==expected_size)>::final_type final_type;
};
// false : recurse by increasing the integer type till it reaches the expected size
template<int expected_size> struct SizedTypeMaker<unsigned short, expected_size, false> {
typedef typename SizedTypeMaker<unsigned int, expected_size, (sizeof(unsigned int) == expected_size)>::final_type final_type;
};
// true: end recursion by defining the correct type to be short
template<int expected_size> struct SizedTypeMaker<unsigned short, expected_size, true> {
typedef unsigned short final_type;
};
// true: end recursion by defining the correct type to be short
template<int expected_size> struct SizedTypeMaker<unsigned short, expected_size, true> {
typedef unsigned short final_type;
};
// Utility to get an int type with the selected size IN BITS
template<int N> struct SizedInteger {
typedef typename SizedTypeMaker<short, (N/STREFLOP_INTEGER_TYPES_CHAR_BITS), (sizeof(short)==(N/STREFLOP_INTEGER_TYPES_CHAR_BITS))>::final_type Type;
};
template<int N> struct SizedUnsignedInteger {
typedef typename SizedTypeMaker<unsigned short, (N/STREFLOP_INTEGER_TYPES_CHAR_BITS), (sizeof(unsigned short)==(N/STREFLOP_INTEGER_TYPES_CHAR_BITS))>::final_type Type;
};
// Utility to get an int type with the selected size IN BITS
template<int N> struct SizedInteger {
typedef typename SizedTypeMaker<short, (N / STREFLOP_INTEGER_TYPES_CHAR_BITS), (sizeof(short) == (N / STREFLOP_INTEGER_TYPES_CHAR_BITS))>::final_type Type;
};
template<int N> struct SizedUnsignedInteger {
typedef typename SizedTypeMaker<unsigned short, (N / STREFLOP_INTEGER_TYPES_CHAR_BITS), (sizeof(unsigned short) == (N / STREFLOP_INTEGER_TYPES_CHAR_BITS))>::final_type Type;
};
// Specialize for size = STREFLOP_INTEGER_TYPES_CHAR_BITS
// Specialize for size = STREFLOP_INTEGER_TYPES_CHAR_BITS
template<> struct SizedInteger<STREFLOP_INTEGER_TYPES_CHAR_BITS> {
typedef char Type;
};
template<> struct SizedInteger<STREFLOP_INTEGER_TYPES_CHAR_BITS> {
typedef char Type;
};
template<> struct SizedUnsignedInteger<STREFLOP_INTEGER_TYPES_CHAR_BITS> {
typedef unsigned char Type;
};
template<> struct SizedUnsignedInteger<STREFLOP_INTEGER_TYPES_CHAR_BITS> {
typedef unsigned char Type;
};
}

View File

@@ -1,14 +1,14 @@
/*
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2010 Mark Vejvoda
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2010 Mark Vejvoda
Code released according to the GNU Lesser General Public License
Code released according to the GNU Lesser General Public License
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Please read the history and copyright information in the documentation provided with the source code
Please read the history and copyright information in the documentation provided with the source code
*/
#ifndef RANDOM_H
@@ -19,107 +19,115 @@
namespace streflop {
/** Random state holder object
Declare one of this per thread, and use it as context to the random functions
Object is properly set by the RandomInit functions
This allows it to remain POD type
*/
struct RandomState {
/** Random state holder object
Declare one of this per thread, and use it as context to the random functions
Object is properly set by the RandomInit functions
This allows it to remain POD type
*/
struct RandomState {
#if !defined(STREFLOP_RANDOM_GEN_SIZE)
#define STREFLOP_RANDOM_GEN_SIZE 32
#endif
// state vector
SizedUnsignedInteger<STREFLOP_RANDOM_GEN_SIZE>::Type mt[19968/STREFLOP_RANDOM_GEN_SIZE];
int mti;
// random seed that was used for initialization
SizedUnsignedInteger<32>::Type seed;
}
// state vector
SizedUnsignedInteger<STREFLOP_RANDOM_GEN_SIZE>::Type mt[19968 / STREFLOP_RANDOM_GEN_SIZE];
int mti;
// random seed that was used for initialization
SizedUnsignedInteger<32>::Type seed;
}
#ifdef __GNUC__
__attribute__ ((aligned (64))) // align state vector on cache line size
__attribute__((aligned(64))) // align state vector on cache line size
#endif
;
;
/// Default random state holder
extern RandomState DefaultRandomState;
/// Default random state holder
extern RandomState DefaultRandomState;
/** Initialize the random number generator with the given seed.
/** Initialize the random number generator with the given seed.
By default, the seed is taken from system time and printed out
so the experiment is reproducible by inputing the same seed again.
By default, the seed is taken from system time and printed out
so the experiment is reproducible by inputing the same seed again.
You can set here a previous seed to reproduce it.
You can set here a previous seed to reproduce it.
This interface allows independance from the actual RNG used,
and/or system functions.
This interface allows independance from the actual RNG used,
and/or system functions.
The RNG used is the Mersenne twister implementation by the
original authors Takuji Nishimura and Makoto Matsumoto.
The RNG used is the Mersenne twister implementation by the
original authors Takuji Nishimura and Makoto Matsumoto.
See also Random.cpp for more information.
*/
SizedUnsignedInteger<32>::Type RandomInit(RandomState& state = DefaultRandomState);
SizedUnsignedInteger<32>::Type RandomInit(SizedUnsignedInteger<32>::Type seed, RandomState& state = DefaultRandomState);
See also Random.cpp for more information.
*/
SizedUnsignedInteger<32>::Type RandomInit(RandomState& state = DefaultRandomState);
SizedUnsignedInteger<32>::Type RandomInit(SizedUnsignedInteger<32>::Type seed, RandomState& state = DefaultRandomState);
/// Returns the random seed that was used for the initialization
/// Defaults to 0 if the RNG is not yet initialized
SizedUnsignedInteger<32>::Type RandomSeed(RandomState& state = DefaultRandomState);
/// Returns the random seed that was used for the initialization
/// Defaults to 0 if the RNG is not yet initialized
SizedUnsignedInteger<32>::Type RandomSeed(RandomState& state = DefaultRandomState);
/** Returns a random number from a uniform distribution.
/** Returns a random number from a uniform distribution.
All integer types are supported, as well as Simple, Double, and Extended
All integer types are supported, as well as Simple, Double, and Extended
The Random(min, max) template takes as argument:
- bool: whether or not including the min bound
- bool: whether or not including the max bound
- type: to generate a number from that type, and decide on min/max bounds
Example: Double x = Random<true, false, Double>(7.0, 18.0)
This will return a Double number between 7.0 (included) and 18.0 (excluded)
This works for both float and integer types.
The Random(min, max) template takes as argument:
- bool: whether or not including the min bound
- bool: whether or not including the max bound
- type: to generate a number from that type, and decide on min/max bounds
Example: Double x = Random<true, false, Double>(7.0, 18.0)
This will return a Double number between 7.0 (included) and 18.0 (excluded)
This works for both float and integer types.
Aliases are named like RandomXY with X,Y = E,I for bounds Excluded,Included.
Example: RandomEI(min,max) will return a number between min (excluded) and max (included).
Aliases are named like RandomXY with X,Y = E,I for bounds Excluded,Included.
Example: RandomEI(min,max) will return a number between min (excluded) and max (included).
The Random() template returns a number of the given type chosen uniformly between
all representable numbers of that type.
- For integer types, this means what you expect: any int, char, whatever on the whole range
- For float types, just recall that there are as many representable floats in each range
2^x - 2^(x+1), this is what floating-point means
The Random() template returns a number of the given type chosen uniformly between
all representable numbers of that type.
- For integer types, this means what you expect: any int, char, whatever on the whole range
- For float types, just recall that there are as many representable floats in each range
2^x - 2^(x+1), this is what floating-point means
Notes:
- If min > max then the result is undefined.
- If you ask for an empty interval (like RandomEE with min==max) then the result is undefined.
- If a NaN value is passed to the float functions, NaN is returned.
- By order of performance, for float types, IE is fastest, then EI, then EE, then II. For integer
types, it happens that the order is II, IE and EI ex-aequo, and EE, but the difference is much
less pronounced than for the float types. Use IE preferably for floats, II for ints.
Notes:
- If min > max then the result is undefined.
- If you ask for an empty interval (like RandomEE with min==max) then the result is undefined.
- If a NaN value is passed to the float functions, NaN is returned.
- By order of performance, for float types, IE is fastest, then EI, then EE, then II. For integer
types, it happens that the order is II, IE and EI ex-aequo, and EE, but the difference is much
less pronounced than for the float types. Use IE preferably for floats, II for ints.
The floating-point functions always compute a random number with the maximum digits of precision,
taking care of bounds. That is, it uses the 1-2 interval as this is a power-of-two bounded interval,
so each representable number in that interval (matching a distinct bit pattern) is given exactly
the same weight. This is really a truly uniform distribution, unlike the 0-1 range (see note below).
That 1-2 interval is then converted to the min-max range, hopefully resulting in the loss of as
few random bits as possible. See also the additional functions below for better performance.
The floating-point functions always compute a random number with the maximum digits of precision,
taking care of bounds. That is, it uses the 1-2 interval as this is a power-of-two bounded interval,
so each representable number in that interval (matching a distinct bit pattern) is given exactly
the same weight. This is really a truly uniform distribution, unlike the 0-1 range (see note below).
That 1-2 interval is then converted to the min-max range, hopefully resulting in the loss of as
few random bits as possible. See also the additional functions below for better performance.
Note: Getting numbers in the 0-1 interval may be tricky. Half the 2^X exponents are in that range as
well as denormal numbers. This could result in an horrible loss of bits when scaling from one exponent
to another. Fortunately, the numbers in 1-2 are generated with maximum precision, and then subtracting 1.0
to get a number in 0-1 keeps that precision because all the numbers obtained this way are still perfectly
representable. Moreover, the minimum exponent reached this way is still far above the denormals range.
Note: Getting numbers in the 0-1 interval may be tricky. Half the 2^X exponents are in that range as
well as denormal numbers. This could result in an horrible loss of bits when scaling from one exponent
to another. Fortunately, the numbers in 1-2 are generated with maximum precision, and then subtracting 1.0
to get a number in 0-1 keeps that precision because all the numbers obtained this way are still perfectly
representable. Moreover, the minimum exponent reached this way is still far above the denormals range.
Note3: The random number generator MUST be initialized for this function to work correctly.
Note3: The random number generator MUST be initialized for this function to work correctly.
Note4: These functions are thread-safe if you use one RandomState object per thread (or if you
synchronize the access to a shared state object, of course).
*/
Note4: These functions are thread-safe if you use one RandomState object per thread (or if you
synchronize the access to a shared state object, of course).
*/
template<bool include_min, bool include_max, typename a_type> a_type Random(a_type min, a_type max, RandomState& state = DefaultRandomState);
// function that returns a random number on the whole possible range
template<typename a_type> a_type Random(RandomState& state = DefaultRandomState);
// Alias that can be useful too
template<typename a_type> inline a_type RandomIE(a_type min, a_type max, RandomState& state = DefaultRandomState) {return Random<true, false, a_type>(min, max, state);}
template<typename a_type> inline a_type RandomEI(a_type min, a_type max, RandomState& state = DefaultRandomState) {return Random<false, true, a_type>(min, max, state);}
template<typename a_type> inline a_type RandomEE(a_type min, a_type max, RandomState& state = DefaultRandomState) {return Random<false, false, a_type>(min, max, state);}
template<typename a_type> inline a_type RandomII(a_type min, a_type max, RandomState& state = DefaultRandomState) {return Random<true, true, a_type>(min, max, state);}
template<bool include_min, bool include_max, typename a_type> a_type Random(a_type min, a_type max, RandomState& state = DefaultRandomState);
// function that returns a random number on the whole possible range
template<typename a_type> a_type Random(RandomState& state = DefaultRandomState);
// Alias that can be useful too
template<typename a_type> inline a_type RandomIE(a_type min, a_type max, RandomState& state = DefaultRandomState) {
return Random<true, false, a_type>(min, max, state);
}
template<typename a_type> inline a_type RandomEI(a_type min, a_type max, RandomState& state = DefaultRandomState) {
return Random<false, true, a_type>(min, max, state);
}
template<typename a_type> inline a_type RandomEE(a_type min, a_type max, RandomState& state = DefaultRandomState) {
return Random<false, false, a_type>(min, max, state);
}
template<typename a_type> inline a_type RandomII(a_type min, a_type max, RandomState& state = DefaultRandomState) {
return Random<true, true, a_type>(min, max, state);
}
#define STREFLOP_RANDOM_MAKE_REAL(a_type) \
template<> a_type Random<a_type>(RandomState& state); \
template<> a_type Random<true, true, a_type>(a_type min, a_type max, RandomState& state); \
@@ -127,46 +135,62 @@ template<> a_type Random<true, false, a_type>(a_type min, a_type max, RandomStat
template<> a_type Random<false, true, a_type>(a_type min, a_type max, RandomState& state); \
template<> a_type Random<false, false, a_type>(a_type min, a_type max, RandomState& state);
STREFLOP_RANDOM_MAKE_REAL(char)
STREFLOP_RANDOM_MAKE_REAL(unsigned char)
STREFLOP_RANDOM_MAKE_REAL(short)
STREFLOP_RANDOM_MAKE_REAL(unsigned short)
STREFLOP_RANDOM_MAKE_REAL(int)
STREFLOP_RANDOM_MAKE_REAL(unsigned int)
STREFLOP_RANDOM_MAKE_REAL(long)
STREFLOP_RANDOM_MAKE_REAL(unsigned long)
STREFLOP_RANDOM_MAKE_REAL(long long)
STREFLOP_RANDOM_MAKE_REAL(unsigned long long)
STREFLOP_RANDOM_MAKE_REAL(char)
STREFLOP_RANDOM_MAKE_REAL(unsigned char)
STREFLOP_RANDOM_MAKE_REAL(short)
STREFLOP_RANDOM_MAKE_REAL(unsigned short)
STREFLOP_RANDOM_MAKE_REAL(int)
STREFLOP_RANDOM_MAKE_REAL(unsigned int)
STREFLOP_RANDOM_MAKE_REAL(long)
STREFLOP_RANDOM_MAKE_REAL(unsigned long)
STREFLOP_RANDOM_MAKE_REAL(long long)
STREFLOP_RANDOM_MAKE_REAL(unsigned long long)
/** Additional and faster functions for real numbers
These return a number in the 1..2 range, the base for all the other random functions
*/
template<bool include_min, bool include_max, typename a_type> a_type Random12(RandomState& state = DefaultRandomState);
// Alias that can be useful too
template<typename a_type> inline a_type Random12IE(RandomState& state = DefaultRandomState) {return Random12<true, false, a_type>(state);}
template<typename a_type> inline a_type Random12EI(RandomState& state = DefaultRandomState) {return Random12<false, true, a_type>(state);}
template<typename a_type> inline a_type Random12EE(RandomState& state = DefaultRandomState) {return Random12<false, false, a_type>(state);}
template<typename a_type> inline a_type Random12II(RandomState& state = DefaultRandomState) {return Random12<true, true, a_type>(state);}
/** Additional and faster functions for real numbers
These return a number in the 1..2 range, the base for all the other random functions
*/
template<bool include_min, bool include_max, typename a_type> a_type Random12(RandomState& state = DefaultRandomState);
// Alias that can be useful too
template<typename a_type> inline a_type Random12IE(RandomState& state = DefaultRandomState) {
return Random12<true, false, a_type>(state);
}
template<typename a_type> inline a_type Random12EI(RandomState& state = DefaultRandomState) {
return Random12<false, true, a_type>(state);
}
template<typename a_type> inline a_type Random12EE(RandomState& state = DefaultRandomState) {
return Random12<false, false, a_type>(state);
}
template<typename a_type> inline a_type Random12II(RandomState& state = DefaultRandomState) {
return Random12<true, true, a_type>(state);
}
/** Additional and faster functions for real numbers
/** Additional and faster functions for real numbers
These return a number in the 0..1 range by subtracting one to the 1..2 function
This avoids a multiplication for the min...max scaling
These return a number in the 0..1 range by subtracting one to the 1..2 function
This avoids a multiplication for the min...max scaling
Provided for convenience only, use the 1..2 range as the base random function
*/
template<bool include_min, bool include_max, typename a_type> inline a_type Random01(RandomState& state = DefaultRandomState) {
return Random12<include_min, include_max, a_type>(state) - a_type(1.0);
}
// Alias that can be useful too
template<typename a_type> inline a_type Random01IE(RandomState& state = DefaultRandomState) {return Random01<true, false, a_type>(state);}
template<typename a_type> inline a_type Random01EI(RandomState& state = DefaultRandomState) {return Random01<false, true, a_type>(state);}
template<typename a_type> inline a_type Random01EE(RandomState& state = DefaultRandomState) {return Random01<false, false, a_type>(state);}
template<typename a_type> inline a_type Random01II(RandomState& state = DefaultRandomState) {return Random01<true, true, a_type>(state);}
Provided for convenience only, use the 1..2 range as the base random function
*/
template<bool include_min, bool include_max, typename a_type> inline a_type Random01(RandomState& state = DefaultRandomState) {
return Random12<include_min, include_max, a_type>(state) - a_type(1.0);
}
// Alias that can be useful too
template<typename a_type> inline a_type Random01IE(RandomState& state = DefaultRandomState) {
return Random01<true, false, a_type>(state);
}
template<typename a_type> inline a_type Random01EI(RandomState& state = DefaultRandomState) {
return Random01<false, true, a_type>(state);
}
template<typename a_type> inline a_type Random01EE(RandomState& state = DefaultRandomState) {
return Random01<false, false, a_type>(state);
}
template<typename a_type> inline a_type Random01II(RandomState& state = DefaultRandomState) {
return Random01<true, true, a_type>(state);
}
/// Define all 12 and 01 functions only for real types
/// use the 12 function to generate the other
/// Define all 12 and 01 functions only for real types
/// use the 12 function to generate the other
#define STREFLOP_RANDOM_MAKE_REAL_FLOAT_TYPES(a_type) \
template<> a_type Random12<true, true, a_type>(RandomState& state); \
@@ -192,53 +216,53 @@ template<> inline a_type Random<false, false, a_type>(a_type min, a_type max, Ra
}
STREFLOP_RANDOM_MAKE_REAL_FLOAT_TYPES(Simple)
STREFLOP_RANDOM_MAKE_REAL_FLOAT_TYPES(Double)
STREFLOP_RANDOM_MAKE_REAL_FLOAT_TYPES(Simple)
STREFLOP_RANDOM_MAKE_REAL_FLOAT_TYPES(Double)
#if defined(Extended)
STREFLOP_RANDOM_MAKE_REAL_FLOAT_TYPES(Extended)
STREFLOP_RANDOM_MAKE_REAL_FLOAT_TYPES(Extended)
#endif
/**
Utility to get a number from a Normal distribution
The no argument version returns a distribution with mean 0, variance 1.
The 2 argument version takes the desired mean standard deviation.
Both are only defined over the floating-point types
/**
Utility to get a number from a Normal distribution
The no argument version returns a distribution with mean 0, variance 1.
The 2 argument version takes the desired mean standard deviation.
Both are only defined over the floating-point types
This uses the common polar-coordinate method to transform between uniform and normal
Step 1: generate a pair of numbers in the -1,1 x -1,1 square
Step 2: loop over to step 1 until it is also in the unit circle
Step 3: Convert using the property property (U1, U2) = (X,Y) * sqrt( -2 * log(D) / D)
with D = X*X+Y*Y the squared distance and log(D) the natural logarithm function
Step 4: Choose U1 or U2, they are independent (keep the other for the next call)
Step 5 (optional): Scale and translate U to a given mean, std_dev
This uses the common polar-coordinate method to transform between uniform and normal
Step 1: generate a pair of numbers in the -1,1 x -1,1 square
Step 2: loop over to step 1 until it is also in the unit circle
Step 3: Convert using the property property (U1, U2) = (X,Y) * sqrt( -2 * log(D) / D)
with D = X*X+Y*Y the squared distance and log(D) the natural logarithm function
Step 4: Choose U1 or U2, they are independent (keep the other for the next call)
Step 5 (optional): Scale and translate U to a given mean, std_dev
There may be better numerical methods, but I'm too lazy to implement them.
Any suggestion/contribution is welcome!
There may be better numerical methods, but I'm too lazy to implement them.
Any suggestion/contribution is welcome!
In particular, it seems quite horrendous to do computations close to the 0, in the 0-1 range,
where there may be denormals and the lot, to scale and translate later on. It would be better
to compute everything in another float interval (ex: 2 to 4 centered on 3 for the same square
has a uniform representable range of floats), and only then convert to the given mean/std_dev
at the last moment.
In particular, it seems quite horrendous to do computations close to the 0, in the 0-1 range,
where there may be denormals and the lot, to scale and translate later on. It would be better
to compute everything in another float interval (ex: 2 to 4 centered on 3 for the same square
has a uniform representable range of floats), and only then convert to the given mean/std_dev
at the last moment.
Note: An optional argument "secondary" may be specified, and in that case, a second number
indepedent from the first will be returned at negligible cost (in other words, by default, half the values
are thrown away)
*/
template<typename a_type> a_type NRandom(a_type mean, a_type std_dev, a_type *secondary = 0, RandomState& state = DefaultRandomState);
template<> Simple NRandom(Simple mean, Simple std_dev, Simple *secondary, RandomState& state);
template<> Double NRandom(Double mean, Double std_dev, Double *secondary, RandomState& state);
Note: An optional argument "secondary" may be specified, and in that case, a second number
indepedent from the first will be returned at negligible cost (in other words, by default, half the values
are thrown away)
*/
template<typename a_type> a_type NRandom(a_type mean, a_type std_dev, a_type *secondary = 0, RandomState& state = DefaultRandomState);
template<> Simple NRandom(Simple mean, Simple std_dev, Simple *secondary, RandomState& state);
template<> Double NRandom(Double mean, Double std_dev, Double *secondary, RandomState& state);
#if defined(Extended)
template<> Extended NRandom(Extended mean, Extended std_dev, Extended *secondary, RandomState& state);
template<> Extended NRandom(Extended mean, Extended std_dev, Extended *secondary, RandomState& state);
#endif
/// Simplified versions
template<typename a_type> a_type NRandom(a_type *secondary = 0, RandomState& state = DefaultRandomState);
template<> Simple NRandom(Simple *secondary, RandomState& state);
template<> Double NRandom(Double *secondary, RandomState& state);
/// Simplified versions
template<typename a_type> a_type NRandom(a_type *secondary = 0, RandomState& state = DefaultRandomState);
template<> Simple NRandom(Simple *secondary, RandomState& state);
template<> Double NRandom(Double *secondary, RandomState& state);
#if defined(Extended)
template<> Extended NRandom(Extended *secondary, RandomState& state);
template<> Extended NRandom(Extended *secondary, RandomState& state);
#endif
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,14 @@
/*
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2010 Mark Vejvoda
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2010 Mark Vejvoda
Code released according to the GNU Lesser General Public License
Code released according to the GNU Lesser General Public License
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Please read the history and copyright information in the documentation provided with the source code
Please read the history and copyright information in the documentation provided with the source code
*/
#ifdef STREFLOP_SOFT
@@ -28,41 +28,49 @@
#include "IntegerTypes.h"
namespace streflop {
// Generic define
template<int Nbits> struct SoftFloatWrapper {
// Generic define
template<int Nbits> struct SoftFloatWrapper {
char holder[(Nbits/STREFLOP_INTEGER_TYPES_CHAR_BITS)];
template<typename T> inline T& value() {return *reinterpret_cast<T*>(&holder);}
template<typename T> inline const T& value() const {return *reinterpret_cast<const T*>(&holder);}
char holder[(Nbits / STREFLOP_INTEGER_TYPES_CHAR_BITS)];
template<typename T> inline T& value() {
return *reinterpret_cast<T*>(&holder);
}
template<typename T> inline const T& value() const {
return *reinterpret_cast<const T*>(&holder);
}
/// Use dummy bool argument for construction from an already initialized holder
template<typename T> inline SoftFloatWrapper(T init_value, bool) {value<T>() = init_value;}
/// Use dummy bool argument for construction from an already initialized holder
template<typename T> inline SoftFloatWrapper(T init_value, bool) {
value<T>() = init_value;
}
/// Uninitialized object
inline SoftFloatWrapper() {}
/// Uninitialized object
inline SoftFloatWrapper() {
}
/// Conversion between different types. Also unfortunately includes otherwise perfectly fine copy constructor
SoftFloatWrapper(const SoftFloatWrapper<32>& f);
SoftFloatWrapper& operator=(const SoftFloatWrapper<32>& f);
SoftFloatWrapper(const SoftFloatWrapper<64>& f);
SoftFloatWrapper& operator=(const SoftFloatWrapper<64>& f);
SoftFloatWrapper(const SoftFloatWrapper<96>& f);
SoftFloatWrapper& operator=(const SoftFloatWrapper<96>& f);
/// Conversion between different types. Also unfortunately includes otherwise perfectly fine copy constructor
SoftFloatWrapper(const SoftFloatWrapper<32>& f);
SoftFloatWrapper& operator=(const SoftFloatWrapper<32>& f);
SoftFloatWrapper(const SoftFloatWrapper<64>& f);
SoftFloatWrapper& operator=(const SoftFloatWrapper<64>& f);
SoftFloatWrapper(const SoftFloatWrapper<96>& f);
SoftFloatWrapper& operator=(const SoftFloatWrapper<96>& f);
/// Destructor
inline ~SoftFloatWrapper() {}
/// Destructor
inline ~SoftFloatWrapper() {
}
/// Now the real fun, arithmetic operator overloading
SoftFloatWrapper& operator+=(const SoftFloatWrapper& f);
SoftFloatWrapper& operator-=(const SoftFloatWrapper& f);
SoftFloatWrapper& operator*=(const SoftFloatWrapper& f);
SoftFloatWrapper& operator/=(const SoftFloatWrapper& f);
bool operator==(const SoftFloatWrapper& f) const;
bool operator!=(const SoftFloatWrapper& f) const;
bool operator<(const SoftFloatWrapper& f) const;
bool operator<=(const SoftFloatWrapper& f) const;
bool operator>(const SoftFloatWrapper& f) const;
bool operator>=(const SoftFloatWrapper& f) const;
/// Now the real fun, arithmetic operator overloading
SoftFloatWrapper& operator+=(const SoftFloatWrapper& f);
SoftFloatWrapper& operator-=(const SoftFloatWrapper& f);
SoftFloatWrapper& operator*=(const SoftFloatWrapper& f);
SoftFloatWrapper& operator/=(const SoftFloatWrapper& f);
bool operator==(const SoftFloatWrapper& f) const;
bool operator!=(const SoftFloatWrapper& f) const;
bool operator<(const SoftFloatWrapper& f) const;
bool operator<=(const SoftFloatWrapper& f) const;
bool operator>(const SoftFloatWrapper& f) const;
bool operator>=(const SoftFloatWrapper& f) const;
#define STREFLOP_SOFT_WRAPPER_NATIVE_OPS(native_type) \
SoftFloatWrapper(const native_type f); \
@@ -79,21 +87,21 @@ template<int Nbits> struct SoftFloatWrapper {
bool operator>(const native_type f) const; \
bool operator>=(const native_type f) const;
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(float)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(double)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(long double)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(char)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(unsigned char)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(short)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(unsigned short)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(int)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(unsigned int)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(long)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(unsigned long)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(long long)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(unsigned long long)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(float)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(double)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(long double)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(char)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(unsigned char)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(short)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(unsigned short)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(int)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(unsigned int)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(long)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(unsigned long)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(long long)
STREFLOP_SOFT_WRAPPER_NATIVE_OPS(unsigned long long)
};
};
#define STREFLOP_SOFT_WRAPPER_MAKE_REAL_CLASS_OPS(N) \
template<> bool SoftFloatWrapper<N>::operator<(const SoftFloatWrapper& f) const; \
@@ -107,13 +115,13 @@ template<> bool SoftFloatWrapper<N>::operator<(const SoftFloatWrapper<N>& f) con
template<> bool SoftFloatWrapper<N>::operator<=(const SoftFloatWrapper<N>& f) const; \
template<> bool SoftFloatWrapper<N>::operator>(const SoftFloatWrapper<N>& f) const; \
template<> bool SoftFloatWrapper<N>::operator>=(const SoftFloatWrapper<N>& f) const;
STREFLOP_SOFT_WRAPPER_MAKE_REAL_CLASS_OPS(32)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_CLASS_OPS(64)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_CLASS_OPS(96)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_CLASS_OPS(32)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_CLASS_OPS(64)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_CLASS_OPS(96)
// Making real the conversion N->M
// Have to include default constructors for template overloading reasons
// Making real the conversion N->M
// Have to include default constructors for template overloading reasons
#define STREFLOP_SOFT_WRAPPER_MAKE_REAL_NM_CONVERSION(Nbits) \
template<> SoftFloatWrapper<Nbits>::SoftFloatWrapper(const SoftFloatWrapper<32>& f); \
template<> SoftFloatWrapper<Nbits>& SoftFloatWrapper<Nbits>::operator=(const SoftFloatWrapper<32>& f); \
@@ -121,9 +129,9 @@ template<> SoftFloatWrapper<Nbits>::SoftFloatWrapper(const SoftFloatWrapper<64>&
template<> SoftFloatWrapper<Nbits>& SoftFloatWrapper<Nbits>::operator=(const SoftFloatWrapper<64>& f); \
template<> SoftFloatWrapper<Nbits>::SoftFloatWrapper(const SoftFloatWrapper<96>& f); \
template<> SoftFloatWrapper<Nbits>& SoftFloatWrapper<Nbits>::operator=(const SoftFloatWrapper<96>& f);
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NM_CONVERSION(32)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NM_CONVERSION(64)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NM_CONVERSION(96)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NM_CONVERSION(32)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NM_CONVERSION(64)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NM_CONVERSION(96)
#define STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(N,native_type) \
@@ -141,64 +149,64 @@ template<> bool SoftFloatWrapper<N>::operator<=(const native_type f) const; \
template<> bool SoftFloatWrapper<N>::operator>(const native_type f) const; \
template<> bool SoftFloatWrapper<N>::operator>=(const native_type f) const;
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32,unsigned long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64,unsigned long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96,unsigned long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(32, unsigned long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(64, unsigned long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_NATIVE_OPS(96, unsigned long long)
// Generic versions are fine here, specializations in the cpp
// Generic versions are fine here, specializations in the cpp
/// binary operators
template<int N> SoftFloatWrapper<N> operator+(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2);
template<int N> SoftFloatWrapper<N> operator-(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2);
template<int N> SoftFloatWrapper<N> operator*(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2);
template<int N> SoftFloatWrapper<N> operator/(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2);
/// binary operators
template<int N> SoftFloatWrapper<N> operator+(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2);
template<int N> SoftFloatWrapper<N> operator-(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2);
template<int N> SoftFloatWrapper<N> operator*(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2);
template<int N> SoftFloatWrapper<N> operator/(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2);
#define STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_CLASS_OPS(N) \
template<> SoftFloatWrapper<N> operator+(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2); \
template<> SoftFloatWrapper<N> operator-(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2); \
template<> SoftFloatWrapper<N> operator*(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2); \
template<> SoftFloatWrapper<N> operator/(const SoftFloatWrapper<N>& f1, const SoftFloatWrapper<N>& f2);
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_CLASS_OPS(32)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_CLASS_OPS(64)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_CLASS_OPS(96)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_CLASS_OPS(32)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_CLASS_OPS(64)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_CLASS_OPS(96)
#define STREFLOP_SOFT_WRAPPER_BINARY_OPS(native_type) \
template<int N> SoftFloatWrapper<N> operator+(const SoftFloatWrapper<N>& f1, const native_type f2); \
@@ -216,19 +224,19 @@ template<int N> bool operator<=(const native_type value, const SoftFloatWrapper<
template<int N> bool operator>(const native_type value, const SoftFloatWrapper<N>& f); \
template<int N> bool operator>=(const native_type value, const SoftFloatWrapper<N>& f);
STREFLOP_SOFT_WRAPPER_BINARY_OPS(float)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(double)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(long double)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(char)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(unsigned char)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(short)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(unsigned short)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(int)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(unsigned int)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(long)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(unsigned long)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(long long)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(unsigned long long)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(float)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(double)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(long double)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(char)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(unsigned char)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(short)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(unsigned short)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(int)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(unsigned int)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(long)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(unsigned long)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(long long)
STREFLOP_SOFT_WRAPPER_BINARY_OPS(unsigned long long)
#define STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(N,native_type) \
@@ -246,56 +254,56 @@ template<> bool operator<(const native_type value, const SoftFloatWrapper<N>& f)
template<> bool operator<=(const native_type value, const SoftFloatWrapper<N>& f); \
template<> bool operator>(const native_type value, const SoftFloatWrapper<N>& f); \
template<> bool operator>=(const native_type value, const SoftFloatWrapper<N>& f);
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32,unsigned long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64,unsigned long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96,unsigned long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(32, unsigned long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(64, unsigned long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, float)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, long double)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, unsigned char)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, unsigned short)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, unsigned int)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, unsigned long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, long long)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_BINARY_OPS(96, unsigned long long)
/// Unary operators
template<int N> SoftFloatWrapper<N> operator-(const SoftFloatWrapper<N>& f);
template<int N> SoftFloatWrapper<N> operator+(const SoftFloatWrapper<N>& f);
/// Unary operators
template<int N> SoftFloatWrapper<N> operator-(const SoftFloatWrapper<N>& f);
template<int N> SoftFloatWrapper<N> operator+(const SoftFloatWrapper<N>& f);
#define STREFLOP_SOFT_WRAPPER_MAKE_REAL_UNARY_CLASS_OPS(N) \
template<> SoftFloatWrapper<N> operator-(const SoftFloatWrapper<N>& f); \
template<> SoftFloatWrapper<N> operator+(const SoftFloatWrapper<N>& f);
STREFLOP_SOFT_WRAPPER_MAKE_REAL_UNARY_CLASS_OPS(32)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_UNARY_CLASS_OPS(64)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_UNARY_CLASS_OPS(96)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_UNARY_CLASS_OPS(32)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_UNARY_CLASS_OPS(64)
STREFLOP_SOFT_WRAPPER_MAKE_REAL_UNARY_CLASS_OPS(96)
#endif

View File

@@ -1,13 +1,13 @@
/*
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2012 Mark Vejvoda
Code released according to the GNU Lesser General Public License
Code released according to the GNU Lesser General Public License
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Please read the history and copyright information in the documentation provided with the source code
Please read the history and copyright information in the documentation provided with the source code
*/
@@ -65,18 +65,18 @@
// Avoid conflict with system types, if any
namespace streflop {
// Use the assumption above for char
typedef char int8_t;
typedef unsigned char uint8_t;
// Use the assumption above for char
typedef char int8_t;
typedef unsigned char uint8_t;
// Now "run" the meta-program to define the types
// Entry point is (unsigned) short, then all types above are tried till the size match
typedef SizedInteger<16>::Type int16_t;
typedef SizedUnsignedInteger<16>::Type uint16_t;
typedef SizedInteger<32>::Type int32_t;
typedef SizedUnsignedInteger<32>::Type uint32_t;
typedef SizedInteger<64>::Type int64_t;
typedef SizedUnsignedInteger<64>::Type uint64_t;
// Now "run" the meta-program to define the types
// Entry point is (unsigned) short, then all types above are tried till the size match
typedef SizedInteger<16>::Type int16_t;
typedef SizedUnsignedInteger<16>::Type uint16_t;
typedef SizedInteger<32>::Type int32_t;
typedef SizedUnsignedInteger<32>::Type uint32_t;
typedef SizedInteger<64>::Type int64_t;
typedef SizedUnsignedInteger<64>::Type uint64_t;
}

View File

@@ -1,13 +1,13 @@
/*
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2012 Mark Vejvoda
Code released according to the GNU Lesser General Public License
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2012 Mark Vejvoda
Code released according to the GNU Lesser General Public License
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Please read the history and copyright information in the documentation provided with the source code
Please read the history and copyright information in the documentation provided with the source code
*/
#ifndef X87DenormalSquasher_H
@@ -16,10 +16,11 @@
/// This file should be included from within a streflop namespace
template<typename ValueType> inline void X87DenormalSquashFunction(ValueType& value) {
struct X {};
X Unknown_numeric_type;
// unknown types do not compile
value = Unknown_numeric_type;
struct X {
};
X Unknown_numeric_type;
// unknown types do not compile
value = Unknown_numeric_type;
}
// Use cmov instruction to avoid branching?
@@ -27,15 +28,15 @@ template<typename ValueType> inline void X87DenormalSquashFunction(ValueType& va
// Con: cmov forces an unconditional writeback to the mem just after read, which may be worse than the branch
template<> inline void X87DenormalSquashFunction<float>(float& value) {
if ((reinterpret_cast<int*>(&value)[0] & 0x7F800000) == 0) value = 0.0f;
if ((reinterpret_cast<int*>(&value)[0] & 0x7F800000) == 0) value = 0.0f;
}
template<> inline void X87DenormalSquashFunction<double>(double& value) {
if ((reinterpret_cast<int*>(&value)[1] & 0x7FF00000) == 0) value = 0.0;
if ((reinterpret_cast<int*>(&value)[1] & 0x7FF00000) == 0) value = 0.0;
}
template<> inline void X87DenormalSquashFunction<long double>(long double& value) {
if ((reinterpret_cast<short*>(&value)[4] & 0x7FFF) == 0) value = 0.0L;
if ((reinterpret_cast<short*>(&value)[4] & 0x7FFF) == 0) value = 0.0L;
}
/// Wrapper class for the denormal squashing of X87
@@ -46,34 +47,68 @@ template<> inline void X87DenormalSquashFunction<long double>(long double& value
template<typename ValueType> struct X87DenormalSquasher {
// Define value
ValueType value;
// Define value
ValueType value;
/// Uninitialized object
inline X87DenormalSquasher() {}
/// Uninitialized object
inline X87DenormalSquasher() {
}
/// Copy and conversion from other precisions
inline X87DenormalSquasher(const X87DenormalSquasher<float>& f) : value(f.value) {X87DenormalSquashFunction<ValueType>(value);}
inline X87DenormalSquasher(const X87DenormalSquasher<double>& f) : value(f.value) {X87DenormalSquashFunction<ValueType>(value);}
inline X87DenormalSquasher(const X87DenormalSquasher<long double>& f) : value(f.value) {X87DenormalSquashFunction<ValueType>(value);}
inline X87DenormalSquasher& operator=(const X87DenormalSquasher<float>& f) {value = f.value; X87DenormalSquashFunction<ValueType>(value); return *this;} // self-ref OK
inline X87DenormalSquasher& operator=(const X87DenormalSquasher<double>& f) {value = f.value; X87DenormalSquashFunction<ValueType>(value); return *this;} // self-ref OK
inline X87DenormalSquasher& operator=(const X87DenormalSquasher<long double>& f) {value = f.value; X87DenormalSquashFunction<ValueType>(value); return *this;} // self-ref OK
/// Copy and conversion from other precisions
inline X87DenormalSquasher(const X87DenormalSquasher<float>& f) : value(f.value) {
X87DenormalSquashFunction<ValueType>(value);
}
inline X87DenormalSquasher(const X87DenormalSquasher<double>& f) : value(f.value) {
X87DenormalSquashFunction<ValueType>(value);
}
inline X87DenormalSquasher(const X87DenormalSquasher<long double>& f) : value(f.value) {
X87DenormalSquashFunction<ValueType>(value);
}
inline X87DenormalSquasher& operator=(const X87DenormalSquasher<float>& f) {
value = f.value; X87DenormalSquashFunction<ValueType>(value); return *this;
} // self-ref OK
inline X87DenormalSquasher& operator=(const X87DenormalSquasher<double>& f) {
value = f.value; X87DenormalSquashFunction<ValueType>(value); return *this;
} // self-ref OK
inline X87DenormalSquasher& operator=(const X87DenormalSquasher<long double>& f) {
value = f.value; X87DenormalSquashFunction<ValueType>(value); return *this;
} // self-ref OK
/// Destructor
inline ~X87DenormalSquasher() {}
/// Destructor
inline ~X87DenormalSquasher() {
}
/// Now the real fun, arithmetic operator overloading
inline X87DenormalSquasher& operator+=(const X87DenormalSquasher& f) {value += f.value; X87DenormalSquashFunction<ValueType>(value); return *this;}
inline X87DenormalSquasher& operator-=(const X87DenormalSquasher& f) {value -= f.value; X87DenormalSquashFunction<ValueType>(value); return *this;}
inline X87DenormalSquasher& operator*=(const X87DenormalSquasher& f) {value *= f.value; X87DenormalSquashFunction<ValueType>(value); return *this;}
inline X87DenormalSquasher& operator/=(const X87DenormalSquasher& f) {value /= f.value; X87DenormalSquashFunction<ValueType>(value); return *this;}
inline bool operator==(const X87DenormalSquasher& f) const {return value == f.value;}
inline bool operator!=(const X87DenormalSquasher& f) const {return value != f.value;}
inline bool operator<(const X87DenormalSquasher& f) const {return value < f.value;}
inline bool operator<=(const X87DenormalSquasher& f) const {return value <= f.value;}
inline bool operator>(const X87DenormalSquasher& f) const {return value > f.value;}
inline bool operator>=(const X87DenormalSquasher& f) const {return value >= f.value;}
/// Now the real fun, arithmetic operator overloading
inline X87DenormalSquasher& operator+=(const X87DenormalSquasher& f) {
value += f.value; X87DenormalSquashFunction<ValueType>(value); return *this;
}
inline X87DenormalSquasher& operator-=(const X87DenormalSquasher& f) {
value -= f.value; X87DenormalSquashFunction<ValueType>(value); return *this;
}
inline X87DenormalSquasher& operator*=(const X87DenormalSquasher& f) {
value *= f.value; X87DenormalSquashFunction<ValueType>(value); return *this;
}
inline X87DenormalSquasher& operator/=(const X87DenormalSquasher& f) {
value /= f.value; X87DenormalSquashFunction<ValueType>(value); return *this;
}
inline bool operator==(const X87DenormalSquasher& f) const {
return value == f.value;
}
inline bool operator!=(const X87DenormalSquasher& f) const {
return value != f.value;
}
inline bool operator<(const X87DenormalSquasher& f) const {
return value < f.value;
}
inline bool operator<=(const X87DenormalSquasher& f) const {
return value <= f.value;
}
inline bool operator>(const X87DenormalSquasher& f) const {
return value > f.value;
}
inline bool operator>=(const X87DenormalSquasher& f) const {
return value >= f.value;
}
#define STREFLOP_X87DENORMAL_NATIVE_FLOAT_OPS(native_type) \
inline X87DenormalSquasher(const native_type f) {value = f; X87DenormalSquashFunction<ValueType>(value);} \
@@ -105,28 +140,36 @@ template<typename ValueType> struct X87DenormalSquasher {
inline bool operator>(const native_type f) const {return value > f;} \
inline bool operator>=(const native_type f) const {return value >= f;}
STREFLOP_X87DENORMAL_NATIVE_FLOAT_OPS(float)
STREFLOP_X87DENORMAL_NATIVE_FLOAT_OPS(double)
STREFLOP_X87DENORMAL_NATIVE_FLOAT_OPS(long double)
STREFLOP_X87DENORMAL_NATIVE_FLOAT_OPS(float)
STREFLOP_X87DENORMAL_NATIVE_FLOAT_OPS(double)
STREFLOP_X87DENORMAL_NATIVE_FLOAT_OPS(long double)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(char)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(unsigned char)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(short)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(unsigned short)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(int)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(unsigned int)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(long)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(unsigned long)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(long long)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(unsigned long long)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(char)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(unsigned char)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(short)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(unsigned short)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(int)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(unsigned int)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(long)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(unsigned long)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(long long)
STREFLOP_X87DENORMAL_NATIVE_INT_OPS(unsigned long long)
};
/// binary operators
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator+(const X87DenormalSquasher<ValueType>& f1, const X87DenormalSquasher<ValueType>& f2) {return X87DenormalSquasher<ValueType>(f1.value + f2.value);}
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator-(const X87DenormalSquasher<ValueType>& f1, const X87DenormalSquasher<ValueType>& f2) {return X87DenormalSquasher<ValueType>(f1.value - f2.value);}
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator*(const X87DenormalSquasher<ValueType>& f1, const X87DenormalSquasher<ValueType>& f2) {return X87DenormalSquasher<ValueType>(f1.value * f2.value);}
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator/(const X87DenormalSquasher<ValueType>& f1, const X87DenormalSquasher<ValueType>& f2) {return X87DenormalSquasher<ValueType>(f1.value / f2.value);}
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator+(const X87DenormalSquasher<ValueType>& f1, const X87DenormalSquasher<ValueType>& f2) {
return X87DenormalSquasher<ValueType>(f1.value + f2.value);
}
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator-(const X87DenormalSquasher<ValueType>& f1, const X87DenormalSquasher<ValueType>& f2) {
return X87DenormalSquasher<ValueType>(f1.value - f2.value);
}
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator*(const X87DenormalSquasher<ValueType>& f1, const X87DenormalSquasher<ValueType>& f2) {
return X87DenormalSquasher<ValueType>(f1.value * f2.value);
}
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator/(const X87DenormalSquasher<ValueType>& f1, const X87DenormalSquasher<ValueType>& f2) {
return X87DenormalSquasher<ValueType>(f1.value / f2.value);
}
#define STREFLOP_X87DENORMAL_FLOAT_BINARY(native_type) \
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator+(const X87DenormalSquasher<ValueType>& f1, const native_type f2) {return f1 + X87DenormalSquasher<ValueType>(f2);} \
@@ -176,8 +219,12 @@ STREFLOP_X87DENORMAL_INT_BINARY(long long)
STREFLOP_X87DENORMAL_INT_BINARY(unsigned long long)
/// Unary operators
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator-(const X87DenormalSquasher<ValueType>& f) {return X87DenormalSquasher<ValueType>(-f.value);}
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator+(const X87DenormalSquasher<ValueType>& f) {return X87DenormalSquasher<ValueType>(+f.value);}
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator-(const X87DenormalSquasher<ValueType>& f) {
return X87DenormalSquasher<ValueType>(-f.value);
}
template<typename ValueType> inline X87DenormalSquasher<ValueType> operator+(const X87DenormalSquasher<ValueType>& f) {
return X87DenormalSquasher<ValueType>(+f.value);
}
/*
/// Stream operators for output
@@ -185,12 +232,12 @@ template<typename ValueType> inline X87DenormalSquasher<ValueType> operator+(con
/// this function may not be reliable (they may depend on system rounding mode, etc.)
/// Still useful for debug output and to report results with a few significant digits
template<typename ValueType> inline std::ostream& operator<<(std::ostream& out, const X87DenormalSquasher<ValueType>& f) {
out << f.value;
return out;
out << f.value;
return out;
}
template<typename ValueType> inline std::istream& operator>>(std::istream& in, X87DenormalSquasher<ValueType>& f) {
in >> f.value;
return in;
in >> f.value;
return in;
}
*/

View File

@@ -1,14 +1,14 @@
/*
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2010 Mark Vejvoda
streflop: STandalone REproducible FLOating-Point
Copyright 2006 Nicolas Brodu
2010 Mark Vejvoda
Code released according to the GNU Lesser General Public License
Code released according to the GNU Lesser General Public License
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Heavily relies on GNU Libm, itself depending on netlib fplibm, GNU MP, and IBM MP lib.
Uses SoftFloat too.
Please read the history and copyright information in the documentation provided with the source code
Please read the history and copyright information in the documentation provided with the source code
*/
#ifndef STREFLOP_H
@@ -28,39 +28,39 @@
// First, define the numerical types
namespace streflop {
// Handle the 6 cells of the configuration array. See README.txt
// Handle the 6 cells of the configuration array. See README.txt
#if defined(STREFLOP_SSE)
// SSE always uses native types, denormals are handled by FPU flags
typedef float Simple;
typedef double Double;
#undef Extended
// SSE always uses native types, denormals are handled by FPU flags
typedef float Simple;
typedef double Double;
#undef Extended
#elif defined(STREFLOP_X87)
// X87 uses a wrapper for no denormals case
// X87 uses a wrapper for no denormals case
#if defined(STREFLOP_NO_DENORMALS)
#include "X87DenormalSquasher.h"
typedef X87DenormalSquasher<float> Simple;
typedef X87DenormalSquasher<double> Double;
typedef X87DenormalSquasher<long double> Extended;
#define Extended Extended
typedef X87DenormalSquasher<float> Simple;
typedef X87DenormalSquasher<double> Double;
typedef X87DenormalSquasher<long double> Extended;
#define Extended Extended
#else
// Use FPU flags for x87 with denormals
typedef float Simple;
typedef double Double;
typedef long double Extended;
#define Extended Extended
// Use FPU flags for x87 with denormals
typedef float Simple;
typedef double Double;
typedef long double Extended;
#define Extended Extended
#endif
#elif defined(STREFLOP_SOFT) && !defined(STREFLOP_NO_DENORMALS)
// Use SoftFloat wrapper
// Use SoftFloat wrapper
#include "SoftFloatWrapper.h"
typedef SoftFloatWrapper<32> Simple;
typedef SoftFloatWrapper<64> Double;
typedef SoftFloatWrapper<96> Extended;
#define Extended Extended
typedef SoftFloatWrapper<32> Simple;
typedef SoftFloatWrapper<64> Double;
typedef SoftFloatWrapper<96> Extended;
#define Extended Extended
#else
@@ -71,21 +71,21 @@ namespace streflop {
}
#if defined(STREFLOP_SSE) && defined(_MSC_VER)
// MSVC will not compile without the long double variants defined, so we either have to declare Extended:
// typedef long double Extended;
// #define Extended Extended
// or write some wrapper macros:
#define atan2l(a, b) atan2((double)a, (double)b)
#define cosl(a) cos((double)a)
#define expl(a) exp((double)a)
#define ldexpl(a, b) ldexp((double)a, (double)b)
#define logl(a) log((double)a)
#define powl(a,b) pow((double)a, (double)b)
#define sinl(a) sin((double)a)
#define sqrtl(a) sqrt((double)a)
#define tanl(a) tan((double)a)
#define frexpl(a, b) frexp((double)a, b)
// The wrappers are possibly the better choice for sync reasons.
// MSVC will not compile without the long double variants defined, so we either have to declare Extended:
// typedef long double Extended;
// #define Extended Extended
// or write some wrapper macros:
#define atan2l(a, b) atan2((double)a, (double)b)
#define cosl(a) cos((double)a)
#define expl(a) exp((double)a)
#define ldexpl(a, b) ldexp((double)a, (double)b)
#define logl(a) log((double)a)
#define powl(a,b) pow((double)a, (double)b)
#define sinl(a) sin((double)a)
#define sqrtl(a) sqrt((double)a)
#define tanl(a) tan((double)a)
#define frexpl(a, b) frexp((double)a, b)
// The wrappers are possibly the better choice for sync reasons.
#endif
// Include the FPU settings file, so the user can initialize the library

View File

@@ -11,15 +11,15 @@
extern "C" {
#endif
/// Initializes the FPU to single precision
void streflop_init_Simple();
/// Initializes the FPU to single precision
void streflop_init_Simple();
/// Initializes the FPU to double precision
void streflop_init_Double();
/// Initializes the FPU to double precision
void streflop_init_Double();
#if defined(Extended)
/// Initializes the FPU to extended precision
void streflop_init_Extended();
/// Initializes the FPU to extended precision
void streflop_init_Extended();
#endif // defined(Extended)
#ifdef __cplusplus