Skip to content

Commit

Permalink
The rest of the 0.0.5 release
Browse files Browse the repository at this point in the history
  • Loading branch information
kotauskas committed Apr 2, 2020
1 parent 50abffd commit ba45702
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bigbit"
version = "0.0.4"
version = "0.0.5"
authors = ["Kotauskas <[email protected]>"]
edition = "2018"
description = "Implements the BigBig format, allowing for compact storage of arbitrarily large numbers."
Expand Down
21 changes: 8 additions & 13 deletions src/headbyte.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ use alloc::vec::Vec;
#[derive(Clone)]
pub struct HBNum {
hb: HeadByte,
followup: Vec<u8>
exponent: Option<Exponent>,
coefficients: Vec<u8>
}
impl HBNum {
pub fn from_headbyte_and_followup(hb: HeadByte, followup: Vec<u8>) -> Result<Self, ()> {
if hb.has_exponent() && followup.len() < 2 {Err(())} else {Ok(Self {hb, followup})}
pub fn from_raw_parts(hb: HeadByte, exponent: Option<Exponent>, coefficients: Vec<u8>) -> Self {
Self {hb, exponent, coefficients}
}

/// Returns the head byte.
Expand All @@ -29,22 +30,16 @@ impl HBNum {
self.hb
}
/// Returns the exponent, or `None` if it's not used (mainly the case for integers).
#[inline]
#[inline(always)]
#[must_use]
pub fn exponent(&self) -> Option<Exponent> {
if self.hb.has_exponent() {
unsafe {Some( Exponent::from_u8_unchecked(*self.followup.get_unchecked(0)) )}
} else {None}
self.exponent
}

/// Returns an iterator over the coefficients in little endian byte order.
#[inline]
#[inline(always)]
pub fn coefficient_le_iter(&self) -> impl Iterator<Item = u8> + DoubleEndedIterator + '_ {
if self.headbyte().has_exponent() {
self.followup[1..].iter()
} else {
self.followup.iter()
}.copied()
self.coefficients.iter().copied()
}
/// Returns an iterator over the coefficients in big endian byte order.
#[inline(always)]
Expand Down
42 changes: 33 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,45 @@
//! Since this is a format parser, `#![no_std]` is enabled by default, meaning that `alloc` is the only dependency, allowing you to use this in a freestanding environment.
//!
//! # State
//! Currently, not the entire BigBit standard is implemented. Here's a list of what's already done:
//! - Head Byte number storage
//! - Linked Bytes number storage
//! - Linked Bytes addition and subtraction (`Add`/`AddAssign` and `Sub`/`SubAssign`)
//! Currently, not the entire BigBit standard is implemented, and **the crate is not ready for use in production just yet**. There are also **no stability guarantees whatsoever**. Here's a list of what's already done:
//! - Head Byte number storage (not really finished, just a stub)
//! - Linked Bytes number storage and arithmetic
//! - Converting Linked Bytes to and from primitive integers
//! - Displaying Linked Bytes numbers in binary, octal, decimal and hexadecimal using formatters as well as other bases (arbitrary from 2 to 36) using a dedicated method
//! - Borrowed Linked Bytes (required for EHB) — a Linked Bytes number which doesn't own its contents and is a slice into an EHB number (still a stub)
//!
//! And here's a list of what's not finished just yet:
//! - Borrowed Linked Bytes (required for EHB) — a Linked Bytes number which doesn't own its contents and is a slice into an EHB number (will be added in 0.0.x)
//! - Creating HB/LB numbers from primitive integers and `f32`/`f64` (most likely will be added in 0.1.0)
//! - Creating \[E\]HB numbers from primitive integers and `f32`/`f64` (most likely will be added in 0.1.0)
//! - The Extended Header Byte format (will be added in 0.0.x)
//! - Arithmetic operations (addition, subtraction, multiplication and division are all defined by the BigBit standard), except for LB addition, which is already implemented; the main issue is dealing with the exponents (will mark the 1.0.0 release, might be partially added over the course of 0.x.x releases)
//! - Arithmetic operations (addition, subtraction, multiplication and division are all defined by the BigBit standard) for \[E\]HB; the main issue is dealing with the exponents (will mark the 1.0.0 release, might be partially added over the course of 0.x.x releases)
//! - Strings encoded using Linked Bytes (will be added in 0.0.x)
//! - `Debug` and `Display` formatting (i.e. converting the numbers either into a debugging-friendly representation as an array of bytes or a string representing the number in decimal scientific notation or full notation, as well as other numeric notations; simple `Debug` and `Display` decimal formatting will be added in 0.1.0 while the rest is planned for 1.0.0)
//! - `Debug` and `Display` formatting for \[E\]HB (i.e. converting the numbers either into a debugging-friendly representation as an array of bytes or a string representing the number in decimal scientific notation or full notation, as well as other numeric notations; simple `Debug` and `Display` decimal formatting will be added in 0.1.0 while the rest is planned for 1.0.0)
//! - **Tests** (planned for 0.1.0 but might be partially added earlier)
//!
//! ##### If you're wondering why all versions until `0.0.3` are yanked, these had a minor LB addition bug, so please upgrade if you haven't already.
//! # Changelog
//! ## 0.0.5
//! - Implemented arithmetic with `self` as the right operand for Linked Bytes, removing the need to always explicitly write `op1 + &op2` (same for other operators)
//! - Fixed the Crates.io badge to link to `bigbit` instead of `bi`**`t`**`bit`
//! - Added `usize` to the list of primitive integer types for which Linked Bytes arithmetic is implemented
//! - Added the `DivRem` and `DivRemAssign` traits for combined division (one operation to get the quotient and remainder)
//! - Renamed `HeadByte::from_headbyte_and_followup` into `from_raw_parts` ***(breaking)***
//! - Implemented logarithm with arbitrary base for Linked Bytes
//! - Implemented string formatting for Linked Bytes
//!
//! ## 0.0.4
//! - Implemented Linked Bytes multiplication and division
//! - Implemented Linked Bytes arithmetic with primitive integers
//! - Reorganized the internal module structure
//! - Added `LBNumRef`
//! - Implemented some more traits on `LBNum`
//!
//! ## 0.0.3
//! - Implemented Linked Bytes subtraction
//! - Started the reorganization
//! - Fixed addition bugs
//!
//!
//! If you're wondering why all versions until `0.0.3` are yanked, these had a minor LB addition bug, so please upgrade if you haven't already.
//!
//! [BigBitStd]: https://github.com/amitguptagwl/BigBit "BitBit specification on GitHub"
Expand Down
6 changes: 6 additions & 0 deletions src/linkedbytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,12 @@ impl<'a> core::ops::Deref for LBNumRef<'a> {
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct InvalidLBSequence;

// /// A Unicode string stored using the Linked Bytes format.
// ///
// /// This is more compact than all of the current UTF formats (namely, UTF-1, 7, 8, 16, let alone 32), since no surrogate pairs are used. Instead, the Linked Bytes format is leveraged, with separate codepoints being stored as individual Linked Bytes numbers. Both the link/end bits of the bytes and length of the entire message, either via the null terminator (which still works since a linking 0 has the most significant bit set to 1 and cannot be confused with the null terminator when reinterpreted as `u8`) or via storing it separately (as Rust `String`s do), are available. This means that the UTF-32 number of each codepoint can be encoded using the usual Linked Bytes format, with the link bit cleared in a byte indicating that one character has ended and a new one is coming next.
// #[derive(Clone, Debug)]
// pub struct LBString(LBSequence);

/// An owned unchecked Linked Bytes sequence, used for storing either strings or numbers.
#[derive(Clone, Debug)]
pub struct LBSequence(pub(crate) Vec<LinkedByte>);
Expand Down
14 changes: 14 additions & 0 deletions src/ops/linkedbytes/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ macro_rules! impl_add_with_primitive {
#[inline(always)]
fn add(mut self, rhs: $ty) -> Self {self += rhs; self}
}
impl core::ops::Add<LBNum> for $ty {
type Output = LBNum;
#[inline(always)]
fn add(self, rhs: LBNum) -> LBNum {rhs + self} // Since addition is commutative, we can just switch the operands around
} // and it's going to work automagically.
impl core::ops::AddAssign<$ty> for LBNum {
fn add_assign(&mut self, rhs: $ty) {
if self.0.inner().get(0).is_none() {
Expand All @@ -102,6 +107,15 @@ macro_rules! impl_add_with_primitive {
*self.0.get_mut(0).unwrap_or_else(||{unsafe{core::hint::unreachable_unchecked()}}) = val;
}
}
impl ops::AddAssign<LBNum> for $ty {
fn add_assign(&mut self, rhs: LBNum) {
if let Ok(val) = TryInto::<$ty>::try_into(*self + rhs) {
*self = val;
} else {
panic!("integer overflow while adding a BigBit number to a primitive integer");
}
}
}
};
}
impl_add_with_primitive!(u8 );
Expand Down
18 changes: 17 additions & 1 deletion src/ops/linkedbytes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,20 @@ impl_partial_eq_ord_to_primitive!(u16 );
impl_partial_eq_ord_to_primitive!(u32 );
impl_partial_eq_ord_to_primitive!(u64 );
impl_partial_eq_ord_to_primitive!(u128 );
impl_partial_eq_ord_to_primitive!(usize);
impl_partial_eq_ord_to_primitive!(usize);

impl LBNum {
/// Consumes `self` and returns the logarithm of the given base.
#[inline]
#[must_use = "this is an expensive non-in-place operation"]
pub fn logb(mut self, base: LBNum) -> Self {
let mut result = Self::ZERO;
let divide_by = base.clone();
let base_m1 = base - 1u8;
while self > base_m1 {
self /= &divide_by;
result.increment();
}
result
}
}

0 comments on commit ba45702

Please sign in to comment.