use core::alloc::LayoutError;
use core::fmt::Display;
#[cfg(feature = "std")]
use std::collections::TryReserveError;
#[cfg(not(feature = "std"))]
use alloc::collections::TryReserveError;
#[cfg(not(target_pointer_width = "32"))]
pub type Word = u64;
#[cfg(not(target_pointer_width = "32"))]
pub type DoubleWord = u128;
#[cfg(not(target_pointer_width = "32"))]
pub type SignedWord = i128;
#[cfg(target_pointer_width = "32")]
pub type Word = u32;
#[cfg(target_pointer_width = "32")]
pub type DoubleWord = u64;
#[cfg(target_pointer_width = "32")]
pub type SignedWord = i64;
const _: [(); 1] = [(); (core::mem::size_of::<Word>() <= core::mem::size_of::<usize>()) as usize];
pub type Exponent = i32;
#[cfg(not(target_pointer_width = "32"))]
pub const EXPONENT_MAX: Exponent = Exponent::MAX;
#[cfg(target_pointer_width = "32")]
pub const EXPONENT_MAX: Exponent = Exponent::MAX / 4;
#[cfg(not(target_pointer_width = "32"))]
pub const EXPONENT_MIN: Exponent = Exponent::MIN;
#[cfg(target_pointer_width = "32")]
pub const EXPONENT_MIN: Exponent = Exponent::MIN / 4;
pub const WORD_MAX: Word = Word::MAX;
pub const WORD_BASE: DoubleWord = WORD_MAX as DoubleWord + 1;
pub const WORD_BIT_SIZE: usize = core::mem::size_of::<Word>() * 8;
pub const PROPTEST_CASES: u32 = 1000;
pub const WORD_SIGNIFICANT_BIT: Word = WORD_MAX << (WORD_BIT_SIZE - 1);
pub const DEFAULT_P: usize = 128;
pub const EXPONENT_BIT_SIZE: usize = core::mem::size_of::<Exponent>() * 8;
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
pub enum Sign {
Neg = -1,
Pos = 1,
}
impl Sign {
pub fn invert(&self) -> Self {
match *self {
Sign::Pos => Sign::Neg,
Sign::Neg => Sign::Pos,
}
}
pub fn is_positive(&self) -> bool {
*self == Sign::Pos
}
pub fn is_negative(&self) -> bool {
*self == Sign::Neg
}
pub fn to_int(&self) -> i8 {
*self as i8
}
}
#[derive(Debug, Clone, Copy)]
pub enum Error {
ExponentOverflow(Sign),
DivisionByZero,
InvalidArgument,
PrecisionRetryExhausted,
MemoryAllocation,
}
#[cfg(feature = "std")]
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
impl Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let repr = match self {
Error::ExponentOverflow(s) => {
if s.is_positive() {
"positive overflow"
} else {
"negative overflow"
}
}
Error::DivisionByZero => "division by zero",
Error::InvalidArgument => "invalid argument",
Error::PrecisionRetryExhausted => "precision retry exhausted",
Error::MemoryAllocation => "memory allocation failure",
};
f.write_str(repr)
}
}
impl PartialEq for Error {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::ExponentOverflow(l0), Self::ExponentOverflow(r0)) => l0 == r0,
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
}
}
}
impl From<TryReserveError> for Error {
fn from(_: TryReserveError) -> Self {
Error::MemoryAllocation
}
}
impl From<LayoutError> for Error {
fn from(_: LayoutError) -> Self {
Error::MemoryAllocation
}
}
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
pub struct Radix(u8);
#[allow(non_upper_case_globals)]
impl Radix {
pub const Bin: Radix = Radix(2);
pub const Oct: Radix = Radix(8);
pub const Dec: Radix = Radix(10);
pub const Hex: Radix = Radix(16);
pub fn try_new(base: u8) -> Result<Self, Error> {
if (2..=36).contains(&base) {
Ok(Radix(base))
} else {
Err(Error::InvalidArgument)
}
}
pub const fn value(self) -> u8 {
self.0
}
pub const fn commensurable_shift(self) -> Option<usize> {
let b = self.0;
if b.is_power_of_two() {
Some(b.trailing_zeros() as usize)
} else {
None
}
}
pub const fn uses_underscore_exponent(self) -> bool {
self.0 > 10
}
pub fn bits_per_digit(self) -> usize {
match self.0 {
2 => 1,
8 => 3,
10 => 3,
16 => 4,
b if b.is_power_of_two() => b.trailing_zeros() as usize,
_ => 4,
}
}
}
impl From<Radix> for u8 {
fn from(r: Radix) -> u8 {
r.0
}
}
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum RoundingMode {
None = 1,
Up = 2,
Down = 4,
ToZero = 8,
FromZero = 16,
ToEven = 32,
ToOdd = 64,
}