ckks_engine/
polynomial.rs1use std::panic;
2
3#[derive(Debug, Clone)]
4pub struct Polynomial {
5 pub coeffs: Vec<i64>, }
7
8impl Polynomial {
9 pub fn new(coeffs: Vec<i64>) -> Self {
11 Polynomial { coeffs }
12 }
13
14 pub fn decode(&self) -> Vec<i64> {
16 self.coeffs.iter().map(|&c| {
17 let real = (c as f64) / 10_000_000.0;
18 real.round() as i64 }).collect()
20 }
21
22 pub fn add(&self, other: &Polynomial) -> Polynomial {
24 let len = self.coeffs.len().max(other.coeffs.len());
26 let mut result = vec![0; len]; for i in 0..len {
30 let a = if i < self.coeffs.len() { self.coeffs[i] } else { 0 }; let b = if i < other.coeffs.len() { other.coeffs[i] } else { 0 }; result[i] = a + b; }
34
35 Polynomial::new(result) }
37
38 pub fn subtract(&self, other: &Polynomial) -> Polynomial {
40 let len = self.coeffs.len().max(other.coeffs.len());
42 let mut result = vec![0; len]; for i in 0..len {
46 let a = if i < self.coeffs.len() { self.coeffs[i] } else { 0 }; let b = if i < other.coeffs.len() { other.coeffs[i] } else { 0 }; result[i] = a - b; }
50
51 Polynomial::new(result) }
53
54 pub fn multiply(&self, other: &Polynomial) -> Polynomial {
56 let result_size = self.coeffs.len().max(other.coeffs.len());
58 let mut result_coeffs = vec![0.0; result_size]; let min_len = self.coeffs.len().min(other.coeffs.len());
62 for i in 0..min_len {
63 result_coeffs[i] = (self.coeffs[i] as f64 * other.coeffs[i] as f64) / 1e7; }
65 Polynomial::new(result_coeffs.iter().map(|&x| x.round() as i64).collect())
67 }
68
69 pub fn negation(&self) -> Polynomial {
71 let negated_coeffs: Vec<f64> = self.coeffs.iter().map(|&c| -(c as f64)).collect();
73 Polynomial::new(negated_coeffs.iter().map(|&x| x.round() as i64).collect())
75 }
76
77 pub fn divide(&self, divisor: &Polynomial, scaling_factor: f64) -> Polynomial {
78 let mut result_coeffs = Vec::new();
79
80 if divisor.coeffs.len() == 1 {
82 let scalar = divisor.coeffs[0];
83 if scalar == 0 {
84 eprintln!("Division by zero encountered in scalar divisor. Skipping computation.");
85 return Polynomial::new(vec![]); }
87
88 for a in &self.coeffs {
89 let result = panic::catch_unwind(|| {
90 let scaled_result = (*a as f64 / scalar as f64) * scaling_factor;
91 scaled_result.round() as i64
92 });
93
94 match result {
95 Ok(value) => result_coeffs.push(value),
96 Err(_) => {
97 eprintln!("Panic occurred during scalar division. Skipping coefficient.");
98 result_coeffs.push(0); }
100 }
101 }
102 } else {
103 for i in 0..std::cmp::max(self.coeffs.len(), divisor.coeffs.len()) {
105 let a = self.coeffs.get(i).copied().unwrap_or(0); let b = divisor.coeffs.get(i).copied().unwrap_or(0); if b == 0 {
109 eprintln!(
110 "Division by zero encountered at index {}. Defaulting to 0.",
111 i
112 );
113 result_coeffs.push(0);
114 continue;
115 }
116
117 let result = panic::catch_unwind(|| {
118 let scaled_result = (a as f64 / b as f64) * scaling_factor;
119 scaled_result.round() as i64
120 });
121
122 match result {
123 Ok(value) => result_coeffs.push(value),
124 Err(_) => {
125 eprintln!("Panic occurred during polynomial division at index {}. Defaulting to 0.", i);
126 result_coeffs.push(0); }
128 }
129 }
130 }
131
132 Polynomial::new(result_coeffs)
134 }
135}