first steps

This commit is contained in:
numzero 2025-11-02 00:19:48 +03:00
commit 1a8542091c
4 changed files with 88 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

16
Cargo.lock generated Normal file
View File

@ -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"

7
Cargo.toml Normal file
View File

@ -0,0 +1,7 @@
[package]
name = "f8"
version = "0.1.0"
edition = "2024"
[dependencies]
static_assertions = "1.1.0"

64
src/lib.rs Normal file
View File

@ -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<u8> for F8 {
fn from(value: u8) -> Self {
todo!()
}
}
impl From<F8> 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}");
}
}
}