Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
softfloat.cpp
Go to the documentation of this file.
3#include <softfloat.hpp>
4
5namespace sysio { namespace chain { namespace webassembly {
6 static constexpr uint32_t inv_float_eps = 0x4B000000;
7 static constexpr uint64_t inv_double_eps = 0x4330000000000000;
8
9 // float binops
10 float interface::_sysio_f32_add( float a, float b ) const {
12 float ret;
13 std::memcpy((char*)&ret, (char*)&r, sizeof(ret));
14 return ret;
15 }
16 float interface::_sysio_f32_sub( float a, float b ) const {
18 float ret;
19 std::memcpy((char*)&ret, (char*)&r, sizeof(ret));
20 return ret;
21 }
22 float interface::_sysio_f32_div( float a, float b ) const {
24 float ret;
25 std::memcpy((char*)&ret, (char*)&r, sizeof(ret));
26 return ret;
27 }
28 float interface::_sysio_f32_mul( float a, float b ) const {
30 float ret;
31 std::memcpy((char*)&ret, (char*)&r, sizeof(ret));
32 return ret;
33 }
34 float interface::_sysio_f32_min( float af, float bf ) const {
37 if (is_nan(a)) {
38 return af;
39 }
40 if (is_nan(b)) {
41 return bf;
42 }
43 if ( f32_sign_bit(a) != f32_sign_bit(b) ) {
44 return f32_sign_bit(a) ? af : bf;
45 }
46 return ::f32_lt(a,b) ? af : bf;
47 }
48 float interface::_sysio_f32_max( float af, float bf ) const {
51 if (is_nan(a)) {
52 return af;
53 }
54 if (is_nan(b)) {
55 return bf;
56 }
57 if ( f32_sign_bit(a) != f32_sign_bit(b) ) {
58 return f32_sign_bit(a) ? bf : af;
59 }
60 return ::f32_lt( a, b ) ? bf : af;
61 }
62 float interface::_sysio_f32_copysign( float af, float bf ) const {
65 uint32_t sign_of_b = b.v >> 31;
66 a.v &= ~(1 << 31); // clear the sign bit
67 a.v = a.v | (sign_of_b << 31); // add the sign of b
68 return from_softfloat32(a);
69 }
70 // float unops
71 float interface::_sysio_f32_abs( float af ) const {
73 a.v &= ~(1 << 31);
74 return from_softfloat32(a);
75 }
76 float interface::_sysio_f32_neg( float af ) const {
78 uint32_t sign = a.v >> 31;
79 a.v &= ~(1 << 31);
80 a.v |= (!sign << 31);
81 return from_softfloat32(a);
82 }
83 float interface::_sysio_f32_sqrt( float a ) const {
85 return from_softfloat32(ret);
86 }
87 // ceil, floor, trunc and nearest are lifted from libc
88 float interface::_sysio_f32_ceil( float af ) const {
90 int e = (int)(a.v >> 23 & 0xFF) - 0X7F;
91 uint32_t m;
92 if (e >= 23)
93 return af;
94 if (e >= 0) {
95 m = 0x007FFFFF >> e;
96 if ((a.v & m) == 0)
97 return af;
98 if (a.v >> 31 == 0)
99 a.v += m;
100 a.v &= ~m;
101 } else {
102 if (a.v >> 31)
103 a.v = 0x80000000; // return -0.0f
104 else if (a.v << 1)
105 a.v = 0x3F800000; // return 1.0f
106 }
107
108 return from_softfloat32(a);
109 }
110 float interface::_sysio_f32_floor( float af ) const {
112 int e = (int)(a.v >> 23 & 0xFF) - 0X7F;
113 uint32_t m;
114 if (e >= 23)
115 return af;
116 if (e >= 0) {
117 m = 0x007FFFFF >> e;
118 if ((a.v & m) == 0)
119 return af;
120 if (a.v >> 31)
121 a.v += m;
122 a.v &= ~m;
123 } else {
124 if (a.v >> 31 == 0)
125 a.v = 0;
126 else if (a.v << 1)
127 a.v = 0xBF800000; // return -1.0f
128 }
129 return from_softfloat32(a);
130 }
131 float interface::_sysio_f32_trunc( float af ) const {
133 int e = (int)(a.v >> 23 & 0xff) - 0x7f + 9;
134 uint32_t m;
135 if (e >= 23 + 9)
136 return af;
137 if (e < 9)
138 e = 1;
139 m = -1U >> e;
140 if ((a.v & m) == 0)
141 return af;
142 a.v &= ~m;
143 return from_softfloat32(a);
144 }
145 float interface::_sysio_f32_nearest( float af ) const {
147 int e = a.v>>23 & 0xff;
148 int s = a.v>>31;
149 float32_t y;
150 if (e >= 0x7f+23)
151 return af;
152 if (s)
153 y = ::f32_add( ::f32_sub( a, float32_t{inv_float_eps} ), float32_t{inv_float_eps} );
154 else
155 y = ::f32_sub( ::f32_add( a, float32_t{inv_float_eps} ), float32_t{inv_float_eps} );
156 if (::f32_eq( y, {0} ) )
157 return s ? -0.0f : 0.0f;
158 return from_softfloat32(y);
159 }
160
161 // float relops
162 bool interface::_sysio_f32_eq( float a, float b ) const { return ::f32_eq( to_softfloat32(a), to_softfloat32(b) ); }
163 bool interface::_sysio_f32_ne( float a, float b ) const { return !::f32_eq( to_softfloat32(a), to_softfloat32(b) ); }
164 bool interface::_sysio_f32_lt( float a, float b ) const { return ::f32_lt( to_softfloat32(a), to_softfloat32(b) ); }
165 bool interface::_sysio_f32_le( float a, float b ) const { return ::f32_le( to_softfloat32(a), to_softfloat32(b) ); }
166 bool interface::_sysio_f32_gt( float af, float bf ) const {
169 if (is_nan(a))
170 return false;
171 if (is_nan(b))
172 return false;
173 return !::f32_le( a, b );
174 }
175 bool interface::_sysio_f32_ge( float af, float bf ) const {
178 if (is_nan(a))
179 return false;
180 if (is_nan(b))
181 return false;
182 return !::f32_lt( a, b );
183 }
184
185 // double binops
186 double interface::_sysio_f64_add( double a, double b ) const {
188 return from_softfloat64(ret);
189 }
190 double interface::_sysio_f64_sub( double a, double b ) const {
192 return from_softfloat64(ret);
193 }
194 double interface::_sysio_f64_div( double a, double b ) const {
196 return from_softfloat64(ret);
197 }
198 double interface::_sysio_f64_mul( double a, double b ) const {
200 return from_softfloat64(ret);
201 }
202 double interface::_sysio_f64_min( double af, double bf ) const {
205 if (is_nan(a))
206 return af;
207 if (is_nan(b))
208 return bf;
209 if (f64_sign_bit(a) != f64_sign_bit(b))
210 return f64_sign_bit(a) ? af : bf;
211 return ::f64_lt( a, b ) ? af : bf;
212 }
213 double interface::_sysio_f64_max( double af, double bf ) const {
216 if (is_nan(a))
217 return af;
218 if (is_nan(b))
219 return bf;
220 if (f64_sign_bit(a) != f64_sign_bit(b))
221 return f64_sign_bit(a) ? bf : af;
222 return ::f64_lt( a, b ) ? bf : af;
223 }
224 double interface::_sysio_f64_copysign( double af, double bf ) const {
227 uint64_t sign_of_b = b.v >> 63;
228 a.v &= ~(uint64_t(1) << 63); // clear the sign bit
229 a.v = a.v | (sign_of_b << 63); // add the sign of b
230 return from_softfloat64(a);
231 }
232
233 // double unops
234 double interface::_sysio_f64_abs( double af ) const {
236 a.v &= ~(uint64_t(1) << 63);
237 return from_softfloat64(a);
238 }
239 double interface::_sysio_f64_neg( double af ) const {
241 uint64_t sign = a.v >> 63;
242 a.v &= ~(uint64_t(1) << 63);
243 a.v |= (uint64_t(!sign) << 63);
244 return from_softfloat64(a);
245 }
246 double interface::_sysio_f64_sqrt( double a ) const {
248 return from_softfloat64(ret);
249 }
250 // ceil, floor, trunc and nearest are lifted from libc
251 double interface::_sysio_f64_ceil( double af ) const {
252 float64_t a = to_softfloat64( af );
254 int e = a.v >> 52 & 0x7ff;
255 float64_t y;
256 if (e >= 0x3ff+52 || ::f64_eq( a, { 0 } ))
257 return af;
258 /* y = int(x) - x, where int(x) is an integer neighbor of x */
259 if (a.v >> 63)
260 y = ::f64_sub( ::f64_add( ::f64_sub( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} ), a );
261 else
262 y = ::f64_sub( ::f64_sub( ::f64_add( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} ), a );
263 /* special case because of non-nearest rounding modes */
264 if (e <= 0x3ff-1) {
265 return a.v >> 63 ? -0.0 : 1.0; //float64_t{0x8000000000000000} : float64_t{0xBE99999A3F800000}; //either -0.0 or 1
266 }
267 if (::f64_lt( y, to_softfloat64(0) )) {
268 ret = ::f64_add( ::f64_add( a, y ), to_softfloat64(1) ); // 0xBE99999A3F800000 } ); // plus 1
269 return from_softfloat64(ret);
270 }
271 ret = ::f64_add( a, y );
272 return from_softfloat64(ret);
273 }
274 double interface::_sysio_f64_floor( double af ) const {
275 float64_t a = to_softfloat64( af );
277 int e = a.v >> 52 & 0x7FF;
278 float64_t y;
279 if ( a.v == 0x8000000000000000) {
280 return af;
281 }
282 if (e >= 0x3FF+52 || a.v == 0) {
283 return af;
284 }
285 if (a.v >> 63)
286 y = ::f64_sub( ::f64_add( ::f64_sub( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} ), a );
287 else
288 y = ::f64_sub( ::f64_sub( ::f64_add( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} ), a );
289 if (e <= 0x3FF-1) {
290 return a.v>>63 ? -1.0 : 0.0; //float64_t{0xBFF0000000000000} : float64_t{0}; // -1 or 0
291 }
292 if ( !::f64_le( y, float64_t{0} ) ) {
294 return from_softfloat64(ret);
295 }
296 ret = ::f64_add( a, y );
297 return from_softfloat64(ret);
298 }
299 double interface::_sysio_f64_trunc( double af ) const {
300 float64_t a = to_softfloat64( af );
301 int e = (int)(a.v >> 52 & 0x7ff) - 0x3ff + 12;
302 uint64_t m;
303 if (e >= 52 + 12)
304 return af;
305 if (e < 12)
306 e = 1;
307 m = -1ULL >> e;
308 if ((a.v & m) == 0)
309 return af;
310 a.v &= ~m;
311 return from_softfloat64(a);
312 }
313
314 double interface::_sysio_f64_nearest( double af ) const {
315 float64_t a = to_softfloat64( af );
316 int e = (a.v >> 52 & 0x7FF);
317 int s = a.v >> 63;
318 float64_t y;
319 if ( e >= 0x3FF+52 )
320 return af;
321 if ( s )
322 y = ::f64_add( ::f64_sub( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} );
323 else
324 y = ::f64_sub( ::f64_add( a, float64_t{inv_double_eps} ), float64_t{inv_double_eps} );
325 if ( ::f64_eq( y, float64_t{0} ) )
326 return s ? -0.0 : 0.0;
327 return from_softfloat64(y);
328 }
329
330 // double relops
331 bool interface::_sysio_f64_eq( double a, double b ) const { return ::f64_eq( to_softfloat64(a), to_softfloat64(b) ); }
332 bool interface::_sysio_f64_ne( double a, double b ) const { return !::f64_eq( to_softfloat64(a), to_softfloat64(b) ); }
333 bool interface::_sysio_f64_lt( double a, double b ) const { return ::f64_lt( to_softfloat64(a), to_softfloat64(b) ); }
334 bool interface::_sysio_f64_le( double a, double b ) const { return ::f64_le( to_softfloat64(a), to_softfloat64(b) ); }
335 bool interface::_sysio_f64_gt( double af, double bf ) const {
338 if (is_nan(a))
339 return false;
340 if (is_nan(b))
341 return false;
342 return !::f64_le( a, b );
343 }
344 bool interface::_sysio_f64_ge( double af, double bf ) const {
347 if (is_nan(a))
348 return false;
349 if (is_nan(b))
350 return false;
351 return !::f64_lt( a, b );
352 }
353
354 // float and double conversions
355 double interface::_sysio_f32_promote( float a ) const {
357 }
358 float interface::_sysio_f64_demote( double a ) const {
360 }
363 if (_sysio_f32_ge(af, 2147483648.0f) || _sysio_f32_lt(af, -2147483648.0f))
364 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f32.convert_s/i32 overflow" );
365
366 if (is_nan(a))
367 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f32.convert_s/i32 unrepresentable");
368 return f32_to_i32( to_softfloat32(_sysio_f32_trunc( af )), 0, false );
369 }
372 if (_sysio_f64_ge(af, 2147483648.0) || _sysio_f64_lt(af, -2147483648.0))
373 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f64.convert_s/i32 overflow");
374 if (is_nan(a))
375 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f64.convert_s/i32 unrepresentable");
376 return f64_to_i32( to_softfloat64(_sysio_f64_trunc( af )), 0, false );
377 }
380 if (_sysio_f32_ge(af, 4294967296.0f) || _sysio_f32_le(af, -1.0f))
381 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f32.convert_u/i32 overflow");
382 if (is_nan(a))
383 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f32.convert_u/i32 unrepresentable");
384 return f32_to_ui32( to_softfloat32(_sysio_f32_trunc( af )), 0, false );
385 }
388 if (_sysio_f64_ge(af, 4294967296.0) || _sysio_f64_le(af, -1.0))
389 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f64.convert_u/i32 overflow");
390 if (is_nan(a))
391 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f64.convert_u/i32 unrepresentable");
392 return f64_to_ui32( to_softfloat64(_sysio_f64_trunc( af )), 0, false );
393 }
396 if (_sysio_f32_ge(af, 9223372036854775808.0f) || _sysio_f32_lt(af, -9223372036854775808.0f))
397 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f32.convert_s/i64 overflow");
398 if (is_nan(a))
399 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f32.convert_s/i64 unrepresentable");
400 return f32_to_i64( to_softfloat32(_sysio_f32_trunc( af )), 0, false );
401 }
404 if (_sysio_f64_ge(af, 9223372036854775808.0) || _sysio_f64_lt(af, -9223372036854775808.0))
405 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f64.convert_s/i64 overflow");
406 if (is_nan(a))
407 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f64.convert_s/i64 unrepresentable");
408
409 return f64_to_i64( to_softfloat64(_sysio_f64_trunc( af )), 0, false );
410 }
413 if (_sysio_f32_ge(af, 18446744073709551616.0f) || _sysio_f32_le(af, -1.0f))
414 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f32.convert_u/i64 overflow");
415 if (is_nan(a))
416 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f32.convert_u/i64 unrepresentable");
417 return f32_to_ui64( to_softfloat32(_sysio_f32_trunc( af )), 0, false );
418 }
421 if (_sysio_f64_ge(af, 18446744073709551616.0) || _sysio_f64_le(af, -1.0))
422 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f64.convert_u/i64 overflow");
423 if (is_nan(a))
424 FC_THROW_EXCEPTION( sysio::chain::wasm_execution_error, "Error, f64.convert_u/i64 unrepresentable");
425 return f64_to_ui64( to_softfloat64(_sysio_f64_trunc( af )), 0, false );
426 }
428 return from_softfloat32(i32_to_f32( a ));
429 }
431 return from_softfloat32(i64_to_f32( a ));
432 }
440 return from_softfloat64(i32_to_f64( a ));
441 }
443 return from_softfloat64(i64_to_f64( a ));
444 }
446 return from_softfloat64(ui32_to_f64( a ));
447 }
449 return from_softfloat64(ui64_to_f64( a ));
450 }
451}}} // ns sysio::chain::webassembly
const mie::Vuint & r
Definition bn.cpp:28
double _sysio_f64_add(double, double) const
float _sysio_f32_mul(float, float) const
Definition softfloat.cpp:28
double _sysio_f64_div(double, double) const
int64_t _sysio_f64_trunc_i64s(double) const
double _sysio_f64_abs(double) const
uint32_t _sysio_f32_trunc_i32u(float) const
bool _sysio_f64_le(double, double) const
float _sysio_ui64_to_f32(uint64_t) const
bool _sysio_f32_lt(float, float) const
double _sysio_f64_mul(double, double) const
float _sysio_f32_copysign(float, float) const
Definition softfloat.cpp:62
double _sysio_ui32_to_f64(uint32_t) const
uint64_t _sysio_f64_trunc_i64u(double) const
bool _sysio_f64_ge(double, double) const
int32_t _sysio_f32_trunc_i32s(float) const
float _sysio_ui32_to_f32(uint32_t) const
double _sysio_f64_sqrt(double) const
double _sysio_i64_to_f64(int64_t) const
uint64_t _sysio_f32_trunc_i64u(float) const
float _sysio_i64_to_f32(int64_t) const
bool _sysio_f64_eq(double, double) const
bool _sysio_f32_gt(float, float) const
double _sysio_f64_sub(double, double) const
double _sysio_ui64_to_f64(uint64_t) const
float _sysio_f32_add(float, float) const
Definition softfloat.cpp:10
float _sysio_f32_sub(float, float) const
Definition softfloat.cpp:16
float _sysio_f64_demote(double) const
float _sysio_f32_div(float, float) const
Definition softfloat.cpp:22
double _sysio_f32_promote(float) const
double _sysio_f64_ceil(double) const
double _sysio_f64_floor(double) const
float _sysio_i32_to_f32(int32_t) const
bool _sysio_f64_lt(double, double) const
bool _sysio_f32_le(float, float) const
bool _sysio_f64_gt(double, double) const
int64_t _sysio_f32_trunc_i64s(float) const
float _sysio_f32_max(float, float) const
Definition softfloat.cpp:48
bool _sysio_f32_ge(float, float) const
double _sysio_f64_copysign(double, double) const
double _sysio_f64_min(double, double) const
double _sysio_f64_trunc(double) const
double _sysio_f64_max(double, double) const
bool _sysio_f32_ne(float, float) const
int32_t _sysio_f64_trunc_i32s(double) const
uint32_t _sysio_f64_trunc_i32u(double) const
float _sysio_f32_min(float, float) const
Definition softfloat.cpp:34
bool _sysio_f32_eq(float, float) const
double _sysio_i32_to_f64(int32_t) const
double _sysio_f64_neg(double) const
double _sysio_f64_nearest(double) const
bool _sysio_f64_ne(double, double) const
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
uint64_t y
Definition sha3.cpp:34
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
float32_t f32_add(float32_t a, float32_t b)
Definition f32_add.c:43
float32_t f32_div(float32_t a, float32_t b)
Definition f32_div.c:44
bool f32_eq(float32_t a, float32_t b)
Definition f32_eq.c:44
bool f32_le(float32_t a, float32_t b)
Definition f32_le.c:43
bool f32_lt(float32_t a, float32_t b)
Definition f32_lt.c:43
float32_t f32_mul(float32_t a, float32_t b)
Definition f32_mul.c:44
float32_t f32_sqrt(float32_t a)
Definition f32_sqrt.c:44
float32_t f32_sub(float32_t a, float32_t b)
Definition f32_sub.c:43
float64_t f32_to_f64(float32_t a)
Definition f32_to_f64.c:44
int_fast32_t f32_to_i32(float32_t a, uint_fast8_t roundingMode, bool exact)
Definition f32_to_i32.c:44
int_fast64_t f32_to_i64(float32_t a, uint_fast8_t roundingMode, bool exact)
Definition f32_to_i64.c:44
uint_fast32_t f32_to_ui32(float32_t a, uint_fast8_t roundingMode, bool exact)
Definition f32_to_ui32.c:44
uint_fast64_t f32_to_ui64(float32_t a, uint_fast8_t roundingMode, bool exact)
Definition f32_to_ui64.c:44
float64_t f64_add(float64_t a, float64_t b)
Definition f64_add.c:43
float64_t f64_div(float64_t a, float64_t b)
Definition f64_div.c:44
bool f64_eq(float64_t a, float64_t b)
Definition f64_eq.c:44
bool f64_le(float64_t a, float64_t b)
Definition f64_le.c:43
bool f64_lt(float64_t a, float64_t b)
Definition f64_lt.c:43
float64_t f64_mul(float64_t a, float64_t b)
Definition f64_mul.c:44
float64_t f64_sqrt(float64_t a)
Definition f64_sqrt.c:44
float64_t f64_sub(float64_t a, float64_t b)
Definition f64_sub.c:43
float32_t f64_to_f32(float64_t a)
Definition f64_to_f32.c:44
int_fast32_t f64_to_i32(float64_t a, uint_fast8_t roundingMode, bool exact)
Definition f64_to_i32.c:44
int_fast64_t f64_to_i64(float64_t a, uint_fast8_t roundingMode, bool exact)
Definition f64_to_i64.c:44
uint_fast32_t f64_to_ui32(float64_t a, uint_fast8_t roundingMode, bool exact)
Definition f64_to_ui32.c:44
uint_fast64_t f64_to_ui64(float64_t a, uint_fast8_t roundingMode, bool exact)
Definition f64_to_ui64.c:44
float32_t i32_to_f32(int32_t a)
Definition i32_to_f32.c:43
float64_t i32_to_f64(int32_t a)
Definition i32_to_f64.c:43
float32_t i64_to_f32(int64_t a)
Definition i64_to_f32.c:43
float64_t i64_to_f64(int64_t a)
Definition i64_to_f64.c:43
float64_t ui64_to_f64(uint64_t)
Definition ui64_to_f64.c:42
float32_t ui32_to_f32(uint32_t)
Definition ui32_to_f32.c:42
float32_t ui64_to_f32(uint64_t)
Definition ui64_to_f32.c:42
float64_t ui32_to_f64(uint32_t)
Definition ui32_to_f64.c:42
float32_t to_softfloat32(float f)
double from_softfloat64(float64_t d)
bool f64_sign_bit(float64_t f)
bool f32_sign_bit(float32_t f)
float64_t to_softfloat64(double d)
float from_softfloat32(float32_t f)
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
signed int int32_t
Definition stdint.h:123
unsigned __int64 uint64_t
Definition stdint.h:136
CK_RV ret
char * s