#![doc = include_str!("../README.md")]
#![no_std]
#![deny(warnings, missing_docs)]
#[macro_use]
mod macros;
pub mod types;
use core::{
alloc::Layout,
mem::{align_of, transmute},
};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(C)]
pub struct DigitLayout {
signed_nbyte: u8,
packed: u8,
exponent: u8,
mantissa: u8,
}
pub trait AsDigit {
const LAYOUT: DigitLayout;
}
pub trait TypeOf_<const N: u32> {
type Type;
}
pub struct TypeOf<const N: u32>;
const _8: usize = u8::BITS as usize;
const _7: usize = _8 - 1;
const MAX_ALIGN: usize = align_of::<usize>();
impl DigitLayout {
#[inline]
pub const fn new(packed: usize, signed: bool, exponent: usize, mantissa: usize) -> Self {
assert!(packed <= u8::MAX as usize);
assert!(exponent <= u8::MAX as usize);
assert!(mantissa <= u8::MAX as usize);
let signed = if signed { 1 } else { 0 };
let total_bits = packed * (signed + exponent + mantissa);
let nbyte = ((total_bits + _7) / _8).next_power_of_two();
assert!(nbyte < (1 << _7));
Self {
packed: packed as _,
signed_nbyte: ((signed << _7) | nbyte) as _,
exponent: exponent as _,
mantissa: mantissa as _,
}
}
#[inline]
pub const fn to_u32(self) -> u32 {
unsafe { transmute(self) }
}
#[inline]
pub const fn packed(self) -> usize {
self.packed as _
}
#[inline]
pub const fn signed(self) -> bool {
self.signed_nbyte >> _7 == 1
}
#[inline]
pub const fn exponent(self) -> usize {
self.exponent as _
}
#[inline]
pub const fn mantissa(self) -> usize {
self.mantissa as _
}
#[inline]
pub const fn padding(self) -> usize {
self.nbits() - self.packed() * (self.signed() as usize + self.exponent() + self.mantissa())
}
#[inline]
pub const fn nbits(self) -> usize {
self.nbytes() * _8
}
#[inline]
pub const fn nbytes(self) -> usize {
(self.signed_nbyte & ((1 << _7) - 1)) as _
}
#[inline]
pub const fn layout(self) -> Layout {
let size = self.nbytes();
let align = if size < MAX_ALIGN { size } else { MAX_ALIGN };
unsafe { Layout::from_size_align_unchecked(size, align) }
}
}