command line, read numbers from file + python script generate test values

This commit is contained in:
2025-04-11 09:12:18 +02:00
parent 950b64c4cd
commit 64c58265c4
5 changed files with 119 additions and 34 deletions

View File

@@ -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
View 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 })
}

View File

@@ -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(())
}