Skip to content

Commit

Permalink
Added BTryFrom trait, change to #[derive(PartialEq, Eq)]
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacholt100 committed Sep 27, 2023
1 parent ca1b6fe commit 28283d3
Show file tree
Hide file tree
Showing 22 changed files with 275 additions and 157 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: codecov report

on:
pull_request:
branches: "**"

env:
CARGO_TERM_COLOR: always

jobs:
codecov:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update nightly
- name: Set nightly as default
run: rustup default nightly
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Generate code coverage
run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
fail_ci_if_error: true
18 changes: 9 additions & 9 deletions .github/workflows/publish-dry-run.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
name: Publish dry run

on:
pull_request:
branches:
- master
pull_request:
branches:
- master

jobs:
publish_dry_run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: publish dry run
run: cargo publish --dry-run
publish_dry_run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: publish dry run
run: cargo publish --dry-run
24 changes: 12 additions & 12 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
name: Publish to crates.io

on:
push:
branches:
- master
push:
branches:
- master

jobs:
#test:
# uses: ./.github/workflows/test.yml
publish:
#needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: publish
run: cargo publish --token ${{ secrets.CRATES_IO_TOKEN }}
#test:
# uses: ./.github/workflows/test.yml
publish:
#needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: publish
run: cargo publish --token ${{ secrets.CRATES_IO_TOKEN }}
20 changes: 0 additions & 20 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,6 @@ env:
CARGO_TERM_COLOR: always

