commit 1a8542091ce61c7354a5fa226912df59bb013e6f Author: numzero Date: Sun Nov 2 00:19:48 2025 +0300 first steps diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..206444a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "f8" +version = "0.1.0" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..82873da --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "f8" +version = "0.1.0" +edition = "2024" + +[dependencies] +static_assertions = "1.1.0" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..2e28ba5 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,64 @@ +pub const M_BITS: u8 = 5; +pub const E_BITS: u8 = 3; +const E_MAX: u8 = 4; + +static_assertions::const_assert_eq!(M_BITS + E_BITS, 8); + +const M_STORAGE_MAX: u8 = (1 << M_BITS) - 1; +const E_STORAGE_MAX: u8 = (1 << E_BITS) - 1; +const M_BIAS: u8 = 1 << M_BITS; +const E_BIAS: u8 = E_STORAGE_MAX - E_MAX; +const M_MASK: u8 = M_STORAGE_MAX << E_BITS; +const E_MASK: u8 = E_STORAGE_MAX; + +#[repr(transparent)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct F8(u8); + +impl F8 { + /// Split self into the mantissa and exponent, as stored. + fn split(self) -> (u8, u8) { + (self.0 >> E_BITS, self.0 & E_MASK) + } + + /// Split self into integers (m, e) such that `self == m * 2.pow(e)`. + fn split_unbias(self) -> (u8, i8) { + let (m, e) = self.split(); + (m | M_BIAS, e as i8 - (E_BIAS + M_BITS) as i8) + } + + fn merge(m: u8, e: u8) -> Self { + assert!(m <= M_STORAGE_MAX); + assert!(e <= E_STORAGE_MAX); + Self((m << E_BITS) | e) + } +} + +impl From for F8 { + fn from(value: u8) -> Self { + todo!() + } +} + +impl From for u8 { + fn from(value: F8) -> Self { + if value.0 == 0 { + return 0; + } + let (m, e) = value.split_unbias(); + if e >= 0 { m << e } else { m >> -e } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_int_conv() { + assert_eq!(u8::from(F8(0)), 0); + for e in 0..E_MAX { + assert_eq!(u8::from(F8(e + E_BIAS)), 1 << e, "e={e}"); + } + } +}