diff --git a/implementations/rust/oo/src/text/mod.rs b/implementations/rust/oo/src/text/mod.rs index 5da5862..91304bd 100644 --- a/implementations/rust/oo/src/text/mod.rs +++ b/implementations/rust/oo/src/text/mod.rs @@ -76,3 +76,89 @@ mod formatting_tests { "]")); } } + +#[cfg(test)] +mod unusual_float_tests { + use std::io; + use crate::*; + + fn d32(v: f32) { + println!("{}{}{}{}{:?}: preserves {:?}", + if v.is_nan() { "nan " } else { "" }, + if v.is_infinite() { "inf " } else { "" }, + if v.is_subnormal() { "sub " } else { "" }, + if v.is_sign_positive() { "+ve " } else { "-ve " }, + v, + iovalue(v)); + } + + fn d64(v: f64) { + println!("{}{}{}{}{:?}: preserves {:?}", + if v.is_nan() { "nan " } else { "" }, + if v.is_infinite() { "inf " } else { "" }, + if v.is_subnormal() { "sub " } else { "" }, + if v.is_sign_positive() { "+ve " } else { "-ve " }, + v, + iovalue(v)); + } + + #[test] fn subnormal32() -> io::Result<()> { + d32(f32::from_bits(0x00000100)); + d32(f32::from_bits(0x80000100)); + Ok(()) + } + + #[test] fn normal32() -> io::Result<()> { + d32(f32::from_bits(0x01000000)); + d32(f32::from_bits(0x81000000)); + Ok(()) + } + + #[test] fn nan32() -> io::Result<()> { + d32(f32::from_bits(0x7fc00000)); + d32(f32::from_bits(0x7fc5a5a5)); + d32(f32::from_bits(0x7f800001)); + d32(f32::from_bits(0x7f85a5a5)); + d32(f32::from_bits(0xffc00000)); + d32(f32::from_bits(0xffc5a5a5)); + d32(f32::from_bits(0xff800001)); + d32(f32::from_bits(0xff85a5a5)); + Ok(()) + } + + #[test] fn inf32() -> io::Result<()> { + d32(f32::from_bits(0x7f800000)); + d32(f32::from_bits(0xff800000)); + Ok(()) + } + + #[test] fn subnormal64() -> io::Result<()> { + d64(f64::from_bits(0x0000000000000100)); + d64(f64::from_bits(0x8000000000000100)); + Ok(()) + } + + #[test] fn normal64() -> io::Result<()> { + d64(f64::from_bits(0x0100000000000000)); + d64(f64::from_bits(0x8100000000000000)); + Ok(()) + } + + #[test] fn nan64() -> io::Result<()> { + d64(f64::from_bits(0x7ff8000000000000)); + d64(f64::from_bits(0x7ff85a5a5a5a5a5a)); + d64(f64::from_bits(0x7ff0000000000001)); + d64(f64::from_bits(0x7ff05a5a5a5a5a5a)); + d64(f64::from_bits(0xfff8000000000000)); + d64(f64::from_bits(0xfff85a5a5a5a5a5a)); + d64(f64::from_bits(0xfff0000000000001)); + d64(f64::from_bits(0xfff05a5a5a5a5a5a)); + Ok(()) + } + + #[test] fn inf64() -> io::Result<()> { + d64(f64::from_bits(0x7ff0000000000000)); + d64(f64::from_bits(0xfff0000000000000)); + Ok(()) + } +} diff --git a/implementations/rust/oo/src/text/writer.rs b/implementations/rust/oo/src/text/writer.rs index 777020e..652ebb0 100644 --- a/implementations/rust/oo/src/text/writer.rs +++ b/implementations/rust/oo/src/text/writer.rs @@ -4,6 +4,7 @@ use crate::IOValue; use crate::IOValueDomainCodec; use crate::Value; use crate::Writer; +use crate::hex::HexFormatter; use num_bigint::BigInt; @@ -205,13 +206,23 @@ impl Writer for TextWriter { } fn write_f32(&mut self, v: f32) -> io::Result<()> { - dtoa::write(&mut self.w, v)?; - write!(self.w, "f") + if f32::is_normal(v) || f32::is_subnormal(v) { + dtoa::write(&mut self.w, v)?; + write!(self.w, "f") + } else { + let bs = v.to_be_bytes(); + write!(self.w, "#p#x\"{}\"", HexFormatter::Packed.encode(&bs)) + } } fn write_f64(&mut self, v: f64) -> io::Result<()> { - dtoa::write(&mut self.w, v)?; - Ok(()) + if f64::is_normal(v) || f64::is_subnormal(v) { + dtoa::write(&mut self.w, v)?; + Ok(()) + } else { + let bs = v.to_be_bytes(); + write!(self.w, "#p#x\"{}\"", HexFormatter::Packed.encode(&bs)) + } } fn write_i128(&mut self, v: i128) -> io::Result<()> {