mirror of
https://github.com/glest/glest-source.git
synced 2025-08-12 03:14:00 +02:00
Fixed the god-awful indentation
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@@ -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
@@ -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
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
*/
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user