command line, read numbers from file + python script generate test values
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use rug::Integer;
|
||||
use crate::matrix::Matrix;
|
||||
use crate::utils::abs;
|
||||
use lll_rs::l2::bigl2;
|
||||
use rug::Integer;
|
||||
|
||||
pub fn agcd(ciphertexts: Vec<Integer>, noise_bits: usize) -> Integer {
|
||||
// 1. Build lattice matrix basis
|
||||
|
52
src/file.rs
Normal file
52
src/file.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use rug::Integer;
|
||||
use std::io;
|
||||
|
||||
pub struct AgcdInput {
|
||||
pub noise_bits: usize,
|
||||
pub numbers: Vec<Integer>,
|
||||
}
|
||||
|
||||
// Parse the input file, return noise_bits and numbers.
|
||||
pub fn parse_file(path: &Path) -> io::Result<AgcdInput> {
|
||||
let content = fs::read_to_string(path)?;
|
||||
let mut lines = content.lines();
|
||||
|
||||
// Parse noise_bits from first non comment line
|
||||
let noise_bits = loop {
|
||||
match lines.next() {
|
||||
Some(first_line) => {
|
||||
let trimmed = first_line.trim();
|
||||
if trimmed.starts_with("//") {
|
||||
continue; // Skip comment lines
|
||||
}
|
||||
break trimmed.parse::<usize>()
|
||||
.map_err(|e| io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!("First non-comment line must be noise_bits (usize): {}", e)
|
||||
))?;
|
||||
},
|
||||
None => return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"Input file is empty or contains only comments"
|
||||
)),
|
||||
}
|
||||
};
|
||||
|
||||
// Parse numbers from remaining lines
|
||||
let numbers: Vec<Integer> = lines
|
||||
.filter(|line| !line.trim().starts_with("//") && !line.trim().is_empty()) // ignore comment and empty lines
|
||||
.filter_map(|line| line.trim().parse::<u64>().ok())
|
||||
.map(Integer::from)
|
||||
.collect();
|
||||
|
||||
if numbers.len() < 2 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"Need at least 2 numbers to compute AGCD"
|
||||
));
|
||||
}
|
||||
|
||||
Ok(AgcdInput { noise_bits, numbers })
|
||||
}
|
64
src/main.rs
64
src/main.rs
@@ -1,32 +1,42 @@
|
||||
use rug::Integer;
|
||||
mod agcd;
|
||||
mod lll;
|
||||
mod matrix;
|
||||
mod utils;
|
||||
mod agcd;
|
||||
use crate::agcd::agcd;
|
||||
mod file;
|
||||
|
||||
fn main() {
|
||||
// 1. Build lattice matrix basis
|
||||
let ciphertexts = vec![
|
||||
Integer::from(32219),
|
||||
Integer::from(21254),
|
||||
Integer::from(16764),
|
||||
Integer::from(338),
|
||||
Integer::from(29960),
|
||||
Integer::from(23516),
|
||||
Integer::from(7084),
|
||||
Integer::from(26735),
|
||||
Integer::from(23195),
|
||||
Integer::from(11928),
|
||||
Integer::from(985),
|
||||
Integer::from(11916),
|
||||
Integer::from(13217),
|
||||
Integer::from(29966),
|
||||
Integer::from(14171),
|
||||
Integer::from(13211),
|
||||
Integer::from(23514),
|
||||
Integer::from(19643)
|
||||
];
|
||||
let noise_bits = 2;
|
||||
let _ = agcd(ciphertexts, noise_bits);
|
||||
use crate::agcd::agcd;
|
||||
use crate::file::parse_file;
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
#[command(propagate_version = true)]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
/// approximate GCD
|
||||
Agcd {
|
||||
/// (default './input.txt')
|
||||
path: Option<PathBuf>,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
match &cli.command {
|
||||
Commands::Agcd { path } => {
|
||||
let path = path.as_deref().unwrap_or(Path::new("./input.txt"));
|
||||
let input = parse_file(path)?;
|
||||
|
||||
let result = agcd(input.numbers, input.noise_bits);
|
||||
println!("Approximate GCD with noise_bits={}: {}", input.noise_bits, result);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
Reference in New Issue
Block a user