Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
.vscode/
/target
Cargo.lock
#winmerge
**/*.bak
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,21 @@ readme = "README.md"
repository = "https://github.com/stencillogic/astro-float"

[dependencies]
astro-float-num = { version = "0.3.6", default-features = false }
astro-float-macro = "0.4.5"
astro-float-num = {path = "astro-float-num",default-features = false } #{ version = "0.3.6", default-features = false }
astro-float-macro = {path = "astro-float-macro" } #"0.4.5"

[features]
default = ["std", "random", "serde"]
std = ["astro-float-num/std"]
random = ["astro-float-num/random"]
serde = ["astro-float-num/serde"]
rkyv = ["astro-float-num/rkyv"]

[dev-dependencies]
astro-float-num = { path = "astro-float-num",default-features = false , features = [ "rkyv" ] }
trybuild = "1.0"
rusty-hook = "0.11.2"
rkyv = "0.8" #couldn't run tests in astro-num on msvc(mpfr won't build)

[workspace]
members = [
Expand Down
2 changes: 2 additions & 0 deletions astro-float-num/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ serde = { version = "1.0.147", optional = true }
rand = { version = "0.8.5", optional = true }
lazy_static = { version = "1.4.0", default-features = false, features = [] }
itertools = { version = "0.10.3", default-features = false, features = [] }
rkyv = { version = "0.8", features = [ "bytecheck" ] , optional = true }

[features]
default = ["std", "random", "serde"]
std = []
random = ["dep:rand"]
serde = ["dep:serde"]
rkyv = ["dep:rkyv"]
4 changes: 4 additions & 0 deletions astro-float-num/src/common/buf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ use crate::common::util::shift_slice_right;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;

#[cfg(feature = "rkyv")]
use rkyv::{Archive, Serialize, Deserialize};

/// Buffer for holding mantissa gidits.
#[derive(Debug, Hash)]
#[cfg_attr(feature = "rkyv", derive(Archive, Serialize, Deserialize))]
pub struct WordBuf {
inner: Vec<Word>,
}
Expand Down
85 changes: 85 additions & 0 deletions astro-float-num/src/defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use std::collections::TryReserveError;
#[cfg(not(feature = "std"))]
use alloc::collections::TryReserveError;

#[cfg(feature = "rkyv")]
use rkyv::{Archive, Serialize, Deserialize};

/// A word.
#[cfg(not(target_arch = "x86"))]
pub type Word = u64;
Expand Down Expand Up @@ -79,6 +82,87 @@ pub enum Sign {
Pos = 1,
}

#[cfg(feature = "rkyv")]
mod rkyv_impl {
use super::Sign;
use rkyv::{
bytecheck::{CheckBytes, InvalidEnumDiscriminantError, Verify},
primitive::ArchivedI16,
rancor::{fail, Fallible, Source},
traits::NoUndef,
Archive, Deserialize, Place, Portable, Serialize,
};
// Hand-written archived enum
#[derive(CheckBytes, Portable)]
#[bytecheck(crate = rkyv::bytecheck, verify)]
#[repr(C)]
pub struct ArchivedSign(ArchivedI16);

// Implementation detail: `ArchivedMyEnum` has no undef bytes
unsafe impl NoUndef for ArchivedSign {}

impl ArchivedSign {
// Internal fallible conversion back to the original enum
fn try_to_native(&self) -> Option<Sign> {
Some(match self.0.to_native() {
-1 => Sign::Neg,
1 => Sign::Pos,
_ => return None,
})
}

// Public infallible conversion back to the original enum
pub fn to_native(&self) -> Sign {
unsafe { self.try_to_native().unwrap_unchecked() }
}
}

unsafe impl<C: Fallible + ?Sized> Verify<C> for ArchivedSign
where
C::Error: Source,
{
// verify runs after all of the fields have been checked
fn verify(&self, _: &mut C) -> Result<(), C::Error> {
// Use the internal conversion to try to convert back
if self.try_to_native().is_none() {
// Return an error if it fails (i.e. the discriminant did not match
// any valid discriminants)
fail!(InvalidEnumDiscriminantError {
enum_name: "ArchivedSign",
invalid_discriminant: self.0.to_native(),
})
}
Ok(())
}
}

impl Archive for Sign {
type Archived = ArchivedSign;
type Resolver = ();

fn resolve(&self, _: Self::Resolver, out: Place<Self::Archived>) {
// Convert Sign -> i16 -> ArchivedI16 and write to `out`
out.write(ArchivedSign((*self as i16).into()));
}
}

// Serialization is a no-op because there's no out-of-line data
impl<S: Fallible + ?Sized> Serialize<S> for Sign {
fn serialize(&self, _: &mut S) -> Result<Self::Resolver, <S as Fallible>::Error> {
Ok(())
}
}

// Deserialization just calls the public conversion and returns the result
impl<D: Fallible + ?Sized> Deserialize<Sign, D> for ArchivedSign {
fn deserialize(&self, _: &mut D) -> Result<Sign, <D as Fallible>::Error> {
Ok(self.to_native())
}
}
}
#[cfg(feature = "rkyv")]
pub use rkyv_impl::*;

impl Sign {
/// Changes the sign to the opposite.
pub fn invert(&self) -> Self {
Expand Down Expand Up @@ -106,6 +190,7 @@ impl Sign {

/// Possible errors.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "rkyv", derive(Archive, Serialize, Deserialize))]
pub enum Error {
/// The exponent value becomes greater than the upper limit of the range of exponent values.
ExponentOverflow(Sign),
Expand Down
5 changes: 5 additions & 0 deletions astro-float-num/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ use crate::Word;
use core::num::FpCategory;
use lazy_static::lazy_static;

#[cfg(feature = "rkyv")]
use rkyv::{Archive, Serialize, Deserialize};

#[cfg(feature = "std")]
use core::fmt::Write;

Expand Down Expand Up @@ -45,11 +48,13 @@ lazy_static! {

/// A floating point number of arbitrary precision.
#[derive(Debug)]
#[cfg_attr(feature = "rkyv", derive(Archive, Serialize, Deserialize))]
pub struct BigFloat {
inner: Flavor,
}

#[derive(Debug)]
#[cfg_attr(feature = "rkyv", derive(Archive, Serialize, Deserialize))]
enum Flavor {
Value(BigFloatNumber),
NaN(Option<Error>),
Expand Down
4 changes: 4 additions & 0 deletions astro-float-num/src/mantissa/mantissa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ use crate::mantissa::util::RightShiftedSlice;
use core::mem::size_of;
use itertools::izip;

#[cfg(feature = "rkyv")]
use rkyv::{Archive, Serialize, Deserialize};

/// Mantissa representation.
#[derive(Debug, Hash)]
#[cfg_attr(feature = "rkyv", derive(Archive, Serialize, Deserialize))]
pub struct Mantissa {
m: WordBuf,
n: usize, // number of bits, 0 is for number 0
Expand Down
4 changes: 4 additions & 0 deletions astro-float-num/src/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ use crate::defs::WORD_BIT_SIZE;
use crate::defs::WORD_SIGNIFICANT_BIT;
use crate::mantissa::Mantissa;

#[cfg(feature = "rkyv")]
use rkyv::{Archive, Serialize, Deserialize};

/// A finite floating point number with mantissa of an arbitrary size, an exponent, and the sign.
#[derive(Debug, Hash)]
#[cfg_attr(feature = "rkyv", derive(Archive, Serialize, Deserialize))]
pub(crate) struct BigFloatNumber {
e: Exponent,
s: Sign,
Expand Down
4 changes: 4 additions & 0 deletions tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// Additional tests of the library.

#[cfg(feature = "rkyv")]
#[cfg(test)]
mod rkyv;

use astro_float_macro::expr;
use astro_float_num::{
ctx::Context, BigFloat, Consts, Radix, RoundingMode, Sign, EXPONENT_MAX, EXPONENT_MIN,
Expand Down
33 changes: 33 additions & 0 deletions tests/rkyv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

#[cfg(test)]
mod tests {
use rkyv::{
to_bytes,
deserialize,
rancor::Error,
access_unchecked,
Archive,
};

use astro_float_num::{
BigFloat,
//ArchivedBigFloat
};

#[test]
fn to_from_rkyv() {
let zero = &BigFloat::new(0);
let bytes = to_bytes::<Error>(zero).unwrap();
let archived =
unsafe { access_unchecked::<<BigFloat as Archive>::Archived>(&bytes) };
let bf : BigFloat = deserialize::<BigFloat, Error>(archived).unwrap();
assert_eq!(bf,zero);

let bf = BigFloat::from_f32(0.3, 64 + 1);
let bytes = to_bytes::<Error>(&bf).unwrap();
let archived =
unsafe { access_unchecked::<<BigFloat as Archive>::Archived>(&bytes) };
let bf2 : BigFloat = deserialize::<BigFloat, Error>(archived).unwrap();
assert_eq!(bf,bf2);
}
}