1mod bf16;
25mod f128;
26mod f16;
27mod f32;
28mod f64;
29pub use crate::bf16::BF16;
30pub use crate::f128::F128;
31pub use crate::f16::F16;
32pub use crate::f32::F32;
33pub use crate::f64::F64;
34
35use num_traits::{
36 identities::{One, Zero},
37 PrimInt,
38};
39use std::borrow::Borrow;
40use std::cmp::Ordering;
41use std::fmt::{LowerHex, UpperHex};
42
43#[derive(Copy, Clone, Debug)]
45pub enum RoundingMode {
46 TiesToEven,
48 TowardZero,
50 TowardNegative,
52 TowardPositive,
54 TiesToAway,
56}
57
58impl RoundingMode {
59 fn set(&self) {
60 unsafe {
61 softfloat_sys::softfloat_roundingMode_write_helper(self.to_softfloat());
62 }
63 }
64
65 fn to_softfloat(&self) -> u8 {
66 match self {
67 RoundingMode::TiesToEven => softfloat_sys::softfloat_round_near_even,
68 RoundingMode::TowardZero => softfloat_sys::softfloat_round_minMag,
69 RoundingMode::TowardNegative => softfloat_sys::softfloat_round_min,
70 RoundingMode::TowardPositive => softfloat_sys::softfloat_round_max,
71 RoundingMode::TiesToAway => softfloat_sys::softfloat_round_near_maxMag,
72 }
73 }
74}
75
76#[derive(Copy, Clone, Debug, Default)]
94pub struct ExceptionFlags(u8);
95
96impl ExceptionFlags {
97 const FLAG_INEXACT: u8 = softfloat_sys::softfloat_flag_inexact;
98 const FLAG_INFINITE: u8 = softfloat_sys::softfloat_flag_infinite;
99 const FLAG_INVALID: u8 = softfloat_sys::softfloat_flag_invalid;
100 const FLAG_OVERFLOW: u8 = softfloat_sys::softfloat_flag_overflow;
101 const FLAG_UNDERFLOW: u8 = softfloat_sys::softfloat_flag_underflow;
102
103 pub fn from_bits(x: u8) -> Self {
104 Self(x)
105 }
106
107 pub fn to_bits(&self) -> u8 {
108 self.0
109 }
110
111 #[deprecated(since = "0.3.0", note = "Please use to_bits instead")]
112 pub fn bits(&self) -> u8 {
113 self.to_bits()
114 }
115
116 pub fn is_inexact(&self) -> bool {
117 self.0 & Self::FLAG_INEXACT != 0
118 }
119
120 pub fn is_infinite(&self) -> bool {
121 self.0 & Self::FLAG_INFINITE != 0
122 }
123
124 pub fn is_invalid(&self) -> bool {
125 self.0 & Self::FLAG_INVALID != 0
126 }
127
128 pub fn is_overflow(&self) -> bool {
129 self.0 & Self::FLAG_OVERFLOW != 0
130 }
131
132 pub fn is_underflow(&self) -> bool {
133 self.0 & Self::FLAG_UNDERFLOW != 0
134 }
135
136 pub fn set(&self) {
137 unsafe {
138 softfloat_sys::softfloat_exceptionFlags_write_helper(self.to_bits());
139 }
140 }
141
142 pub fn get(&mut self) {
143 let x = unsafe { softfloat_sys::softfloat_exceptionFlags_read_helper() };
144 self.0 = x;
145 }
146}
147
148pub trait Float {
169 type Payload: PrimInt + UpperHex + LowerHex;
170
171 const EXPONENT_BIT: Self::Payload;
172 const FRACTION_BIT: Self::Payload;
173 const SIGN_POS: usize;
174 const EXPONENT_POS: usize;
175
176 fn set_payload(&mut self, x: Self::Payload);
177
178 fn from_bits(v: Self::Payload) -> Self;
179
180 fn to_bits(&self) -> Self::Payload;
181
182 #[deprecated(since = "0.3.0", note = "Please use to_bits instead")]
183 fn bits(&self) -> Self::Payload;
184
185 fn add<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self;
186
187 fn sub<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self;
188
189 fn mul<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self;
190
191 fn fused_mul_add<T: Borrow<Self>>(&self, x: T, y: T, rnd: RoundingMode) -> Self;
192
193 fn div<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self;
194
195 fn rem<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self;
196
197 fn sqrt(&self, rnd: RoundingMode) -> Self;
198
199 fn eq<T: Borrow<Self>>(&self, x: T) -> bool;
200
201 fn lt<T: Borrow<Self>>(&self, x: T) -> bool;
202
203 fn le<T: Borrow<Self>>(&self, x: T) -> bool;
204
205 fn lt_quiet<T: Borrow<Self>>(&self, x: T) -> bool;
206
207 fn le_quiet<T: Borrow<Self>>(&self, x: T) -> bool;
208
209 fn eq_signaling<T: Borrow<Self>>(&self, x: T) -> bool;
210
211 fn is_signaling_nan(&self) -> bool;
212
213 fn from_u32(x: u32, rnd: RoundingMode) -> Self;
214
215 fn from_u64(x: u64, rnd: RoundingMode) -> Self;
216
217 fn from_i32(x: i32, rnd: RoundingMode) -> Self;
218
219 fn from_i64(x: i64, rnd: RoundingMode) -> Self;
220
221 fn to_u32(&self, rnd: RoundingMode, exact: bool) -> u32;
222
223 fn to_u64(&self, rnd: RoundingMode, exact: bool) -> u64;
224
225 fn to_i32(&self, rnd: RoundingMode, exact: bool) -> i32;
226
227 fn to_i64(&self, rnd: RoundingMode, exact: bool) -> i64;
228
229 fn to_f16(&self, rnd: RoundingMode) -> F16;
230
231 fn to_bf16(&self, rnd: RoundingMode) -> BF16;
232
233 fn to_f32(&self, rnd: RoundingMode) -> F32;
234
235 fn to_f64(&self, rnd: RoundingMode) -> F64;
236
237 fn to_f128(&self, rnd: RoundingMode) -> F128;
238
239 fn round_to_integral(&self, rnd: RoundingMode) -> Self;
240
241 #[inline]
242 fn compare<T: Borrow<Self>>(&self, x: T) -> Option<Ordering> {
243 let eq = self.eq(x.borrow());
244 let lt = self.lt(x.borrow());
245 if self.is_nan() || x.borrow().is_nan() {
246 None
247 } else if eq {
248 Some(Ordering::Equal)
249 } else if lt {
250 Some(Ordering::Less)
251 } else {
252 Some(Ordering::Greater)
253 }
254 }
255
256 #[inline]
257 fn from_u8(x: u8, rnd: RoundingMode) -> Self
258 where
259 Self: Sized,
260 {
261 Self::from_u32(x as u32, rnd)
262 }
263
264 #[inline]
265 fn from_u16(x: u16, rnd: RoundingMode) -> Self
266 where
267 Self: Sized,
268 {
269 Self::from_u32(x as u32, rnd)
270 }
271
272 #[inline]
273 fn from_i8(x: i8, rnd: RoundingMode) -> Self
274 where
275 Self: Sized,
276 {
277 Self::from_i32(x as i32, rnd)
278 }
279
280 #[inline]
281 fn from_i16(x: i16, rnd: RoundingMode) -> Self
282 where
283 Self: Sized,
284 {
285 Self::from_i32(x as i32, rnd)
286 }
287
288 #[inline]
289 fn neg(&self) -> Self
290 where
291 Self: Sized,
292 {
293 let mut ret = Self::from_bits(self.to_bits());
294 ret.set_sign(!self.sign());
295 ret
296 }
297
298 #[inline]
299 fn abs(&self) -> Self
300 where
301 Self: Sized,
302 {
303 let mut ret = Self::from_bits(self.to_bits());
304 ret.set_sign(Self::Payload::zero());
305 ret
306 }
307
308 #[inline]
309 fn sign(&self) -> Self::Payload {
310 (self.to_bits() >> Self::SIGN_POS) & Self::Payload::one()
311 }
312
313 #[inline]
314 fn exponent(&self) -> Self::Payload {
315 (self.to_bits() >> Self::EXPONENT_POS) & Self::EXPONENT_BIT
316 }
317
318 #[inline]
319 fn fraction(&self) -> Self::Payload {
320 self.to_bits() & Self::FRACTION_BIT
321 }
322
323 #[inline]
324 fn is_positive(&self) -> bool {
325 self.sign() == Self::Payload::zero()
326 }
327
328 #[inline]
329 fn is_positive_zero(&self) -> bool {
330 self.is_positive()
331 && self.exponent() == Self::Payload::zero()
332 && self.fraction() == Self::Payload::zero()
333 }
334
335 #[inline]
336 fn is_positive_subnormal(&self) -> bool {
337 self.is_positive()
338 && self.exponent() == Self::Payload::zero()
339 && self.fraction() != Self::Payload::zero()
340 }
341
342 #[inline]
343 fn is_positive_normal(&self) -> bool {
344 self.is_positive()
345 && self.exponent() != Self::Payload::zero()
346 && self.exponent() != Self::EXPONENT_BIT
347 }
348
349 #[inline]
350 fn is_positive_infinity(&self) -> bool {
351 self.is_positive()
352 && self.exponent() == Self::EXPONENT_BIT
353 && self.fraction() == Self::Payload::zero()
354 }
355
356 #[inline]
357 fn is_negative(&self) -> bool {
358 self.sign() == Self::Payload::one()
359 }
360
361 #[inline]
362 fn is_negative_zero(&self) -> bool {
363 self.is_negative()
364 && self.exponent() == Self::Payload::zero()
365 && self.fraction() == Self::Payload::zero()
366 }
367
368 #[inline]
369 fn is_negative_subnormal(&self) -> bool {
370 self.is_negative()
371 && self.exponent() == Self::Payload::zero()
372 && self.fraction() != Self::Payload::zero()
373 }
374
375 #[inline]
376 fn is_negative_normal(&self) -> bool {
377 self.is_negative()
378 && self.exponent() != Self::Payload::zero()
379 && self.exponent() != Self::EXPONENT_BIT
380 }
381
382 #[inline]
383 fn is_negative_infinity(&self) -> bool {
384 self.is_negative()
385 && self.exponent() == Self::EXPONENT_BIT
386 && self.fraction() == Self::Payload::zero()
387 }
388
389 #[inline]
390 fn is_nan(&self) -> bool {
391 self.exponent() == Self::EXPONENT_BIT && self.fraction() != Self::Payload::zero()
392 }
393
394 #[inline]
395 fn is_zero(&self) -> bool {
396 self.is_positive_zero() || self.is_negative_zero()
397 }
398
399 #[inline]
400 fn is_subnormal(&self) -> bool {
401 self.exponent() == Self::Payload::zero()
402 }
403
404 #[inline]
405 fn set_sign(&mut self, x: Self::Payload) {
406 self.set_payload(
407 (self.to_bits() & !(Self::Payload::one() << Self::SIGN_POS))
408 | ((x & Self::Payload::one()) << Self::SIGN_POS),
409 );
410 }
411
412 #[inline]
413 fn set_exponent(&mut self, x: Self::Payload) {
414 self.set_payload(
415 (self.to_bits() & !(Self::EXPONENT_BIT << Self::EXPONENT_POS))
416 | ((x & Self::EXPONENT_BIT) << Self::EXPONENT_POS),
417 );
418 }
419
420 #[inline]
421 fn set_fraction(&mut self, x: Self::Payload) {
422 self.set_payload((self.to_bits() & !Self::FRACTION_BIT) | (x & Self::FRACTION_BIT));
423 }
424
425 #[inline]
426 fn positive_infinity() -> Self
427 where
428 Self: Sized,
429 {
430 let mut x = Self::from_bits(Self::Payload::zero());
431 x.set_exponent(Self::EXPONENT_BIT);
432 x
433 }
434
435 #[inline]
436 fn positive_zero() -> Self
437 where
438 Self: Sized,
439 {
440 let x = Self::from_bits(Self::Payload::zero());
441 x
442 }
443
444 #[inline]
445 fn negative_infinity() -> Self
446 where
447 Self: Sized,
448 {
449 let mut x = Self::from_bits(Self::Payload::zero());
450 x.set_sign(Self::Payload::one());
451 x.set_exponent(Self::EXPONENT_BIT);
452 x
453 }
454
455 #[inline]
456 fn negative_zero() -> Self
457 where
458 Self: Sized,
459 {
460 let mut x = Self::from_bits(Self::Payload::zero());
461 x.set_sign(Self::Payload::one());
462 x
463 }
464
465 #[inline]
466 fn quiet_nan() -> Self
467 where
468 Self: Sized,
469 {
470 let mut x = Self::from_bits(Self::Payload::zero());
471 x.set_exponent(Self::EXPONENT_BIT);
472 x.set_fraction(Self::Payload::one() << (Self::EXPONENT_POS - 1));
473 x
474 }
475}
476
477#[cfg(test)]
478mod tests {
479 use super::*;
480
481 #[test]
482 fn flag_inexact() {
483 let a = 0x1234;
484 let b = 0x7654;
485 let a = F16::from_bits(a);
486 let b = F16::from_bits(b);
487 let mut flag = ExceptionFlags::default();
488 flag.set();
489 let _d = a.add(b, RoundingMode::TiesToEven);
490 flag.get();
491 assert!(flag.is_inexact());
492 assert!(!flag.is_infinite());
493 assert!(!flag.is_invalid());
494 assert!(!flag.is_overflow());
495 assert!(!flag.is_underflow());
496 }
497
498 #[test]
499 fn flag_infinite() {
500 let a = 0x1234;
501 let b = 0x0;
502 let a = F16::from_bits(a);
503 let b = F16::from_bits(b);
504 let mut flag = ExceptionFlags::default();
505 flag.set();
506 let _d = a.div(b, RoundingMode::TiesToEven);
507 flag.get();
508 assert!(!flag.is_inexact());
509 assert!(flag.is_infinite());
510 assert!(!flag.is_invalid());
511 assert!(!flag.is_overflow());
512 assert!(!flag.is_underflow());
513 }
514
515 #[test]
516 fn flag_invalid() {
517 let a = 0x0;
518 let b = 0x0;
519 let a = F16::from_bits(a);
520 let b = F16::from_bits(b);
521 let mut flag = ExceptionFlags::default();
522 flag.set();
523 let _d = a.div(b, RoundingMode::TiesToEven);
524 flag.get();
525 assert!(!flag.is_inexact());
526 assert!(!flag.is_infinite());
527 assert!(flag.is_invalid());
528 assert!(!flag.is_overflow());
529 assert!(!flag.is_underflow());
530 }
531
532 #[test]
533 fn flag_overflow() {
534 let a = 0x7bff;
535 let b = 0x7bff;
536 let a = F16::from_bits(a);
537 let b = F16::from_bits(b);
538 let mut flag = ExceptionFlags::default();
539 flag.set();
540 let _d = a.add(b, RoundingMode::TiesToEven);
541 flag.get();
542 assert!(flag.is_inexact());
543 assert!(!flag.is_infinite());
544 assert!(!flag.is_invalid());
545 assert!(flag.is_overflow());
546 assert!(!flag.is_underflow());
547 }
548
549 #[test]
550 fn flag_underflow() {
551 let a = 0x0001;
552 let b = 0x0001;
553 let a = F16::from_bits(a);
554 let b = F16::from_bits(b);
555 let mut flag = ExceptionFlags::default();
556 flag.set();
557 let _d = a.mul(b, RoundingMode::TiesToEven);
558 flag.get();
559 assert!(flag.is_inexact());
560 assert!(!flag.is_infinite());
561 assert!(!flag.is_invalid());
562 assert!(!flag.is_overflow());
563 assert!(flag.is_underflow());
564 }
565}