Compare commits

...

4 Commits

Author SHA1 Message Date
1b6ad7c797 Implement test and gen for already-imported values. 2025-12-04 08:58:57 +01:00
f88c221a67 Rename priems to primes_list. 2025-12-04 08:56:32 +01:00
fed8fe9ba8 Remove TODO list.
I'm rewriting most of it anyways.
2025-12-03 21:41:38 +01:00
ceb7e5974e Restructure code.
I'm gonna rewrite this whole thing.
2025-12-03 21:39:22 +01:00
6 changed files with 73 additions and 302 deletions

115
Cargo.lock generated
View File

@@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "ansi_term"
@@ -22,24 +22,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.33.3"
@@ -55,56 +43,6 @@ dependencies = [
"vec_map",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9"
dependencies = [
"cfg-if",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6"
dependencies = [
"cfg-if",
"lazy_static",
]
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "heck"
version = "0.3.2"
@@ -127,7 +65,6 @@ dependencies = [
name = "indivisible"
version = "2.0.0"
dependencies = [
"rayon",
"structopt",
]
@@ -143,25 +80,6 @@ version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@@ -204,37 +122,6 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"lazy_static",
"num_cpus",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "strsim"
version = "0.8.0"

View File

@@ -6,10 +6,9 @@ description = "A prime number generator and tester"
edition = "2018"
readme = "README"
license = "GPL-3.0"
keywords = ["primes", "math"]
keywords = [ "primes", "math" ]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
structopt = "0.3.13"
rayon = "1.5"

6
TODO
View File

@@ -1,6 +0,0 @@
============
*** TODO ***
============
Technical:
- Use bigints (maybe GMP or another similar library)
- Parallelize computations

View File

@@ -16,142 +16,65 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use structopt::StructOpt;
use std::path::PathBuf;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::collections::VecDeque;
use std::path::PathBuf;
use std::process;
use std::rc::Rc;
use structopt::StructOpt;
mod test;
mod worker;
#[derive(StructOpt)]
#[structopt(about = "A prime number generator and tester.")]
struct Opt
{
struct Opt {
#[structopt(short, long, help = "Print all found primes")]
verbose:bool,
#[structopt(short, long, name = "FILE", help = "Import prime numbers from FILE")]
import:Option<PathBuf>,
#[structopt(short, long, help = "Test if n is prime instead of generation")]
#[structopt(short, long, help = "Test if num is prime instead of generation")]
test:bool,
#[structopt(help = "Ordinal of the prime to generate")]
n:u64,
#[structopt(help = "Ordinal of the prime to generate or number to test for primality")]
num:u64,
#[structopt(short, long, name = "n", help = "Number of threads to spawn")]
jobs:Option<u64>,
}
fn main()
{
fn main() {
let opts = Opt::from_args();
// get the first `n` primes
let n = opts.n;
let mut primes:VecDeque<u64> = VecDeque::new();
let mut primes_list = Rc::new(RefCell::new(VecDeque::<u64>::new()));
if opts.import.is_some()
{
if opts.import.is_some() {
let in_file = File::open(opts.import.unwrap()).unwrap();
let reader = BufReader::new(in_file);
reader.lines().into_iter().for_each(|x| {
primes.push_back(x.unwrap().parse().unwrap());
});
}
if opts.test
{
let mut res:bool;
// if no primes were imported, test from beginning (2)
if primes.len() == 0
{
res = test::is_prime(n);
}
// `n` should be in `primes` if the last prime is larger than `n`
else if primes.back().unwrap() >= &(n)
{
res = primes.contains(&(n));
}
// we can memory test `n` if the last prime is >= sqrt(n)
else if primes.back().unwrap() >= &((n as f64).sqrt() as u64)
{
res = test::is_prime_mem(n, &primes)
}
/*
* if we have less primes than sqrt(n) then we can test all those
* prior to the last prime in the list, and then begin testing odd
* numbers.
*/
else
{
res = test::is_prime_mem(n, &primes);
if res
{
res = test::is_prime_f(n, primes.back().unwrap() + 2);
}
}
if res
{
if opts.verbose
{
println!("true");
}
std::process::exit(0);
}
else
{
if opts.verbose
{
println!("false");
}
std::process::exit(1);
for p in reader.lines().into_iter() {
primes_list.borrow_mut().push_back(p.unwrap().parse().unwrap());
}
}
else
{
// if `primes` already contains the nth prime, print it
if primes.len() >= n as usize
{
println!("{}", primes.get((n as usize) - 1).unwrap());
}
else
{
let mut candidate:u64;
if primes.len() == 0
{
// assume 2 as a prime
primes.push_back(2);
if opts.verbose
{
println!("{}", 2);
}
candidate = 3;
}
else if primes.len() == 1
{
candidate = 3;
}
else
{
candidate = *primes.back().unwrap() + 2;
}
let jobs = match opts.jobs {
Some(n) => n,
None => 1, // TODO: use number of CPUs
};
while primes.len() < n as usize
{
if test::is_prime_mem(candidate, &primes)
{
primes.push_back(candidate);
if opts.verbose
{
println!("{}", candidate);
}
}
if opts.num == 0 {
eprintln!("Invalid value for num: {}", opts.num);
process::exit(1);
}
candidate += 2;
}
if !opts.verbose
{
println!("{}", primes.get((n as usize) - 1).unwrap());
if opts.test && *primes_list.borrow().back().unwrap_or(&0) >= opts.num {
for i in primes_list.borrow().iter() {
if *i == opts.num {
process::exit(0)
}
}
process::exit(1)
} else if !opts.test && primes_list.borrow().len() >= opts.num as usize {
let res = *primes_list.borrow().get(opts.num as usize).unwrap();
println!("{}", res);
} else {
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright (C) 2021 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use std::collections::VecDeque;
use rayon::prelude::*;
pub fn is_prime_f(n:u64, b:u64) -> bool
{
assert_ne!(b, 0);
assert_ne!(b, 1);
if n == 1
{
return false;
}
let mut start = b;
if start == 2
{
if n % 2 == 0
{
return false;
}
else
{
start += 1;
}
}
// skip even numbers
else if start % 2 == 0
{
start += 1;
}
let limit = (n as f64).sqrt() as u64 + 1;
let composite = (start..limit).step_by(2).collect::<Vec<u64>>()
.par_iter().any(|x| n % x == 0);
return !composite;
}
pub fn is_prime(n:u64) -> bool
{
return is_prime_f(n, 2);
}
pub fn is_prime_mem(n:u64, primes:&VecDeque<u64>) -> bool
{
let limit = (n as f64).sqrt() as u64;
let pp = primes.partition_point(|x| *x < limit);
//let composite = primes.par_iter().take(pp+1).any(|x| n % *x == 0);
let composite = primes.iter().take(pp+1).any(|x| n % *x == 0);
return !composite;
}

36
src/worker.rs Normal file
View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2025 Nicolás Ortega Froysa <nicolas@ortegas.org>
* Author: Nicolás Ortega Froysa <nicolas@ortegas.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;
pub struct Worker {
primes_list:Rc<RefCell<VecDeque<u64>>>,
}
impl Worker {
pub fn new(primes_list:Rc<RefCell<VecDeque<u64>>>) -> Worker {
Worker {
primes_list,
}
}
pub fn run(&mut self) {
}
}