1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-08-04 23:17:46 +00:00

factor: Split the CLI and I/O code off the factoring logic

This commit is contained in:
nicoo 2020-06-24 13:37:21 +02:00
parent bb01e67521
commit bd4d6fcac5
3 changed files with 73 additions and 61 deletions

View file

@ -11,9 +11,6 @@ keywords = ["coreutils", "uutils", "cross-platform", "cli", "utility"]
categories = ["command-line-utilities"] categories = ["command-line-utilities"]
edition = "2018" edition = "2018"
[lib]
path = "src/factor.rs"
[dependencies] [dependencies]
rand = "0.5" rand = "0.5"
uucore = { version="0.0.4", package="uucore", git="https://github.com/uutils/uucore.git", branch="canary" } uucore = { version="0.0.4", package="uucore", git="https://github.com/uutils/uucore.git", branch="canary" }
@ -22,3 +19,6 @@ uucore_procs = { version="0.0.4", package="uucore_procs", git="https://github.co
[[bin]] [[bin]]
name = "factor" name = "factor"
path = "src/main.rs" path = "src/main.rs"
[lib]
path = "src/cli.rs"

63
src/uu/factor/src/cli.rs Normal file
View file

@ -0,0 +1,63 @@
// * This file is part of the uutils coreutils package.
// *
// * (c) 2014 T. Jameson Little <t.jameson.little@gmail.com>
// * (c) 2020 nicoo <nicoo@debian.org>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.
#[macro_use]
extern crate uucore;
use std::error::Error;
use std::io::{self, stdin, stdout, BufRead, Write};
mod factor;
pub(crate) use factor::*;
mod miller_rabin;
mod numeric;
mod rho;
mod table;
static SYNTAX: &str = "[OPTION] [NUMBER]...";
static SUMMARY: &str = "Print the prime factors of the given number(s).
If none are specified, read from standard input.";
static LONG_HELP: &str = "";
fn print_factors_str(num_str: &str, w: &mut impl io::Write) -> Result<(), Box<dyn Error>> {
num_str
.parse::<u64>()
.map_err(|e| e.into())
.and_then(|x| writeln!(w, "{}:{}", x, factor(x)).map_err(|e| e.into()))
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let matches = app!(SYNTAX, SUMMARY, LONG_HELP).parse(args.collect_str());
let stdout = stdout();
let mut w = io::BufWriter::new(stdout.lock());
if matches.free.is_empty() {
let stdin = stdin();
for line in stdin.lock().lines() {
for number in line.unwrap().split_whitespace() {
if let Err(e) = print_factors_str(number, &mut w) {
show_warning!("{}: {}", number, e);
}
}
}
} else {
for number in &matches.free {
if let Err(e) = print_factors_str(number, &mut w) {
show_warning!("{}: {}", number, e);
}
}
}
if let Err(e) = w.flush() {
show_error!("{}", e);
}
0
}

View file

@ -1,6 +1,5 @@
// * This file is part of the uutils coreutils package. // * This file is part of the uutils coreutils package.
// * // *
// * (c) 2014 T. Jameson Little <t.jameson.little@gmail.com>
// * (c) 2020 nicoo <nicoo@debian.org> // * (c) 2020 nicoo <nicoo@debian.org>
// * // *
// * For the full copyright and license information, please view the LICENSE file // * For the full copyright and license information, please view the LICENSE file
@ -8,48 +7,35 @@
extern crate rand; extern crate rand;
#[macro_use]
extern crate uucore;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::error::Error;
use std::fmt; use std::fmt;
use std::io::{self, stdin, stdout, BufRead, Write};
use std::ops; use std::ops;
mod miller_rabin; use crate::{miller_rabin, rho, table};
mod numeric;
mod rho;
mod table;
static SYNTAX: &str = "[OPTION] [NUMBER]..."; pub struct Factors {
static SUMMARY: &str = "Print the prime factors of the given number(s).
If none are specified, read from standard input.";
static LONG_HELP: &str = "";
struct Factors {
f: BTreeMap<u64, u8>, f: BTreeMap<u64, u8>,
} }
impl Factors { impl Factors {
fn one() -> Factors { pub fn one() -> Factors {
Factors { f: BTreeMap::new() } Factors { f: BTreeMap::new() }
} }
fn prime(p: u64) -> Factors { pub fn prime(p: u64) -> Factors {
debug_assert!(miller_rabin::is_prime(p)); debug_assert!(miller_rabin::is_prime(p));
let mut f = Factors::one(); let mut f = Factors::one();
f.push(p); f.push(p);
f f
} }
fn add(&mut self, prime: u64, exp: u8) { pub fn add(&mut self, prime: u64, exp: u8) {
debug_assert!(exp > 0); debug_assert!(exp > 0);
let n = *self.f.get(&prime).unwrap_or(&0); let n = *self.f.get(&prime).unwrap_or(&0);
self.f.insert(prime, exp + n); self.f.insert(prime, exp + n);
} }
fn push(&mut self, prime: u64) { pub fn push(&mut self, prime: u64) {
self.add(prime, 1) self.add(prime, 1)
} }
@ -81,7 +67,7 @@ impl fmt::Display for Factors {
} }
} }
fn factor(mut n: u64) -> Factors { pub fn factor(mut n: u64) -> Factors {
let mut factors = Factors::one(); let mut factors = Factors::one();
if n < 2 { if n < 2 {
@ -109,43 +95,6 @@ fn factor(mut n: u64) -> Factors {
factors factors
} }
fn print_factors_str(num_str: &str, w: &mut impl io::Write) -> Result<(), Box<dyn Error>> {
num_str
.parse::<u64>()
.map_err(|e| e.into())
.and_then(|x| writeln!(w, "{}:{}", x, factor(x)).map_err(|e| e.into()))
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let matches = app!(SYNTAX, SUMMARY, LONG_HELP).parse(args.collect_str());
let stdout = stdout();
let mut w = io::BufWriter::new(stdout.lock());
if matches.free.is_empty() {
let stdin = stdin();
for line in stdin.lock().lines() {
for number in line.unwrap().split_whitespace() {
if let Err(e) = print_factors_str(number, &mut w) {
show_warning!("{}: {}", number, e);
}
}
}
} else {
for number in &matches.free {
if let Err(e) = print_factors_str(number, &mut w) {
show_warning!("{}: {}", number, e);
}
}
}
if let Err(e) = w.flush() {
show_error!("{}", e);
}
0
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::factor; use super::factor;