Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#![no_std] as an optional feature #59

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
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: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
matrix:
include:
- rust: 1.36.0 # MSRV
- rust: 1.60.0 # MSRV
- rust: stable
- rust: beta
- rust: nightly
Expand Down
15 changes: 9 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[package]

name = "primal"
version = "0.3.3"
version = "0.4.0"
authors = ["Huon Wilson <[email protected]>"]
edition = "2018"
edition = "2021"

homepage = "https://github.com/huonw/primal"
repository = "https://github.com/huonw/primal"
Expand All @@ -20,19 +20,22 @@ prime).
"""

[dependencies]
primal-check = { path = "primal-check", version = "0.3" }
primal-estimate = { path = "primal-estimate", version = "0.3" }
primal-sieve = { path = "primal-sieve", version = "0.3" }
primal-check = { path = "primal-check", version = "0.4" }
primal-estimate = { path = "primal-estimate", version = "0.4" }
primal-sieve = { path = "primal-sieve", version = "0.4" }

[dev-dependencies]
primal-slowsieve = { path = "primal-slowsieve", version = "0.3" }
primal-slowsieve = { path = "primal-slowsieve", version = "0.4" }
criterion = { version = "0.3.4", features = ["html_reports"] }

[[bench]]
name = "bench"
harness = false

[features]
libm = ["primal-sieve/libm"]
std = ["primal-sieve/std"]
default = ["std"]
unstable = ["primal-sieve/unstable"]

[workspace]
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@ count the exact number of primes below 10<sup>10</sup> (455052511)
on the author's laptop (i7-3517U).

[**Documentation**](http://docs.rs/primal/)

### no_std

This crate can be built for no_std environments by disabling the default features, and optionally enabling `libm` for functions like `perfect_primes`
```
[dependencies]
primal = { version = "0.4", default-features = false, features = ["libm"] }
```
8 changes: 4 additions & 4 deletions generators/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[package]
name = "generators"
version = "0.3.0"
version = "0.4.0"
authors = ["Huon Wilson <[email protected]>"]
edition = "2018"
edition = "2021"
publish = false

[dependencies]
primal-slowsieve = { path = "../primal-slowsieve", version = "0.3" }
primal-check = { path = "../primal-check", version = "0.3" }
primal-slowsieve = { path = "../primal-slowsieve", version = "0.4" }
primal-check = { path = "../primal-check", version = "0.4" }

[package.metadata.release]
release = false
28 changes: 18 additions & 10 deletions generators/src/bin/estimate-generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ ensure that primal-estimate is as tight as possible.
enum BoundType {
// Unconventional upper case to allow using the static's name
// directly to construct this.
HIGH, LOW
HIGH,
LOW,
}

#[derive(Clone, Debug)]
Expand All @@ -27,12 +28,11 @@ pub struct EstimateGroup {
estimators: &'static [Estimate],
}


macro_rules! estimates {
($(
$group: ident: {
$($from: expr, $source: expr =>
|$n_: pat, $lg: pat, $lglg: pat, $inv_lg: pat, $n_inv_lg: pat| { $e: expr },)*
| $n_: pat, $lg: pat, $lglg: pat, $inv_lg: pat, $n_inv_lg: pat_param | { $e: expr },)*
}
)*) => {
$(
Expand Down Expand Up @@ -154,7 +154,6 @@ mod nth_prime {
}
}


fn non_nan_cmp(x: f64, y: f64) -> std::cmp::Ordering {
x.partial_cmp(&y).unwrap()
}
Expand Down Expand Up @@ -204,8 +203,8 @@ fn analyse(group: &EstimateGroup) {
// yet up to estimators[i + 1].valid_from, so the prefix
// up to our current estimator will be valid at
// n_. Compute those estimators' estimates at this point.
let estimates =
estimators[..i + 1].iter()
let estimates = estimators[..i + 1]
.iter()
.map(|e| (e, (e.compute)(n_, lg, lglg, inv_lg, n_inv_lg)));

// The "best" of the estimates depends whether this is
Expand All @@ -218,20 +217,26 @@ fn analyse(group: &EstimateGroup) {
// Does the estimate overflow?
if limit == MAX && estimate > MAX {
upper_limit = Some(n_ / MULT);
break
break;
}

// If the best one at this point is different to the best
// at the previous points, we've switched into a new
// segment, so we need to record the old one.
if best.expression != current.expression {
subranges.push(Subrange { estimate: current, from: current_first });
subranges.push(Subrange {
estimate: current,
from: current_first,
});
current = best;
current_first = n_;
}
}
}
subranges.push(Subrange { estimate: current, from: current_first });
subranges.push(Subrange {
estimate: current,
from: current_first,
});

if let Some(limit) = upper_limit {
println!("const MAX_VALID_INPUT: u64 = {:.0};", limit);
Expand All @@ -243,7 +248,10 @@ fn analyse(group: &EstimateGroup) {
format!(" if n >= {:.0}_u64", sr.from)
};

println!("// {}\n_{} => {},", sr.estimate.source, guard, sr.estimate.expression)
println!(
"// {}\n_{} => {},",
sr.estimate.source, guard, sr.estimate.expression
)
}
}

Expand Down
5 changes: 1 addition & 4 deletions primal-bit/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "primal-bit"
version = "0.3.2"
version = "0.4.0"
authors = ["Huon Wilson <[email protected]>",
"The Rust Project Developers"]
edition = "2018"
Expand All @@ -15,8 +15,5 @@ description = """
Bit-vector specialised to the prime-number-related needs of `primal`.
"""

[dependencies]
hamming = "0.1"

[features]
unstable = []
2 changes: 2 additions & 0 deletions primal-bit/src/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
//! encapsulated in a module to reduce scope.
#![allow(unsafe_code)]

use alloc::{vec, vec::Vec};

use crate::BITS;

/// The bitvector type.
Expand Down
11 changes: 6 additions & 5 deletions primal-bit/src/iter.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::iter;
use std::mem;
use std::ops::Range;
use std::slice;
use std::vec;
use core::iter;
use core::mem;
use core::ops::Range;
use core::slice;

use alloc::vec;

use crate::BitVec;
use crate::BITS;
Expand Down
34 changes: 24 additions & 10 deletions primal-bit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@

//! A very simple bit-vector that serves the needs of `primal`.

#![no_std]
#![deny(unsafe_code)]

use std::fmt;
use std::hash;
use std::ops::Index;
extern crate alloc;

use core::fmt;
use core::hash;
use core::ops::Index;

mod inner;
mod iter;
mod util;

pub use crate::inner::BitVec;
pub use crate::iter::{Iter, IntoOnes, Ones};

pub use crate::iter::{IntoOnes, Iter, Ones};
use crate::util as hamming;
const BITS: usize = 8;

impl Index<usize> for BitVec {
Expand Down Expand Up @@ -55,7 +59,9 @@ impl BitVec {
let bytes = self.as_bytes();

hamming::weight(&bytes[..byte]) as usize
+ bytes.get(byte).map_or(0, |b| (b & mask).count_ones() as usize)
+ bytes
.get(byte)
.map_or(0, |b| (b & mask).count_ones() as usize)
}

/// Find the index of the `n`th (0-indexed) set bit.
Expand Down Expand Up @@ -118,24 +124,32 @@ impl BitVec {
/// ```
#[inline]
pub fn set_all(&mut self) {
for w in self.as_bytes_mut() { *w = !0; }
for w in self.as_bytes_mut() {
*w = !0;
}
self.fix_last_block();
}

/// Clears all bits in this vector.
#[inline]
pub fn clear(&mut self) {
for w in self.as_bytes_mut() { *w = 0; }
for w in self.as_bytes_mut() {
*w = 0;
}
}

/// Returns true if there are no bits in this vector
#[inline]
pub fn is_empty(&self) -> bool { self.len() == 0 }
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}

impl Default for BitVec {
#[inline]
fn default() -> BitVec { BitVec::new() }
fn default() -> BitVec {
BitVec::new()
}
}

impl fmt::Debug for BitVec {
Expand Down
47 changes: 47 additions & 0 deletions primal-bit/src/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//currrently required for slice align_to
#![allow(unsafe_code)]

fn naive(x: &[u8]) -> u64 {
x.iter().fold(0, |a, b| a + b.count_ones() as u64)
}
/// Computes the [Hamming
/// weight](https://en.wikipedia.org/wiki/Hamming_weight) of `x`, that
/// is, the population count, or number of 1.
///
/// The Original implementation is from https://crates.io/crates/hamming
/// copied here to avoid std dependency.
pub(crate) fn weight(x: &[u8]) -> u64 {
const M1: u64 = 0x5555555555555555;
const M2: u64 = 0x3333333333333333;
const M4: u64 = 0x0F0F0F0F0F0F0F0F;
const M8: u64 = 0x00FF00FF00FF00FF;

type T30 = [u64; 30];
let (head, thirty, tail) = unsafe { x.align_to::<T30>() };

let mut count = naive(head) + naive(tail);
for array in thirty {
let mut acc = 0;
for j_ in 0..10 {
let j = j_ * 3;
let mut count1 = array[j];
let mut count2 = array[j + 1];
let mut half1 = array[j + 2];
let mut half2 = half1;
half1 &= M1;
half2 = (half2 >> 1) & M1;
count1 -= (count1 >> 1) & M1;
count2 -= (count2 >> 1) & M1;
count1 += half1;
count2 += half2;
count1 = (count1 & M2) + ((count1 >> 2) & M2);
count1 += (count2 & M2) + ((count2 >> 2) & M2);
acc += (count1 & M4) + ((count1 >> 4) & M4);
}
acc = (acc & M8) + ((acc >> 8) & M8);
acc = acc + (acc >> 16);
acc = acc + (acc >> 32);
count += acc & 0xFFFF;
}
count
}
12 changes: 8 additions & 4 deletions primal-check/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "primal-check"
version = "0.3.4"
version = "0.4.0"
authors = ["Huon Wilson <[email protected]>"]
edition = "2018"
edition = "2021"

homepage = "https://github.com/huonw/primal"
repository = "https://github.com/huonw/primal"
Expand All @@ -15,10 +15,14 @@ Fast standalone primality testing.
"""

[dependencies]
num-integer = "0.1"
libm = { version = "0.2.8", optional = true }
num-integer = { version = "0.1", default_features = false }

[dev-dependencies]
primal = { path = "..", version = "0.3" }
primal = { path = "..", version = "0.4" }

[features]
std = []
libm = ["dep:libm"]
default = ["std"]
unstable = []
2 changes: 1 addition & 1 deletion primal-check/src/is_prime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub fn miller_rabin(n: u64) -> bool {
(3_474_749_660_382, &[2, 3, 5, 7, 11, 13]),
(341_550_071_728_320, &[2, 3, 5, 7, 11, 13, 17]),
(3_825_123_056_546_413_050, &[2, 3, 5, 7, 11, 13, 17, 19, 23]),
(std::u64::MAX, &[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]),
(core::u64::MAX, &[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]),
];

if n % 2 == 0 { return n == 2 }
Expand Down
4 changes: 3 additions & 1 deletion primal-check/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
//!
//! This crate is designed to be used via `primal`.

#![cfg_attr(not(feature = "std"), no_std)]

pub use crate::is_prime::miller_rabin;
pub use crate::perfect_power::{as_perfect_power, as_prime_power};

mod perfect_power;
mod is_prime;
mod perfect_power;
Loading