jobs:
codecov:
runs-on: ubuntu-latest
env:
CARGO_TERM_COLOR: always
steps:
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update nightly
- name: Set nightly as default
run: rustup default nightly
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Generate code coverage
run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
fail_ci_if_error: true
build_stable:
runs-on: ubuntu-latest
steps:
Expand Down
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,11 @@
[![Crates.io](https://img.shields.io/crates/d/bnum?logo=rust)
](https://crates.io/crates/bnum)
[![dependency status](https://deps.rs/repo/github/isaacholt100/bnum/status.svg)](https://deps.rs/repo/github/isaacholt100/bnum)
[![codecov](https://codecov.io/gh/isaacholt100/bnum/branch/v0.9.0/graph/badge.svg)](https://codecov.io/gh/isaacholt100/bnum)
[![license](https://img.shields.io/crates/l/bnum)](https://github.com/isaacholt100/bnum)

Arbitrary precision, fixed-size signed and unsigned integer types for Rust.

## Why bnum?

- **Zero dependencies by default**: `bnum` does not depend on any other crates by default. Support for crates such as [`rand`](https://docs.rs/rand/latest/rand/) and [`serde`](https://docs.rs/serde/latest/serde/) can be enabled with crate [features](#features).
- **`no-std` compatible**: `bnum` can be used in `no_std` environments, provided that the [`arbitrary`](#fuzzing) and [`quickcheck`](#quickcheck) features are not enabled.
- **Compile-time integer parsing**: the `from_str_radix` and `parse_str_radix` methods on bnum integers are `const`, which allows parsing of integers from string slices at compile time. Note that this is more powerful than compile-time parsing of integer literals. This is because it allows parsing of strings in all radices from `2` to `36` inclusive instead of just `2`, `8`, `10` and `16`. Additionally, the string to be parsed does not have to be a literal: it could, for example, be obtained via `include_str!("...")`, or `option_env!("...")`.
- **`const` evaluation**: nearly all methods defined on bnum integers are `const`, which allows complex compile-time calculations.

## Overview

The aim of this crate is to provide integer types of arbitrary fixed size which behave exactly like Rust's primitive integer types: `u8`, `i8`, `u16`, `i16`, etc. Nearly all methods defined on Rust's signed and unsigned primitive integers are defined `bnum`'s signed and unsigned integers. Additionally, some other useful methods are provided, mostly inspired by the [`BigInt`](https://docs.rs/num-bigint/latest/num_bigint/struct.BigInt.html) and [`BigUint`](https://docs.rs/num-bigint/latest/num_bigint/struct.BigUint.html) types from the [`num_bigint`](https://docs.rs/num-bigint/latest/num_bigint/index.html) crate.
Expand All @@ -26,6 +20,13 @@ This crate uses Rust's const generics to allow creation of integers of arbitrary

`BUint` and `BInt` are the fastest as they store (and so operate on) the least number of digits for a given bit size. However, the drawback is that the bit size must be a multiple of `64` (`bitsize = N * 64`). This is why other integer types are provided as well, as they allow the bit size to be a multiple of `32`, `16`, or `8` instead. When choosing which of these types to use, determine which of `64, 32, 16, 8` is the largest multiple of the desired bit size, and use the corresponding type. For example, if you wanted a 96-bit unsigned integer, 32 is the largest multiple of 96 out of these, so use `BUintD32<3>`. A 40-bit signed integer would be `BIntD8<5>`.

## Why bnum?

- **Zero dependencies by default**: `bnum` does not depend on any other crates by default. Support for crates such as [`rand`](https://docs.rs/rand/latest/rand/) and [`serde`](https://docs.rs/serde/latest/serde/) can be enabled with crate [features](#features).
- **`no-std` compatible**: `bnum` can be used in `no_std` environments, provided that the [`arbitrary`](#fuzzing) and [`quickcheck`](#quickcheck) features are not enabled.
- **Compile-time integer parsing**: the `from_str_radix` and `parse_str_radix` methods on bnum integers are `const`, which allows parsing of integers from string slices at compile time. Note that this is more powerful than compile-time parsing of integer literals. This is because it allows parsing of strings in all radices from `2` to `36` inclusive instead of just `2`, `8`, `10` and `16`. Additionally, the string to be parsed does not have to be a literal: it could, for example, be obtained via `include_str!("...")`, or `env!("...")`.
- **`const` evaluation**: nearly all methods defined on bnum integers are `const`, which allows complex compile-time calculations.

## Installation

To install and use `bnum`, simply add the following line to your `Cargo.toml` file in the `[dependencies]` section:
Expand Down Expand Up @@ -148,6 +149,10 @@ At the moment, the [`From`](https://doc.rust-lang.org/core/convert/trait.From.ht

The [`num_traits::NumCast`](https://docs.rs/num-traits/latest/num_traits/cast/trait.NumCast.html) trait is implemented for bnum's integers but will panic if its method [`from`](https://docs.rs/num-traits/latest/num_traits/cast/trait.NumCast.html#tymethod.from) is called, as it is not possible to guarantee a correct conversion, due to trait bounds enforced by [`NumCast`](https://docs.rs/num-traits/latest/num_traits/cast/trait.NumCast.html). This trait should therefore never be used on bnum's integers. The implementation exists only to allow implementation of the [`num_traits::PrimInt`](https://docs.rs/num-traits/latest/num_traits/int/trait.PrimInt.html) trait for bnum's integers.

## Prior bugs

The short list of bugs in previous versions can be found at [`changes/prior-bugs.md`](https://github.com/isaacholt100/bnum/blob/master/changes/prior-bugs.md).

## Future Work

This library aims to provide arbitrary, fixed precision equivalents of Rust's 3 built-in number types: signed integers, unsigned integers and floats. Signed and unsigned integers have been implemented and fully tested, and will aim to keep up to date with Rust's integer interface. (e.g. when a new method is implemented on a Rust primitive integer, this library will attempt to keep in step to include that method as well. This includes nightly-only methods.)
Expand Down
4 changes: 0 additions & 4 deletions changes/incorrect-code

This file was deleted.

4 changes: 4 additions & 0 deletions changes/prior-bugs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- `<= v0.1.0`: incorrect implementation of `from_be`, `to_be` on all integers.
- `<= v0.8.0`: `unchecked_shl`, `unchecked_shr` (only for `BUint` with `64` bit digits).
- `<= v0.8.0`: incorrect implementation of `Add<$Digit>` for all `BUint`s (where `$Digit` is the underlying digit type).
- `<= v0.8.0`: `lcm` incorrectly panics when `self` is zero.
8 changes: 5 additions & 3 deletions changes/v0.9.0
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
- Performance enhancement for `shr` methods
- Make wrapping_rem panic message same as for primitives
- Breaking: make unchecked_shl, unchecked_shr take u32 as shift argument, not Self.
- **NOTE**: the previous implementation of unchecked_shl, unchecked_shr for 64 digit integers was incorrect, it has now been fixed.
- Fixed incorrect implementation of Add<Digit> for all BUints
- Fixed lcm implementation to not panic if self is zero
- Fixed incorrect implementation of unchecked_shl, unchecked_shr for 64 bit digit integers.
- Fixed incorrect implementation of Add<$Digit> for all BUints
- Fixed lcm implementation to not panic if self is zero
- Changed to #[derive(PartialEq, Eq)] to allow pattern matching on const values.
- Added trait `BTryFrom` for fallible conversions between bnum integers (`TryFrom` can't be used due to the automatic implementation of `TryFrom<T> for T`).
27 changes: 0 additions & 27 deletions lit-parser/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,3 @@

fn main() {
// let a: u128 = x324534;
// let a = lit_parser::n!(x234987234x24);
// println!("{}", a);
for i in 126..=126 {
println!("{}, {}", log10_2e(i), 2.0f64.powi(i as i32).log10().floor());
}
}

fn log10_2e(e: u128) -> u128 {
let mut pow = 0;
let mut current_pow = 0;
let mut mod10 = 1;
for i in 0..e {
mod10 *= 2;
if mod10 >= 10 {
current_pow += 1;
mod10 %= 10;
if current_pow > pow {
pow = current_pow;
current_pow = 0;
}
}
// println!("{}", mod10);
// println!("{}", current_pow);
// println!("{}\n", pow);
}
pow
}
12 changes: 6 additions & 6 deletions scripts/quickcheck_test.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
export QUICKCHECK_TESTS=1000000
while true
do
RUSTFLAGS="--cfg test_int_bits=\"$1\"" cargo test quickcheck_ --quiet --features="$2 rand numtraits nightly"
clear && printf '\e[3J'
if [ $? -ne 0 ]
then
exit 1
fi
RUSTFLAGS="--cfg test_int_bits=\"$1\"" cargo test quickcheck_ --quiet --features="$2 rand numtraits nightly"
clear && printf '\e[3J'
if [ $? -ne 0 ]
then
exit 1
fi
done
16 changes: 8 additions & 8 deletions scripts/quickcheck_test_name.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ export QUICKCHECK_TESTS=1000000
iters=0
while true
do
cargo test --all-features --lib --quiet $1
if [ $? -ne 0 ]
then
exit 1
fi
clear && printf '\e[3J'
((iters=iters+1))
echo "iterations: $iters"
cargo test --all-features --lib --quiet $1
if [ $? -ne 0 ]
then
exit 1
fi
clear && printf '\e[3J'
((iters=iters+1))
echo "iterations: $iters"
done
24 changes: 12 additions & 12 deletions scripts/run_all_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ CYAN_COLOR="\033[0;36;1m"
RESET_FORMAT="\033[0m"

test_integer_info () {
echo "\n${CYAN_COLOR}info${RESET_FORMAT}: running tests with $1-bit test integers..."
echo "\n${CYAN_COLOR}info${RESET_FORMAT}: running tests with $1-bit test integers..."
}

export QUICKCHECK_TESTS=10000

run_test () {
echo $QUICKCHECK_TESTS
test_integer_info "$1"
RUSTFLAGS="--cfg test_int_bits=\"$1\"" cargo test int --lib --quiet $2
if [ $? -ne 0 ]
then
exit 1
fi
test_integer_info "$1"
RUSTFLAGS="--cfg test_int_bits=\"$1\"" cargo test int --lib --quiet $2
if [ $? -ne 0 ]
then
exit 1
fi
}

for flags in "" "--all-features"
do
echo "\n${CYAN_COLOR}info${RESET_FORMAT}: running tests with flags '$flags'..."
for bits in 64 128
do
run_test $bits $flags
done
echo "\n${CYAN_COLOR}info${RESET_FORMAT}: running tests with flags '$flags'..."
for bits in 64 128
do
run_test $bits $flags
done
done
3 changes: 0 additions & 3 deletions scripts/set_num_tests.sh

This file was deleted.

22 changes: 11 additions & 11 deletions src/bint/cmp.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use crate::nightly::impl_const;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::cmp::{Ord, Ordering, PartialOrd};

macro_rules! cmp {
($BUint: ident, $BInt: ident, $Digit: ident) => {
impl_const! {
impl<const N: usize> const PartialEq for $BInt<N> {
#[inline]
fn eq(&self, other: &Self) -> bool {
Self::eq(self, other)
}
}
}

impl<const N: usize> Eq for $BInt<N> {}
// impl_const! {
// impl<const N: usize> const PartialEq for $BInt<N> {
// #[inline]
// fn eq(&self, other: &Self) -> bool {
// Self::eq(self, other)
// }
// }
// }

// impl<const N: usize> Eq for $BInt<N> {}

impl_const! {
impl<const N: usize> const PartialOrd for $BInt<N> {
Expand Down
32 changes: 18 additions & 14 deletions src/bint/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,26 +150,30 @@ macro_rules! convert {
int_try_from_bint!($BInt, $Digit; i8, i16, i32, i64, i128, isize);
uint_try_from_bint!($BInt; u8, u16, u32, u64, u128, usize);

impl_const! {
impl<const N: usize> const TryFrom<$BUint<N>> for $BInt<N> {
type Error = TryFromIntError;

#[inline]
fn try_from(u: $BUint<N>) -> Result<Self, Self::Error> {
if u.leading_ones() != 0 {
Err(TryFromIntError(()))
} else {
Ok(Self::from_bits(u))
}
}
}
}
// impl_const! {
// impl<const N: usize> const TryFrom<$BUint<N>> for $BInt<N> {
// type Error = TryFromIntError;

// #[inline]
// fn try_from(u: $BUint<N>) -> Result<Self, Self::Error> {
// if u.leading_ones() != 0 {
// Err(TryFromIntError(()))
// } else {
// Ok(Self::from_bits(u))
// }
// }
// }
// }

#[cfg(test)]
paste::paste! {
mod [<$Digit _digit_tests>] {
use crate::test::types::big_types::$Digit::*;
use crate::test::{self, types::itest};
use crate::test::cast_types::*;
use crate::BTryFrom;

test::test_btryfrom!(itest; UTESTD8, UTESTD16, UTESTD32, UTESTD64, TestUint1, TestUint2, TestUint3, TestUint4, TestUint5, TestUint6, TestUint7, TestUint8, TestUint9, TestUint10, ITESTD8, ITESTD16, ITESTD32, ITESTD64, TestInt1, TestInt2, TestInt3, TestInt4, TestInt5, TestInt6, TestInt7, TestInt8, TestInt9, TestInt10);

#[cfg(not(test_int_bits = "64"))]
test::test_from! {
Expand Down
4 changes: 1 addition & 3 deletions src/bint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ macro_rules! mod_impl {
///
#[doc = doc::arithmetic_doc!($BInt)]

// Clippy: we can allow derivation of `Hash` and manual implementation of `PartialEq` as the derived `PartialEq` would be the same except we make our implementation const.
#[allow(clippy::derived_hash_with_manual_eq)]
#[derive(Clone, Copy, Hash)]
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "valuable", derive(valuable::Valuable))]
Expand Down
Loading

0 comments on commit 28283d3

Please sign in to comment.