Skip to content

Commit 48c666b

Browse files
committed
Updated to use num::{float,NumCast} and remove usage of sqrts
1 parent 498dace commit 48c666b

File tree

2 files changed

+48
-20
lines changed

2 files changed

+48
-20
lines changed

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ readme="README.md"
1717
documentation = "https://wackywendell.github.io/primes/"
1818
homepage = "https://github.com/wackywendell/primes/tree/master"
1919
repository = "https://github.com/wackywendell/primes/tree/master"
20+
21+
[dependencies]
22+
num = "^0.1.24"

src/lib.rs

+45-20
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ This also provides a few functions unconnected to `PrimeSet`, which will be fast
6060
case, but slower in the long term as they do not use any caching of primes.
6161
6262
*/
63-
#![feature(core,step_by,test)]
63+
#![feature(step_by,test)]
6464
#![doc(html_root_url = "https://wackywendell.github.io/primes/")]
6565

6666
#[warn(non_camel_case_types)]
@@ -70,25 +70,28 @@ case, but slower in the long term as they do not use any caching of primes.
7070
#[warn(missing_docs)]
7171

7272
extern crate test;
73+
extern crate num;
7374

7475
use std::ops::Index;
7576
use std::slice;
76-
use std::num::{Float,cast};
7777
use std::cmp::Ordering::{Equal,Less,Greater};
78+
use num::{Float,NumCast};
7879

7980
#[cfg(test)]
8081
use test::Bencher;
8182

82-
fn sqrt_floor<T: std::num::NumCast>(n : T) -> T {
83-
cast::<f64, T>(
84-
(cast::<T, f64>(n).unwrap()).sqrt().floor()
85-
).unwrap()
83+
/// Equivalent to floor(sqrt(n)), but takes an integer and returns an integer
84+
fn sqrt_floor<T: NumCast>(n : T) -> T {
85+
let n64 : f64 = NumCast::from(n).unwrap();
86+
let rt = n64.sqrt().floor();
87+
NumCast::from(rt).unwrap()
8688
}
8789

88-
fn sqrt_ceil<T: std::num::NumCast>(n : T) -> T {
89-
cast::<f64, T>(
90-
(cast::<T, f64>(n).unwrap()).sqrt().ceil()
91-
).unwrap()
90+
/// Equivalent to floor(sqrt(n)), but takes an integer and returns an integer
91+
fn sqrt_ceil<T: NumCast>(n : T) -> T {
92+
let n64 : f64 = NumCast::from(n).unwrap();
93+
let rt = n64.sqrt().ceil();
94+
NumCast::from(rt).unwrap()
9295
}
9396

9497
/** A prime generator, using the Sieve of Eratosthenes.
@@ -116,12 +119,11 @@ impl PrimeSet {
116119
/// Finds one more prime, and adds it to the list
117120
pub fn expand(&mut self) {
118121
let mut l : u64 = self.lst[self.lst.len()-1] + 2;
119-
let mut sql = sqrt_floor(l);
120122
let mut remainder = 0;
121123
loop {
122124
for &n in self.lst.iter() {
123125
remainder = l % n;
124-
if remainder == 0 || n > sql {
126+
if remainder == 0 || n*n > l {
125127
break;
126128
}
127129
};
@@ -132,7 +134,6 @@ impl PrimeSet {
132134
};
133135

134136
l += 2;
135-
sql = sqrt_floor(l);
136137
}
137138
}
138139

@@ -227,22 +228,22 @@ impl PrimeSet {
227228
pub fn prime_factors(&mut self, n: u64) -> Vec<u64> {
228229
if n == 1 {return Vec::new();}
229230
let mut curn = n;
230-
let mut m = sqrt_ceil(curn);
231231
let mut lst: Vec<u64> = Vec::new();
232232
for p in self.iter() {
233233
while curn % p == 0 {
234+
println!("Pushing {} ({} / {})", p, curn, n);
234235
lst.push(p);
235236
curn /= p;
236237
if curn == 1 {return lst;}
237-
m = sqrt_ceil(curn);
238238
}
239239

240-
if p > m {
241-
lst.push(p);
240+
if p*p > curn {
241+
println!("Final push {} ({} / {})", p, curn, n);
242+
lst.push(curn);
242243
return lst;
243244
}
244245
}
245-
panic!("This should be unreachable.");
246+
unreachable!("This should be unreachable.");
246247
}
247248
}
248249

@@ -272,9 +273,8 @@ impl<'a> Iterator for PrimeSetIter<'a> {
272273

273274
/// Find the first factor (other than 1) of a number
274275
fn firstfac(x: u64) -> u64 {
275-
let m = sqrt_ceil(x);
276276
if x % 2 == 0 { return 2; };
277-
for n in (3..m + 1).step_by(2) {
277+
for n in (3..).step_by(2).take_while(|m| m*m <= x) {
278278
if x % n == 0 { return n; };
279279
}
280280
return x;
@@ -315,6 +315,30 @@ pub fn is_prime(n : u64) -> bool {
315315
firstfac(n) == n
316316
}
317317

318+
#[test]
319+
fn test_sqrts(){
320+
assert_eq!(sqrt_ceil(0), 0);
321+
assert_eq!(sqrt_floor(0), 0);
322+
323+
assert_eq!(sqrt_ceil(1), 1);
324+
assert_eq!(sqrt_floor(1), 1);
325+
326+
let rts = [2u64,3,5,7,11,13,17,19,23, 8734, 809832, 7433154, 1 << 26 - 1];
327+
for &rt in rts.iter() {
328+
let sq = rt * rt;
329+
println!("rt: {}, n: {}", rt, sq);
330+
331+
assert_eq!(sqrt_ceil(sq), rt);
332+
assert_eq!(sqrt_floor(sq), rt);
333+
334+
assert_eq!(sqrt_ceil(sq-1), rt);
335+
assert_eq!(sqrt_floor(sq-1), rt-1);
336+
337+
assert_eq!(sqrt_ceil(sq+1), rt+1);
338+
assert_eq!(sqrt_floor(sq+1), rt);
339+
}
340+
}
341+
318342
#[test]
319343
fn test_iter(){
320344
let mut pset = PrimeSet::new();
@@ -394,6 +418,7 @@ fn test_factors(){
394418

395419
// Test unique factors
396420
for &(n, ref v) in ns.iter(){
421+
println!("{}: {:?}", n, v);
397422
assert_eq!(pset.prime_factors(n), *v);
398423
assert_eq!(factors(n), *v);
399424

0 commit comments

Comments
 (0)