A Rust crate with both `main.rs` and `lib.rs` performing primality checking
up vote
3
down vote
favorite
Introduction
I decided to get my feet wet in Rust by going ahead an implementing a full crate with the tests, documentation, and all other accompanying stuff. This is a toy implementation of a library containing a function that checks whether a given u64
is prime or not.
What I've also done is implement a main.rs
in addition to the lib.rs
, that produces an executable when the cargo run
or cargo build
command is issued. So far the toolchain hasn't complained yet. It seems to be working fine, but I seek adivce on the practicality of it.
The organization
Here is the full structure (excluding the target
folder):
prime
+- src
| +- lib.rs
| +- main.rs
| +- prime.rs
+- tests
| +- extern_test.rs
+- Cargo.lock
+- Cargo.toml
The files
lib.rs
pub mod prime;
main.rs
pub mod prime;
use std::env;
use std::io::stdin;
fn take_input() {
println!("Prime cheker utility.n=====================n");
loop {
process_single_line();
if user_wants_to_exit() {
break;
}
}
}
fn process_single_line() {
let mut num_str: String = String::new();
println!("Enter the number to check : ");
stdin().read_line(&mut num_str).unwrap();
process_string(num_str.trim());
}
fn user_wants_to_exit() -> bool {
let mut usr_str = String::new();
println!("Do you want to exit? (y/n) : ");
stdin()
.read_line(&mut usr_str)
.expect("Error while reading input.");
let trimmed = usr_str.trim();
trimmed == "y" || trimmed == "Y" || trimmed.to_lowercase() == "yes"
}
fn process_string(num_str: &str) {
let num = num_str.parse::<u64>().expect(INVALID_NUMBER);
println!(
"The integer {} is{} a prime.",
num,
match prime::is_prime(num) {
true => "",
false => " not",
}
);
}
const HELP_TEXT: &str = "USAGE:nn1. primen2. prime [unsigned integer]n";
const INVALID_NUMBER: &str = "Please enter a valid unsigned integer.";
fn main() {
let args: Vec<String> = env::args().collect();
match args.len() {
1 => take_input(),
2 => process_string(args[1].trim()),
_ => {
println!("{}", HELP_TEXT);
}
}
}
prime.rs
/// This function takes a 64-bit unsigned integer and checks if it is a prime.
///
/// If the number is prime, `true` is returned, and vice-versa.
///
/// #Example
///
/// ```rust
/// use prime_util::*;
///
/// let result = prime::is_prime(31);
/// assert_eq!(result, true);
/// ```
pub fn is_prime(num: u64) -> bool {
if num < 2 {
return false;
}
if num == 2 || num == 3 {
return true;
}
// Even numbers and multiples of 3 are eliminated
if num % 2 == 0 || num % 3 == 0 {
return false;
}
// Optimized divisor approach
// First we calculate the maximum limit of iteration
let limit = (num as f64).sqrt() as u64;
// We start the iteration from 5 (2 and 3 have been already tested)
let mut divisor = 5;
// The step alternates between 2 and 4 to keep the divisor of the form
// 6k +/- 1, where k is an integer
let mut step = 2;
while divisor <= limit {
if num % divisor == 0 {
return false;
}
divisor += step;
step = if step == 2 { 4 } else { 2 }
}
true
}
extern_test.rs
extern crate prime_util;
#[cfg(test)]
mod integration_test {
use prime_util::prime;
#[test]
fn small_number_checks() {
assert_eq!(prime::is_prime(11), true);
assert_eq!(prime::is_prime(12), false);
assert_eq!(prime::is_prime(13), true);
}
#[test]
fn large_number_checks() {
assert_eq!(prime::is_prime(179434027), true);
assert_eq!(prime::is_prime(179434029), false);
assert_eq!(prime::is_prime(179434031), false);
assert_eq!(prime::is_prime(179434033), true);
}
#[test]
fn first_10_numbers_tested() {
assert_eq!(prime::is_prime(0), false);
assert_eq!(prime::is_prime(1), false);
assert_eq!(prime::is_prime(2), true);
assert_eq!(prime::is_prime(3), true);
assert_eq!(prime::is_prime(4), false);
assert_eq!(prime::is_prime(5), true);
assert_eq!(prime::is_prime(6), false);
assert_eq!(prime::is_prime(7), true);
assert_eq!(prime::is_prime(8), false);
assert_eq!(prime::is_prime(9), false);
assert_eq!(prime::is_prime(10), false);
}
}
Others
Cargo.toml is the default one. Nothing has been changed.
Topics of interest
I would like to point out some specific areas that I would like to hear advice on (although I always welcome comments on any aspect of the project):
- The fact that I have both
main.rs
andlib.rs
. Cargo couldn't care less apparently. Because it executes all tests (even the documentation test) and also executes as a command-line program whencargo run
is called (both with and without arguments). - The general quality of the code. I feel it can always be improved and made more Rusty.
- The organization of the files and the containing code, and the documentation.
- The external tests that I've included. Any additions/modifications necessary?
I reiterate my invitation for general criticism as well.
beginner primes rust
add a comment |
up vote
3
down vote
favorite
Introduction
I decided to get my feet wet in Rust by going ahead an implementing a full crate with the tests, documentation, and all other accompanying stuff. This is a toy implementation of a library containing a function that checks whether a given u64
is prime or not.
What I've also done is implement a main.rs
in addition to the lib.rs
, that produces an executable when the cargo run
or cargo build
command is issued. So far the toolchain hasn't complained yet. It seems to be working fine, but I seek adivce on the practicality of it.
The organization
Here is the full structure (excluding the target
folder):
prime
+- src
| +- lib.rs
| +- main.rs
| +- prime.rs
+- tests
| +- extern_test.rs
+- Cargo.lock
+- Cargo.toml
The files
lib.rs
pub mod prime;
main.rs
pub mod prime;
use std::env;
use std::io::stdin;
fn take_input() {
println!("Prime cheker utility.n=====================n");
loop {
process_single_line();
if user_wants_to_exit() {
break;
}
}
}
fn process_single_line() {
let mut num_str: String = String::new();
println!("Enter the number to check : ");
stdin().read_line(&mut num_str).unwrap();
process_string(num_str.trim());
}
fn user_wants_to_exit() -> bool {
let mut usr_str = String::new();
println!("Do you want to exit? (y/n) : ");
stdin()
.read_line(&mut usr_str)
.expect("Error while reading input.");
let trimmed = usr_str.trim();
trimmed == "y" || trimmed == "Y" || trimmed.to_lowercase() == "yes"
}
fn process_string(num_str: &str) {
let num = num_str.parse::<u64>().expect(INVALID_NUMBER);
println!(
"The integer {} is{} a prime.",
num,
match prime::is_prime(num) {
true => "",
false => " not",
}
);
}
const HELP_TEXT: &str = "USAGE:nn1. primen2. prime [unsigned integer]n";
const INVALID_NUMBER: &str = "Please enter a valid unsigned integer.";
fn main() {
let args: Vec<String> = env::args().collect();
match args.len() {
1 => take_input(),
2 => process_string(args[1].trim()),
_ => {
println!("{}", HELP_TEXT);
}
}
}
prime.rs
/// This function takes a 64-bit unsigned integer and checks if it is a prime.
///
/// If the number is prime, `true` is returned, and vice-versa.
///
/// #Example
///
/// ```rust
/// use prime_util::*;
///
/// let result = prime::is_prime(31);
/// assert_eq!(result, true);
/// ```
pub fn is_prime(num: u64) -> bool {
if num < 2 {
return false;
}
if num == 2 || num == 3 {
return true;
}
// Even numbers and multiples of 3 are eliminated
if num % 2 == 0 || num % 3 == 0 {
return false;
}
// Optimized divisor approach
// First we calculate the maximum limit of iteration
let limit = (num as f64).sqrt() as u64;
// We start the iteration from 5 (2 and 3 have been already tested)
let mut divisor = 5;
// The step alternates between 2 and 4 to keep the divisor of the form
// 6k +/- 1, where k is an integer
let mut step = 2;
while divisor <= limit {
if num % divisor == 0 {
return false;
}
divisor += step;
step = if step == 2 { 4 } else { 2 }
}
true
}
extern_test.rs
extern crate prime_util;
#[cfg(test)]
mod integration_test {
use prime_util::prime;
#[test]
fn small_number_checks() {
assert_eq!(prime::is_prime(11), true);
assert_eq!(prime::is_prime(12), false);
assert_eq!(prime::is_prime(13), true);
}
#[test]
fn large_number_checks() {
assert_eq!(prime::is_prime(179434027), true);
assert_eq!(prime::is_prime(179434029), false);
assert_eq!(prime::is_prime(179434031), false);
assert_eq!(prime::is_prime(179434033), true);
}
#[test]
fn first_10_numbers_tested() {
assert_eq!(prime::is_prime(0), false);
assert_eq!(prime::is_prime(1), false);
assert_eq!(prime::is_prime(2), true);
assert_eq!(prime::is_prime(3), true);
assert_eq!(prime::is_prime(4), false);
assert_eq!(prime::is_prime(5), true);
assert_eq!(prime::is_prime(6), false);
assert_eq!(prime::is_prime(7), true);
assert_eq!(prime::is_prime(8), false);
assert_eq!(prime::is_prime(9), false);
assert_eq!(prime::is_prime(10), false);
}
}
Others
Cargo.toml is the default one. Nothing has been changed.
Topics of interest
I would like to point out some specific areas that I would like to hear advice on (although I always welcome comments on any aspect of the project):
- The fact that I have both
main.rs
andlib.rs
. Cargo couldn't care less apparently. Because it executes all tests (even the documentation test) and also executes as a command-line program whencargo run
is called (both with and without arguments). - The general quality of the code. I feel it can always be improved and made more Rusty.
- The organization of the files and the containing code, and the documentation.
- The external tests that I've included. Any additions/modifications necessary?
I reiterate my invitation for general criticism as well.
beginner primes rust
add a comment |
up vote
3
down vote
favorite
up vote
3
down vote
favorite
Introduction
I decided to get my feet wet in Rust by going ahead an implementing a full crate with the tests, documentation, and all other accompanying stuff. This is a toy implementation of a library containing a function that checks whether a given u64
is prime or not.
What I've also done is implement a main.rs
in addition to the lib.rs
, that produces an executable when the cargo run
or cargo build
command is issued. So far the toolchain hasn't complained yet. It seems to be working fine, but I seek adivce on the practicality of it.
The organization
Here is the full structure (excluding the target
folder):
prime
+- src
| +- lib.rs
| +- main.rs
| +- prime.rs
+- tests
| +- extern_test.rs
+- Cargo.lock
+- Cargo.toml
The files
lib.rs
pub mod prime;
main.rs
pub mod prime;
use std::env;
use std::io::stdin;
fn take_input() {
println!("Prime cheker utility.n=====================n");
loop {
process_single_line();
if user_wants_to_exit() {
break;
}
}
}
fn process_single_line() {
let mut num_str: String = String::new();
println!("Enter the number to check : ");
stdin().read_line(&mut num_str).unwrap();
process_string(num_str.trim());
}
fn user_wants_to_exit() -> bool {
let mut usr_str = String::new();
println!("Do you want to exit? (y/n) : ");
stdin()
.read_line(&mut usr_str)
.expect("Error while reading input.");
let trimmed = usr_str.trim();
trimmed == "y" || trimmed == "Y" || trimmed.to_lowercase() == "yes"
}
fn process_string(num_str: &str) {
let num = num_str.parse::<u64>().expect(INVALID_NUMBER);
println!(
"The integer {} is{} a prime.",
num,
match prime::is_prime(num) {
true => "",
false => " not",
}
);
}
const HELP_TEXT: &str = "USAGE:nn1. primen2. prime [unsigned integer]n";
const INVALID_NUMBER: &str = "Please enter a valid unsigned integer.";
fn main() {
let args: Vec<String> = env::args().collect();
match args.len() {
1 => take_input(),
2 => process_string(args[1].trim()),
_ => {
println!("{}", HELP_TEXT);
}
}
}
prime.rs
/// This function takes a 64-bit unsigned integer and checks if it is a prime.
///
/// If the number is prime, `true` is returned, and vice-versa.
///
/// #Example
///
/// ```rust
/// use prime_util::*;
///
/// let result = prime::is_prime(31);
/// assert_eq!(result, true);
/// ```
pub fn is_prime(num: u64) -> bool {
if num < 2 {
return false;
}
if num == 2 || num == 3 {
return true;
}
// Even numbers and multiples of 3 are eliminated
if num % 2 == 0 || num % 3 == 0 {
return false;
}
// Optimized divisor approach
// First we calculate the maximum limit of iteration
let limit = (num as f64).sqrt() as u64;
// We start the iteration from 5 (2 and 3 have been already tested)
let mut divisor = 5;
// The step alternates between 2 and 4 to keep the divisor of the form
// 6k +/- 1, where k is an integer
let mut step = 2;
while divisor <= limit {
if num % divisor == 0 {
return false;
}
divisor += step;
step = if step == 2 { 4 } else { 2 }
}
true
}
extern_test.rs
extern crate prime_util;
#[cfg(test)]
mod integration_test {
use prime_util::prime;
#[test]
fn small_number_checks() {
assert_eq!(prime::is_prime(11), true);
assert_eq!(prime::is_prime(12), false);
assert_eq!(prime::is_prime(13), true);
}
#[test]
fn large_number_checks() {
assert_eq!(prime::is_prime(179434027), true);
assert_eq!(prime::is_prime(179434029), false);
assert_eq!(prime::is_prime(179434031), false);
assert_eq!(prime::is_prime(179434033), true);
}
#[test]
fn first_10_numbers_tested() {
assert_eq!(prime::is_prime(0), false);
assert_eq!(prime::is_prime(1), false);
assert_eq!(prime::is_prime(2), true);
assert_eq!(prime::is_prime(3), true);
assert_eq!(prime::is_prime(4), false);
assert_eq!(prime::is_prime(5), true);
assert_eq!(prime::is_prime(6), false);
assert_eq!(prime::is_prime(7), true);
assert_eq!(prime::is_prime(8), false);
assert_eq!(prime::is_prime(9), false);
assert_eq!(prime::is_prime(10), false);
}
}
Others
Cargo.toml is the default one. Nothing has been changed.
Topics of interest
I would like to point out some specific areas that I would like to hear advice on (although I always welcome comments on any aspect of the project):
- The fact that I have both
main.rs
andlib.rs
. Cargo couldn't care less apparently. Because it executes all tests (even the documentation test) and also executes as a command-line program whencargo run
is called (both with and without arguments). - The general quality of the code. I feel it can always be improved and made more Rusty.
- The organization of the files and the containing code, and the documentation.
- The external tests that I've included. Any additions/modifications necessary?
I reiterate my invitation for general criticism as well.
beginner primes rust
Introduction
I decided to get my feet wet in Rust by going ahead an implementing a full crate with the tests, documentation, and all other accompanying stuff. This is a toy implementation of a library containing a function that checks whether a given u64
is prime or not.
What I've also done is implement a main.rs
in addition to the lib.rs
, that produces an executable when the cargo run
or cargo build
command is issued. So far the toolchain hasn't complained yet. It seems to be working fine, but I seek adivce on the practicality of it.
The organization
Here is the full structure (excluding the target
folder):
prime
+- src
| +- lib.rs
| +- main.rs
| +- prime.rs
+- tests
| +- extern_test.rs
+- Cargo.lock
+- Cargo.toml
The files
lib.rs
pub mod prime;
main.rs
pub mod prime;
use std::env;
use std::io::stdin;
fn take_input() {
println!("Prime cheker utility.n=====================n");
loop {
process_single_line();
if user_wants_to_exit() {
break;
}
}
}
fn process_single_line() {
let mut num_str: String = String::new();
println!("Enter the number to check : ");
stdin().read_line(&mut num_str).unwrap();
process_string(num_str.trim());
}
fn user_wants_to_exit() -> bool {
let mut usr_str = String::new();
println!("Do you want to exit? (y/n) : ");
stdin()
.read_line(&mut usr_str)
.expect("Error while reading input.");
let trimmed = usr_str.trim();
trimmed == "y" || trimmed == "Y" || trimmed.to_lowercase() == "yes"
}
fn process_string(num_str: &str) {
let num = num_str.parse::<u64>().expect(INVALID_NUMBER);
println!(
"The integer {} is{} a prime.",
num,
match prime::is_prime(num) {
true => "",
false => " not",
}
);
}
const HELP_TEXT: &str = "USAGE:nn1. primen2. prime [unsigned integer]n";
const INVALID_NUMBER: &str = "Please enter a valid unsigned integer.";
fn main() {
let args: Vec<String> = env::args().collect();
match args.len() {
1 => take_input(),
2 => process_string(args[1].trim()),
_ => {
println!("{}", HELP_TEXT);
}
}
}
prime.rs
/// This function takes a 64-bit unsigned integer and checks if it is a prime.
///
/// If the number is prime, `true` is returned, and vice-versa.
///
/// #Example
///
/// ```rust
/// use prime_util::*;
///
/// let result = prime::is_prime(31);
/// assert_eq!(result, true);
/// ```
pub fn is_prime(num: u64) -> bool {
if num < 2 {
return false;
}
if num == 2 || num == 3 {
return true;
}
// Even numbers and multiples of 3 are eliminated
if num % 2 == 0 || num % 3 == 0 {
return false;
}
// Optimized divisor approach
// First we calculate the maximum limit of iteration
let limit = (num as f64).sqrt() as u64;
// We start the iteration from 5 (2 and 3 have been already tested)
let mut divisor = 5;
// The step alternates between 2 and 4 to keep the divisor of the form
// 6k +/- 1, where k is an integer
let mut step = 2;
while divisor <= limit {
if num % divisor == 0 {
return false;
}
divisor += step;
step = if step == 2 { 4 } else { 2 }
}
true
}
extern_test.rs
extern crate prime_util;
#[cfg(test)]
mod integration_test {
use prime_util::prime;
#[test]
fn small_number_checks() {
assert_eq!(prime::is_prime(11), true);
assert_eq!(prime::is_prime(12), false);
assert_eq!(prime::is_prime(13), true);
}
#[test]
fn large_number_checks() {
assert_eq!(prime::is_prime(179434027), true);
assert_eq!(prime::is_prime(179434029), false);
assert_eq!(prime::is_prime(179434031), false);
assert_eq!(prime::is_prime(179434033), true);
}
#[test]
fn first_10_numbers_tested() {
assert_eq!(prime::is_prime(0), false);
assert_eq!(prime::is_prime(1), false);
assert_eq!(prime::is_prime(2), true);
assert_eq!(prime::is_prime(3), true);
assert_eq!(prime::is_prime(4), false);
assert_eq!(prime::is_prime(5), true);
assert_eq!(prime::is_prime(6), false);
assert_eq!(prime::is_prime(7), true);
assert_eq!(prime::is_prime(8), false);
assert_eq!(prime::is_prime(9), false);
assert_eq!(prime::is_prime(10), false);
}
}
Others
Cargo.toml is the default one. Nothing has been changed.
Topics of interest
I would like to point out some specific areas that I would like to hear advice on (although I always welcome comments on any aspect of the project):
- The fact that I have both
main.rs
andlib.rs
. Cargo couldn't care less apparently. Because it executes all tests (even the documentation test) and also executes as a command-line program whencargo run
is called (both with and without arguments). - The general quality of the code. I feel it can always be improved and made more Rusty.
- The organization of the files and the containing code, and the documentation.
- The external tests that I've included. Any additions/modifications necessary?
I reiterate my invitation for general criticism as well.
beginner primes rust
beginner primes rust
asked 2 days ago
Astrobleme
1,5561339
1,5561339
add a comment |
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208488%2fa-rust-crate-with-both-main-rs-and-lib-rs-performing-primality-checking%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown