first steps
This commit is contained in:
commit
1a8542091c
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
16
Cargo.lock
generated
Normal file
16
Cargo.lock
generated
Normal 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
7
Cargo.toml
Normal 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
64
src/lib.rs
Normal 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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user