feat: no_std support
* no_std support * Use integer log2 when possible to estimate allocations * Remove std features from a few dependencies * Use libm for missing funcs in nostd environment * Use autocfg to detect presence of i128 * Better CI test for nostd environment * Move benchmark to a separate crate * Make the tests pass in no_std builds * Use thumbv7m target for nostd build test * Add documentation about the no-std compatibility * Make zeroize and prime features no_std-compatible * Test each feature in nostd context * Fix mac test to work in no_std environment * Avoid using thread_rng in nostd tests * Fix prime tests in nostd mode * Fix all warnings and errors * Only test nostd builds on nightly on travis * Travis: Only do nostd builds on nightly
This commit is contained in:
parent
688ad829e5
commit
874ab0fbaa
23
Cargo.toml
23
Cargo.toml
@ -16,11 +16,6 @@ autobenches = false
|
||||
[package.metadata.docs.rs]
|
||||
features = ["std", "serde", "rand", "prime"]
|
||||
|
||||
[[bench]]
|
||||
harness = false
|
||||
name = "bench_main"
|
||||
required-features = ["prime"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dependencies.smallvec]
|
||||
@ -43,37 +38,47 @@ default-features = false
|
||||
optional = true
|
||||
version = "0.6"
|
||||
default-features = false
|
||||
features = ["std"]
|
||||
|
||||
[dependencies.zeroize]
|
||||
version = "0.6"
|
||||
optional = true
|
||||
default-features = false
|
||||
features = ["zeroize_derive"]
|
||||
|
||||
[dependencies.serde]
|
||||
optional = true
|
||||
version = "1.0"
|
||||
default-features = false
|
||||
features = ["std"]
|
||||
|
||||
[dependencies.libm]
|
||||
version = "0.1.4"
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1.2.0"
|
||||
default-features = false
|
||||
# no_std feature is an anti-pattern. Why, lazy_static, why?
|
||||
# See https://github.com/rust-lang-nursery/lazy-static.rs/issues/150
|
||||
features = ["spin_no_std"]
|
||||
|
||||
[dependencies.byteorder]
|
||||
version = "1.2.7"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.2"
|
||||
rand_chacha = "0.1"
|
||||
rand_xorshift = "0.1"
|
||||
rand_isaac = "0.1"
|
||||
|
||||
[build-dependencies]
|
||||
autocfg = "0.1.5"
|
||||
|
||||
[dev-dependencies.serde_test]
|
||||
version = "1.0"
|
||||
|
||||
[features]
|
||||
default = ["std", "i128", "u64_digit"]
|
||||
i128 = ["num-integer/i128", "num-traits/i128"]
|
||||
std = ["num-integer/std", "num-traits/std", "smallvec/std", "rand/std"]
|
||||
std = ["num-integer/std", "num-traits/std", "smallvec/std", "rand/std", "serde/std", "zeroize/std"]
|
||||
u64_digit = []
|
||||
prime = ["rand"]
|
||||
nightly = ["zeroize/nightly", "rand/nightly"]
|
||||
|
12
README.md
12
README.md
@ -26,10 +26,14 @@ extern crate num_bigint_dig as num_bigint;
|
||||
|
||||
## Features
|
||||
|
||||
The `std` crate feature is mandatory and enabled by default. If you depend on
|
||||
`num-bigint` with `default-features = false`, you must manually enable the
|
||||
`std` feature yourself. In the future, we hope to support `#![no_std]` with
|
||||
the `alloc` crate when `std` is not enabled.
|
||||
The `std` feature is enabled by default and mandatory to compile on older rust
|
||||
version.
|
||||
|
||||
On Rust 1.36 and later, it is possible to use this crate on no_std target. If
|
||||
you wish to compile for a target that does not have an `std` crate, you should
|
||||
use `num-bigint` with `default-features = false`. All other sub-features should
|
||||
be compatible with no_std. Note that in this mode, `num-bigint` still relies on
|
||||
the alloc crate, so make sure you define a `global_allocator`.
|
||||
|
||||
Implementations for `i128` and `u128` are only available with Rust 1.26 and
|
||||
later. The build script automatically detects this, but you can make it
|
||||
|
19
benchmark_crate/Cargo.toml
Normal file
19
benchmark_crate/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "num-bigint-dig-benchmark"
|
||||
version = "0.0.0"
|
||||
autobenches = false
|
||||
publish = false
|
||||
|
||||
[[bench]]
|
||||
harness = false
|
||||
name = "bench_main"
|
||||
|
||||
[dependencies]
|
||||
num-bigint-dig = { path = "../", features = ["prime", "rand"] }
|
||||
num-integer = "0.1.39"
|
||||
num-traits = "0.2.4"
|
||||
rand = "0.6"
|
||||
rand_chacha = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.2"
|
@ -1,5 +1,3 @@
|
||||
#![cfg(feature = "rand")]
|
||||
|
||||
use criterion::Criterion;
|
||||
use num_bigint::{BigUint, RandBigInt};
|
||||
use num_traits::Pow;
|
0
benchmark_crate/src/lib.rs
Normal file
0
benchmark_crate/src/lib.rs
Normal file
33
build.rs
33
build.rs
@ -1,35 +1,12 @@
|
||||
extern crate autocfg;
|
||||
use std::env;
|
||||
use std::io::Write;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
fn main() {
|
||||
if probe("fn main() { 0i128; }") {
|
||||
let ac = autocfg::new();
|
||||
|
||||
if ac.probe_type("i128") {
|
||||
println!("cargo:rustc-cfg=has_i128");
|
||||
} else if env::var_os("CARGO_FEATURE_I128").is_some() {
|
||||
panic!("i128 support was not detected!");
|
||||
}
|
||||
}
|
||||
|
||||
/// Test if a code snippet can be compiled
|
||||
fn probe(code: &str) -> bool {
|
||||
let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
|
||||
let out_dir = env::var_os("OUT_DIR").expect("environment variable OUT_DIR");
|
||||
|
||||
let mut child = Command::new(rustc)
|
||||
.arg("--out-dir")
|
||||
.arg(out_dir)
|
||||
.arg("--emit=obj")
|
||||
.arg("-")
|
||||
.stdin(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("rustc probe");
|
||||
|
||||
child
|
||||
.stdin
|
||||
.as_mut()
|
||||
.expect("rustc stdin")
|
||||
.write_all(code.as_bytes())
|
||||
.expect("write rustc stdin");
|
||||
|
||||
child.wait().expect("rustc probe").success()
|
||||
}
|
||||
}
|
@ -16,10 +16,27 @@ cargo test --verbose
|
||||
cargo build --no-default-features --features="std"
|
||||
cargo test --no-default-features --features="std"
|
||||
|
||||
# It should build in no_std
|
||||
if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then
|
||||
rustup target add thumbv7m-none-eabi
|
||||
cargo build --no-default-features --target=thumbv7m-none-eabi
|
||||
|
||||
# It should work in no_std on nightly.
|
||||
# Note: Doctest might show an error: https://github.com/rust-lang/rust/issues/54010
|
||||
# The "error" is wrong however, the doctests still run.
|
||||
cargo test --no-default-features
|
||||
fi
|
||||
|
||||
# Each isolated feature should also work everywhere.
|
||||
for feature in $FEATURES; do
|
||||
cargo build --verbose --no-default-features --features="std $feature"
|
||||
cargo test --verbose --no-default-features --features="std $feature"
|
||||
|
||||
# Ensure that feature also works in nostd context on nightly.
|
||||
if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then
|
||||
cargo build --verbose --no-default-features --features="$feature"
|
||||
cargo test --verbose --no-default-features --features="$feature"
|
||||
fi
|
||||
done
|
||||
|
||||
# test all supported features together
|
||||
@ -28,5 +45,6 @@ cargo test --features="std $FEATURES"
|
||||
|
||||
# make sure benchmarks can be built
|
||||
if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then
|
||||
cd benchmark_crate
|
||||
cargo bench --all-features --no-run
|
||||
fi
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::mem;
|
||||
use core::mem;
|
||||
|
||||
/// Find last set bit
|
||||
/// fls(0) == 0, fls(u32::MAX) == 32
|
||||
@ -9,3 +9,12 @@ pub fn fls<T: num_traits::PrimInt>(v: T) -> usize {
|
||||
pub fn ilog2<T: num_traits::PrimInt>(v: T) -> usize {
|
||||
fls(v) - 1
|
||||
}
|
||||
|
||||
/// Divide two integers, and ceil the result.
|
||||
pub fn idiv_ceil<T: num_traits::PrimInt>(a: T, b: T) -> T {
|
||||
if a % b != T::zero() {
|
||||
a / b + T::one()
|
||||
} else {
|
||||
a / b
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use core::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
|
||||
use crate::big_digit::BigDigit;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use num_traits::{One, Zero};
|
||||
use smallvec::SmallVec;
|
||||
use std::cmp::Ordering;
|
||||
use core::cmp::Ordering;
|
||||
|
||||
use crate::algorithms::{add2, cmp_slice, sub2};
|
||||
use crate::big_digit::{self, BigDigit, DoubleBigDigit};
|
||||
|
@ -4,8 +4,8 @@ use crate::bigint::{BigInt, ToBigInt};
|
||||
use crate::biguint::{BigUint, IntDigits};
|
||||
use integer::Integer;
|
||||
use num_traits::{One, Signed, Zero};
|
||||
use std::borrow::Cow;
|
||||
use std::ops::Neg;
|
||||
use alloc::borrow::Cow;
|
||||
use core::ops::Neg;
|
||||
|
||||
/// XGCD sets z to the greatest common divisor of a and b and returns z.
|
||||
/// If extended is true, XGCD returns their value such that z = a*x + b*y.
|
||||
@ -98,8 +98,8 @@ fn lehmer_gcd(
|
||||
|
||||
// Ensure that a >= b
|
||||
if a < b {
|
||||
std::mem::swap(&mut a, &mut b);
|
||||
std::mem::swap(&mut ua, &mut ub);
|
||||
core::mem::swap(&mut a, &mut b);
|
||||
core::mem::swap(&mut ua, &mut ub);
|
||||
}
|
||||
|
||||
// loop invariant A >= B
|
||||
@ -277,8 +277,8 @@ pub fn extended_gcd(
|
||||
|
||||
// Ensure that a >= b
|
||||
if a < b {
|
||||
std::mem::swap(&mut a, &mut b);
|
||||
std::mem::swap(&mut ua, &mut ub);
|
||||
core::mem::swap(&mut a, &mut b);
|
||||
core::mem::swap(&mut ua, &mut ub);
|
||||
}
|
||||
|
||||
let mut q: BigInt = 0.into();
|
||||
@ -527,8 +527,8 @@ fn euclid_udpate(
|
||||
*q = q_new;
|
||||
*r = r_new;
|
||||
|
||||
std::mem::swap(a, b);
|
||||
std::mem::swap(b, r);
|
||||
core::mem::swap(a, b);
|
||||
core::mem::swap(b, r);
|
||||
|
||||
if extended {
|
||||
// ua, ub = ub, ua - q * ub
|
||||
@ -546,7 +546,7 @@ fn euclid_udpate(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::str::FromStr;
|
||||
use core::str::FromStr;
|
||||
|
||||
use num_traits::FromPrimitive;
|
||||
|
||||
@ -574,11 +574,11 @@ mod tests {
|
||||
while !r.is_zero() {
|
||||
let quotient = &old_r / &r;
|
||||
old_r = old_r - "ient * &r;
|
||||
std::mem::swap(&mut old_r, &mut r);
|
||||
core::mem::swap(&mut old_r, &mut r);
|
||||
old_s = old_s - "ient * &s;
|
||||
std::mem::swap(&mut old_s, &mut s);
|
||||
core::mem::swap(&mut old_s, &mut s);
|
||||
old_t = old_t - quotient * &t;
|
||||
std::mem::swap(&mut old_t, &mut t);
|
||||
core::mem::swap(&mut old_t, &mut t);
|
||||
}
|
||||
|
||||
(old_r, old_s, old_t)
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::cmp;
|
||||
use std::iter::repeat;
|
||||
use core::cmp;
|
||||
use core::iter::repeat;
|
||||
|
||||
use crate::algorithms::{adc, add2, sub2, sub_sign};
|
||||
use crate::big_digit::{BigDigit, DoubleBigDigit, BITS};
|
||||
@ -310,7 +310,7 @@ mod tests {
|
||||
#[cfg(feature = "u64_digit")]
|
||||
#[test]
|
||||
fn test_mac3_regression() {
|
||||
let b: Vec<BigDigit> = vec![
|
||||
let b = [
|
||||
6871754923702299421,
|
||||
18286959765922425554,
|
||||
16443042141374662930,
|
||||
@ -657,7 +657,7 @@ mod tests {
|
||||
17511662813348858473,
|
||||
12,
|
||||
];
|
||||
let c: Vec<BigDigit> = vec![
|
||||
let c = [
|
||||
13147625290258353449,
|
||||
13817956093586917764,
|
||||
18028234882233861888,
|
||||
@ -1655,18 +1655,18 @@ mod tests {
|
||||
1305238720762,
|
||||
];
|
||||
|
||||
let mut a1: Vec<BigDigit> = vec![0; 1341];
|
||||
let mut a2: Vec<BigDigit> = vec![0; 1341];
|
||||
let mut a3: Vec<BigDigit> = vec![0; 1341];
|
||||
let mut a1 = &mut [0; 1341];
|
||||
let mut a2 = &mut [0; 1341];
|
||||
let mut a3 = &mut [0; 1341];
|
||||
|
||||
//print!("{} {}", b.len(), c.len());
|
||||
long(&mut a1, &b, &c);
|
||||
karatsuba(&mut a2, &b, &c);
|
||||
long(a1, &b, &c);
|
||||
karatsuba(a2, &b, &c);
|
||||
|
||||
assert_eq!(a1, a2);
|
||||
assert_eq!(&a1[..], &a2[..]);
|
||||
|
||||
// println!("res: {:?}", &a1);
|
||||
toom3(&mut a3, &b, &c);
|
||||
assert_eq!(a1, a3);
|
||||
toom3(a3, &b, &c);
|
||||
assert_eq!(&a1[..], &a3[..]);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::borrow::Cow;
|
||||
use alloc::borrow::Cow;
|
||||
|
||||
use num_traits::{One, Signed};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::borrow::Cow;
|
||||
use std::iter::repeat;
|
||||
use alloc::borrow::Cow;
|
||||
use core::iter::repeat;
|
||||
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::borrow::Cow;
|
||||
use alloc::borrow::Cow;
|
||||
|
||||
use num_traits::Zero;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::cmp;
|
||||
use std::cmp::Ordering::*;
|
||||
use core::cmp;
|
||||
use core::cmp::Ordering::*;
|
||||
|
||||
use num_traits::Zero;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -1,19 +1,21 @@
|
||||
#![allow(clippy::suspicious_arithmetic_impl)]
|
||||
#[allow(deprecated, unused_imports)]
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use std::default::Default;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter::{Product, Sum};
|
||||
use std::ops::{
|
||||
use alloc::borrow::Cow;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::string::String;
|
||||
use core::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use core::default::Default;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{Product, Sum};
|
||||
use core::ops::{
|
||||
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
|
||||
Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
|
||||
};
|
||||
use std::str::{self, FromStr};
|
||||
use std::{fmt, mem};
|
||||
use core::str::{self, FromStr};
|
||||
use core::{fmt, mem};
|
||||
#[cfg(has_i128)]
|
||||
use std::{i128, u128};
|
||||
use std::{i64, u64};
|
||||
use core::{i128, u128};
|
||||
use core::{i64, u64};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
|
@ -270,7 +270,8 @@ impl Distribution<BigInt> for RandomBits {
|
||||
/// to provide actually random primes.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
#[cfg_attr(feature = "std", doc = " ```")]
|
||||
#[cfg_attr(not(feature = "std"), doc = " ```ignore")]
|
||||
/// extern crate rand;
|
||||
/// extern crate num_bigint_dig as num_bigint;
|
||||
///
|
||||
|
@ -1,18 +1,22 @@
|
||||
#[allow(deprecated, unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use std::default::Default;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter::{Product, Sum};
|
||||
use std::ops::{
|
||||
use alloc::borrow::Cow;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::string::String;
|
||||
use core::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
use core::default::Default;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{Product, Sum};
|
||||
use core::ops::{
|
||||
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
|
||||
Mul, MulAssign, Neg, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
|
||||
};
|
||||
use std::str::{self, FromStr};
|
||||
use std::{cmp, fmt, mem};
|
||||
use std::{f32, f64};
|
||||
use std::{u64, u8};
|
||||
use core::str::{self, FromStr};
|
||||
use core::{cmp, fmt, mem};
|
||||
use core::{f32, f64};
|
||||
use core::{u64, u32, u8};
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use libm::F64Ext;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
@ -22,9 +26,11 @@ use zeroize::Zeroize;
|
||||
|
||||
use integer::{Integer, Roots};
|
||||
use num_traits::{
|
||||
CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Float, FromPrimitive, Num, One, Pow,
|
||||
CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow,
|
||||
ToPrimitive, Unsigned, Zero,
|
||||
};
|
||||
use num_traits::float::FloatCore;
|
||||
|
||||
use BigInt;
|
||||
|
||||
use big_digit::{self, BigDigit};
|
||||
@ -38,7 +44,7 @@ use self::monty::monty_modpow;
|
||||
use super::VEC_SIZE;
|
||||
use crate::algorithms::{__add2, __sub2rev, add2, sub2, sub2rev};
|
||||
use crate::algorithms::{biguint_shl, biguint_shr};
|
||||
use crate::algorithms::{cmp_slice, fls, ilog2};
|
||||
use crate::algorithms::{cmp_slice, fls, ilog2, idiv_ceil};
|
||||
use crate::algorithms::{div_rem, div_rem_digit, mac_with_carry, mul3, scalar_mul};
|
||||
use crate::algorithms::{extended_gcd, mod_inverse};
|
||||
use crate::traits::{ExtendedGcd, ModInverse};
|
||||
@ -194,9 +200,9 @@ fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint {
|
||||
debug_assert!(v.iter().all(|&c| (c as u32) < radix));
|
||||
|
||||
// Estimate how big the result will be, so we can pre-allocate it.
|
||||
let bits = (radix as f64).log2() * v.len() as f64;
|
||||
let big_digits = (bits / big_digit::BITS as f64).ceil();
|
||||
let mut data = SmallVec::with_capacity(big_digits as usize);
|
||||
let bits = ilog2(radix) * v.len();
|
||||
let big_digits = idiv_ceil(bits, big_digit::BITS);
|
||||
let mut data = SmallVec::with_capacity(big_digits);
|
||||
|
||||
let (base, power) = get_radix_base(radix);
|
||||
let radix = radix as BigDigit;
|
||||
@ -1713,14 +1719,14 @@ impl FromPrimitive for BigUint {
|
||||
}
|
||||
|
||||
// match the rounding of casting from float to int
|
||||
n = n.trunc();
|
||||
n = FloatCore::trunc(n);
|
||||
|
||||
// handle 0.x, -0.x
|
||||
if n.is_zero() {
|
||||
return Some(BigUint::zero());
|
||||
}
|
||||
|
||||
let (mantissa, exponent, sign) = Float::integer_decode(n);
|
||||
let (mantissa, exponent, sign) = FloatCore::integer_decode(n);
|
||||
|
||||
if sign == -1 {
|
||||
return None;
|
||||
@ -1925,7 +1931,8 @@ fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec<u8> {
|
||||
debug_assert!(!u.is_zero() && !radix.is_power_of_two());
|
||||
|
||||
// Estimate how big the result will be, so we can pre-allocate it.
|
||||
let radix_digits = ((u.bits() as f64) / (radix as f64).log2()).ceil();
|
||||
let bits = ilog2(radix);
|
||||
let radix_digits = idiv_ceil(u.bits(), bits);
|
||||
let mut res = Vec::with_capacity(radix_digits as usize);
|
||||
let mut digits = u.clone();
|
||||
|
||||
@ -2518,7 +2525,7 @@ impl serde::Serialize for BigUint {
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, n)| {
|
||||
if i == last && n < &(::std::u32::MAX as u64) {
|
||||
if i == last && n < &(u32::MAX as u64) {
|
||||
vec![*n as u32]
|
||||
} else {
|
||||
vec![*n as u32, (n >> 32) as u32]
|
||||
|
39
src/lib.rs
39
src/lib.rs
@ -50,7 +50,9 @@
|
||||
//!
|
||||
//! It's easy to generate large random numbers:
|
||||
//!
|
||||
//! ```rust
|
||||
#![cfg_attr(feature = "std", doc = " ```")]
|
||||
#![cfg_attr(not(feature = "std"), doc = " ```ignore")]
|
||||
//!
|
||||
//! # #[cfg(feature = "rand")]
|
||||
//! extern crate rand;
|
||||
//! extern crate num_bigint_dig as bigint;
|
||||
@ -78,12 +80,37 @@
|
||||
//! ## Compatibility
|
||||
//!
|
||||
//! The `num-bigint` crate is tested for rustc 1.15 and greater.
|
||||
//!
|
||||
//! ## `no_std` compatibility
|
||||
//!
|
||||
//! This crate is compatible with `no_std` environments from Rust 1.36. Note
|
||||
//! however that it still requires the `alloc` crate, so the user should ensure
|
||||
//! that they set a `global_allocator`.
|
||||
//!
|
||||
//! To use in no_std environment, add the crate as such in your `Cargo.toml`
|
||||
//! file:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! num-bigint = { version = "0.3", default-features=false }
|
||||
//! ```
|
||||
//!
|
||||
//! Every features should be compatible with no_std environment, so feel free to
|
||||
//! add features like `prime`, `i128`, etc...
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/num-bigint/0.2")]
|
||||
// We don't actually support `no_std` yet, and probably won't until `alloc` is stable. We're just
|
||||
// reserving this ability with the "std" feature now, and compilation will fail without.
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std as alloc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate core;
|
||||
|
||||
#[cfg(feature = "rand")]
|
||||
extern crate rand;
|
||||
#[cfg(all(test, feature = "rand"))]
|
||||
@ -113,8 +140,11 @@ extern crate num_traits;
|
||||
#[cfg(feature = "prime")]
|
||||
extern crate byteorder;
|
||||
|
||||
extern crate libm;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use core::fmt;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
@ -182,6 +212,7 @@ impl fmt::Display for ParseBigIntError {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for ParseBigIntError {
|
||||
fn description(&self) -> &str {
|
||||
self.__description()
|
||||
|
@ -1,7 +1,8 @@
|
||||
#![allow(clippy::many_single_char_names)]
|
||||
|
||||
use num_traits::{One, Zero};
|
||||
use std::ops::Shl;
|
||||
use core::ops::Shl;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit};
|
||||
use biguint::BigUint;
|
||||
@ -193,7 +194,7 @@ pub fn monty_modpow(x: &BigUint, y: &BigUint, m: &BigUint) -> BigUint {
|
||||
mr.n0inv,
|
||||
num_words,
|
||||
);
|
||||
::std::mem::swap(&mut z, &mut zz);
|
||||
core::mem::swap(&mut z, &mut zz);
|
||||
yi <<= n;
|
||||
j += n;
|
||||
}
|
||||
|
@ -388,7 +388,7 @@ pub fn probably_prime_lucas(n: &BigUint) -> bool {
|
||||
let mut t2 = &vk1 << 1;
|
||||
|
||||
if t1 < t2 {
|
||||
::std::mem::swap(&mut t1, &mut t2);
|
||||
core::mem::swap(&mut t1, &mut t2);
|
||||
}
|
||||
|
||||
t1 -= t2;
|
||||
@ -440,6 +440,7 @@ fn get_bit(x: &BigUint, i: usize) -> u8 {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use alloc::vec::Vec;
|
||||
// use RandBigInt;
|
||||
|
||||
use crate::biguint::ToBigUint;
|
||||
|
@ -20,7 +20,8 @@ use std::{i16, i32, i64, i8, isize};
|
||||
use std::{u16, u32, u64, u8, usize};
|
||||
|
||||
use num_integer::Integer;
|
||||
use num_traits::{Float, FromPrimitive, Num, One, Pow, Signed, ToPrimitive, Zero};
|
||||
use num_traits::{FromPrimitive, Num, One, Pow, Signed, ToPrimitive, Zero};
|
||||
use num_traits::float::FloatCore;
|
||||
|
||||
mod consts;
|
||||
use consts::*;
|
||||
@ -1119,9 +1120,22 @@ fn test_negative_shr() {
|
||||
#[test]
|
||||
#[cfg(feature = "rand")]
|
||||
fn test_random_shr() {
|
||||
use rand::distributions::Standard;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
fn thread_rng() -> impl rand::Rng {
|
||||
rand::thread_rng()
|
||||
}
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn thread_rng() -> impl rand::Rng {
|
||||
use rand::SeedableRng;
|
||||
// Chosen by fair dice roll
|
||||
rand::rngs::StdRng::seed_from_u64(4)
|
||||
}
|
||||
|
||||
use rand::Rng;
|
||||
let mut rng = rand::thread_rng();
|
||||
use rand::distributions::Standard;
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
||||
for p in rng.sample_iter::<i64, _>(&Standard).take(1000) {
|
||||
let big = BigInt::from(p);
|
||||
|
@ -20,10 +20,12 @@ use std::{i128, u128};
|
||||
use std::{u16, u32, u64, u8, usize};
|
||||
|
||||
use num_traits::{
|
||||
CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Float, FromPrimitive, Num, One, Pow,
|
||||
CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow,
|
||||
ToPrimitive, Zero,
|
||||
};
|
||||
|
||||
use num_traits::float::FloatCore;
|
||||
|
||||
mod consts;
|
||||
use consts::*;
|
||||
|
||||
|
@ -11,9 +11,18 @@ mod biguint {
|
||||
use num_bigint::{BigUint, RandBigInt, RandomBits};
|
||||
use num_traits::Zero;
|
||||
use rand::distributions::Uniform;
|
||||
use rand::thread_rng;
|
||||
use rand::{Rng, SeedableRng};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
fn thread_rng() -> impl Rng {
|
||||
rand::thread_rng()
|
||||
}
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn thread_rng() -> impl Rng {
|
||||
// Chosen by fair dice roll
|
||||
rand::StdRng::seed_from_u64(4)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rand() {
|
||||
let mut rng = thread_rng();
|
||||
@ -216,9 +225,18 @@ mod bigint {
|
||||
use num_bigint::{BigInt, RandBigInt, RandomBits};
|
||||
use num_traits::Zero;
|
||||
use rand::distributions::Uniform;
|
||||
use rand::thread_rng;
|
||||
use rand::{Rng, SeedableRng};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
fn thread_rng() -> impl Rng {
|
||||
rand::thread_rng()
|
||||
}
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn thread_rng() -> impl Rng {
|
||||
// Chosen by fair dice roll
|
||||
rand::rngs::StdRng::seed_from_u64(4)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rand() {
|
||||
let mut rng = thread_rng();
|
||||
|
@ -104,9 +104,21 @@ mod biguint {
|
||||
#[cfg(feature = "rand")]
|
||||
#[test]
|
||||
fn test_roots_rand() {
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
fn thread_rng() -> impl rand::Rng {
|
||||
rand::thread_rng()
|
||||
}
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn thread_rng() -> impl rand::Rng {
|
||||
use rand::SeedableRng;
|
||||
// Chosen by fair dice roll
|
||||
rand::rngs::StdRng::seed_from_u64(4)
|
||||
}
|
||||
|
||||
use num_bigint::RandBigInt;
|
||||
use rand::Rng;
|
||||
use rand::distributions::Uniform;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
let mut rng = thread_rng();
|
||||
let bit_range = Uniform::new(0, 2048);
|
||||
|
Loading…
x
Reference in New Issue
Block a user