summaryrefslogtreecommitdiff
path: root/libmath/FPcontrol-Nt.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /libmath/FPcontrol-Nt.c
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'libmath/FPcontrol-Nt.c')
-rw-r--r--libmath/FPcontrol-Nt.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/libmath/FPcontrol-Nt.c b/libmath/FPcontrol-Nt.c
new file mode 100644
index 00000000..6a3fb22d
--- /dev/null
+++ b/libmath/FPcontrol-Nt.c
@@ -0,0 +1,82 @@
+#include "lib9.h"
+#include <float.h>
+#include "mathi.h"
+
+void
+FPinit(void)
+{
+ _controlfp(_EM_INEXACT,_MCW_EM); // abort on underflow, etc.
+}
+
+ulong
+getFPstatus(void)
+{
+ ulong fsr = 0, fsr32 = _statusfp();
+ if(fsr32&_SW_INEXACT) fsr |= INEX;
+ if(fsr32&_SW_OVERFLOW) fsr |= OVFL;
+ if(fsr32&_SW_UNDERFLOW) fsr |= UNFL;
+ if(fsr32&_SW_ZERODIVIDE) fsr |= ZDIV;
+ if(fsr32&_SW_INVALID) fsr |= INVAL;
+ return fsr;
+}
+
+ulong
+FPstatus(ulong fsr, ulong mask)
+{
+ ulong old = getFPstatus();
+ fsr = (fsr&mask) | (old&~mask);
+ if(fsr!=old){
+ _clearfp();
+ if(fsr){
+ ulong fcr = _controlfp(0,0);
+ double x = 1., y = 1e200, z = 0.;
+ _controlfp(_MCW_EM,_MCW_EM);
+ if(fsr&INEX) z = x + y;
+ if(fsr&OVFL) z = y*y;
+ if(fsr&UNFL) z = (x/y)/y;
+ if(fsr&ZDIV) z = x/z;
+ if(fsr&INVAL) z = z/z;
+ _controlfp(fcr,_MCW_EM);
+ }
+ }
+ return(old&mask);
+}
+
+ulong
+getFPcontrol(void)
+{
+ ulong fcr, fcr32 = _controlfp(0,0);
+ switch(fcr32&_MCW_RC){
+ case _RC_NEAR: fcr = RND_NR; break;
+ case _RC_DOWN: fcr = RND_NINF; break;
+ case _RC_UP: fcr = RND_PINF; break;
+ case _RC_CHOP: fcr = RND_Z; break;
+ }
+ if(!(fcr32&_EM_INEXACT)) fcr |= INEX;
+ if(!(fcr32&_EM_OVERFLOW)) fcr |= OVFL;
+ if(!(fcr32&_EM_UNDERFLOW)) fcr |= UNFL;
+ if(!(fcr32&_EM_ZERODIVIDE)) fcr |= ZDIV;
+ if(!(fcr32&_EM_INVALID)) fcr |= INVAL;
+ return fcr;
+}
+
+ulong
+FPcontrol(ulong fcr, ulong mask)
+{
+ ulong old = getFPcontrol();
+ ulong fcr32 = _MCW_EM, mask32 = _MCW_RC|_MCW_EM;
+ fcr = (fcr&mask) | (old&~mask);
+ if(fcr&INEX) fcr32 ^= _EM_INEXACT;
+ if(fcr&OVFL) fcr32 ^= _EM_OVERFLOW;
+ if(fcr&UNFL) fcr32 ^= _EM_UNDERFLOW;
+ if(fcr&ZDIV) fcr32 ^= _EM_ZERODIVIDE;
+ if(fcr&INVAL) fcr32 ^= _EM_INVALID;
+ switch(fcr&RND_MASK){
+ case RND_NR: fcr32 |= _RC_NEAR; break;
+ case RND_NINF: fcr32 |= _RC_DOWN; break;
+ case RND_PINF: fcr32 |= _RC_UP; break;
+ case RND_Z: fcr32 |= _RC_CHOP; break;
+ }
+ _controlfp(fcr32,mask32);
+ return(old&mask);
+}