command line, read numbers from file + python script generate test values
This commit is contained in:
parent
950b64c4cd
commit
64c58265c4
@ -6,5 +6,6 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.35", features = ["derive"] }
|
||||
lll-rs = "0.2.0"
|
||||
rug = "1.27.0"
|
||||
|
@ -1,6 +1,28 @@
|
||||
from random import randint
|
||||
p = randint(100,1000)
|
||||
a = ["Integer::from("+str(p*randint(1,100)+randint(0,20))+"), " for _ in range(200)]
|
||||
for b in a:
|
||||
print(b)
|
||||
print(p)
|
||||
import sys
|
||||
import random
|
||||
import argparse
|
||||
|
||||
def generate_test_file(noise_bits, number):
|
||||
|
||||
p = random.randint(100, 1000)
|
||||
while p % 2 == 0:
|
||||
p = random.randint(100, 1000)
|
||||
|
||||
max_noise = (1 << noise_bits) - 1 # 2^noise_bits - 1
|
||||
|
||||
a = [str(p * random.randint(1, 100) + random.randint(0, max_noise)) for _ in range(number)]
|
||||
|
||||
print(noise_bits)
|
||||
|
||||
for b in a:
|
||||
print(b)
|
||||
|
||||
print(f"// True p: {p}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Generate test input for AGCD computation')
|
||||
parser.add_argument('--noise-bits', type=int, default=5, help='Number of noise bits (default: 5)')
|
||||
parser.add_argument('--number', type=int, default=20, help='Number of numbers to generate (default: 20)')
|
||||
|
||||
args = parser.parse_args()
|
||||
generate_test_file(args.noise_bits, args.number)
|
||||
|
@ -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(())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user