1 ! Copyright (C) 2009 Joe Groff.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays assocs combinators continuations generalizations
4 kernel math math.bitwise sequences sets system vocabs ;
15 +fp-invalid-operation+
21 CONSTANT: all-fp-exceptions
23 +fp-invalid-operation+
36 UNION: fp-rounding-mode
46 UNION: fp-denormal-mode
52 HOOK: (fp-env-registers) cpu ( -- registers )
54 : fp-env-register ( -- register ) (fp-env-registers) first ;
56 :: mask> ( bits assoc -- symbols )
57 assoc [| k v | bits v mask zero? ] assoc-reject keys ;
58 : >mask ( symbols assoc -- bits )
61 [ [ at ] curry [ bitor ] map-reduce ] if ;
63 : remask ( x new-bits mask-bits -- x' )
64 [ unmask ] [ mask ] bi-curry bi* bitor ; inline
66 GENERIC: (set-fp-env-register) ( fp-env -- )
68 GENERIC: (get-exception-flags) ( fp-env -- exceptions )
69 GENERIC#: (set-exception-flags) 1 ( fp-env exceptions -- fp-env )
71 GENERIC: (get-fp-traps) ( fp-env -- exceptions )
72 GENERIC#: (set-fp-traps) 1 ( fp-env exceptions -- fp-env )
74 GENERIC: (get-rounding-mode) ( fp-env -- mode )
75 GENERIC#: (set-rounding-mode) 1 ( fp-env mode -- fp-env )
77 GENERIC: (get-denormal-mode) ( fp-env -- mode )
78 GENERIC#: (set-denormal-mode) 1 ( fp-env mode -- fp-env )
80 : change-fp-env-registers ( quot -- )
81 (fp-env-registers) swap [ (set-fp-env-register) ] compose each ; inline
83 : set-fp-traps ( exceptions -- ) [ (set-fp-traps) ] curry change-fp-env-registers ;
84 : set-rounding-mode ( mode -- ) [ (set-rounding-mode) ] curry change-fp-env-registers ;
85 : set-denormal-mode ( mode -- ) [ (set-denormal-mode) ] curry change-fp-env-registers ;
87 : get-fp-env ( -- exception-flags fp-traps rounding-mode denormal-mode )
89 [ (get-exception-flags) ]
91 [ (get-rounding-mode) ]
92 [ (get-denormal-mode) ]
95 : set-fp-env ( exception-flags fp-traps rounding-mode denormal-mode -- )
98 [ [ (set-exception-flags) ] when* ]
99 [ [ (set-fp-traps) ] when* ]
100 [ [ (set-rounding-mode) ] when* ]
101 [ [ (set-denormal-mode) ] when* ]
103 ] 4 ncurry change-fp-env-registers ;
105 CONSTANT: vm-error-exception-flag>bit
107 { +fp-invalid-operation+ 0x01 }
108 { +fp-overflow+ 0x02 }
109 { +fp-underflow+ 0x04 }
110 { +fp-zero-divide+ 0x08 }
111 { +fp-inexact+ 0x10 }
116 : fp-exception-flags ( -- exceptions )
117 (fp-env-registers) [ (get-exception-flags) ] [ union ] map-reduce >array ; inline
118 : set-fp-exception-flags ( exceptions -- )
119 [ (set-exception-flags) ] curry change-fp-env-registers ; inline
120 : clear-fp-exception-flags ( -- ) { } set-fp-exception-flags ; inline
122 : collect-fp-exceptions ( quot -- exceptions )
123 [ clear-fp-exception-flags ] dip call fp-exception-flags ; inline
125 : vm-error>exception-flags ( error -- exceptions )
126 third vm-error-exception-flag>bit mask> ;
127 : vm-error-exception-flag? ( error flag -- ? )
128 vm-error>exception-flags member? ;
130 : denormal-mode ( -- mode ) fp-env-register (get-denormal-mode) ;
132 :: with-denormal-mode ( mode quot -- )
133 denormal-mode :> orig
134 mode set-denormal-mode
135 quot [ orig set-denormal-mode ] finally ; inline
137 : rounding-mode ( -- mode ) fp-env-register (get-rounding-mode) ;
139 :: with-rounding-mode ( mode quot -- )
140 rounding-mode :> orig
141 mode set-rounding-mode
142 quot [ orig set-rounding-mode ] finally ; inline
144 : fp-traps ( -- exceptions )
145 (fp-env-registers) [ (get-fp-traps) ] [ union ] map-reduce >array ; inline
147 :: with-fp-traps ( exceptions quot -- )
148 clear-fp-exception-flags
150 exceptions set-fp-traps
151 quot [ orig set-fp-traps ] finally ; inline
153 : without-fp-traps ( quot -- )
154 { } swap with-fp-traps ; inline
156 ! USE-X86: math.floats.env.x86
157 ! USE-PPC: math.floats.env.ppc
160 { [ cpu x86? ] [ "math.floats.env.x86" require ] }
161 { [ cpu ppc? ] [ "math.floats.env.ppc" require ] }
162 [ "CPU architecture unsupported by math.floats.env" throw ]