1fn tadd(a: i8, b: i8) -> i8 {
7 match (a, b) {
8 (-1, -1) => 1, (-1, 0) => -1, (-1, 1) => 0,
9 (0, -1) => -1, (0, 0) => 0, (0, 1) => 1,
10 (1, -1) => 0, (1, 0) => 1, (1, 1) => -1, _ => 0,
11 }
12}
13fn tmul(a: i8, b: i8) -> i8 {
14 match (a, b) {
15 (-1, -1) => 1, (-1, 1) => -1, (1, -1) => -1, (1, 1) => 1, _ => 0,
16 }
17}
18
19pub fn vec_add(a: &[i8], b: &[i8]) -> Vec<i8> {
21 a.iter().zip(b).map(|(&x, &y)| tadd(x, y)).collect()
22}
23
24pub fn inner_product(a: &[i8], b: &[i8]) -> i8 {
26 a.iter().zip(b).fold(0, |acc, (&x, &y)| tadd(acc, tmul(x, y)))
27}
28
29pub fn mat_vec_mul(mat: &[Vec<i8>], vec: &[i8]) -> Vec<i8> {
31 mat.iter().map(|row| inner_product(row, vec)).collect()
32}
33
34pub fn mat_mul(a: &[Vec<i8>], b: &[Vec<i8>]) -> Vec<Vec<i8>> {
36 let cols = b.get(0).map(|r| r.len()).unwrap_or(0);
37 (0..a.len()).map(|i| {
38 (0..cols).map(|j| {
39 let sum: i8 = (0..b.len()).fold(0, |acc, k| tadd(acc, tmul(a[i][k], b[k][j])));
40 sum
41 }).collect()
42 }).collect()
43}
44
45pub fn random_vec(len: usize, seed: u64) -> Vec<i8> {
47 let mut s = seed;
48 (0..len).map(|i| {
49 s = s.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
50 match (s.wrapping_add(i as u64)) % 3 { 0 => -1, 1 => 0, _ => 1 }
51 }).collect()
52}
53
54pub fn lwe_sample(secret: &[i8], seed: u64) -> (Vec<i8>, i8) {
56 let a = random_vec(secret.len(), seed);
57 let b = inner_product(&a, secret);
58 (a, b)
59}
60
61pub fn hamming_weight(v: &[i8]) -> usize { v.iter().filter(|&&x| x != 0).count() }
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn test_vec_add_closure() {
70 let r = vec_add(&[1, -1, 0], &[-1, 1, 0]);
71 assert!(r.iter().all(|&v| v >= -1 && v <= 1));
72 }
73
74 #[test]
75 fn test_vec_add_identity() {
76 let r = vec_add(&[1, -1, 0], &[0, 0, 0]);
77 assert_eq!(r, vec![1, -1, 0]);
78 }
79
80 #[test]
81 fn test_inner_product() {
82 assert_eq!(inner_product(&[1, 1], &[1, 1]), -1); }
86
87 #[test]
88 fn test_mat_vec_mul() {
89 let mat = vec![vec![1, 0], vec![0, 1]]; let v = vec![1, -1];
91 let r = mat_vec_mul(&mat, &v);
92 assert_eq!(r, vec![1, -1]);
93 }
94
95 #[test]
96 fn test_mat_mul_identity() {
97 let id = vec![vec![1, 0], vec![0, 1]];
98 let r = mat_mul(&id, &id);
99 assert_eq!(r, id);
100 }
101
102 #[test]
103 fn test_random_vec() {
104 let v = random_vec(10, 42);
105 assert_eq!(v.len(), 10);
106 assert!(v.iter().all(|&x| x >= -1 && x <= 1));
107 }
108
109 #[test]
110 fn test_lwe_sample() {
111 let secret = vec![1, -1, 0, 1];
112 let (a, b) = lwe_sample(&secret, 123);
113 assert_eq!(a.len(), 4);
114 }
115
116 #[test]
117 fn test_hamming_weight() {
118 assert_eq!(hamming_weight(&[1, -1, 0, 0, 1]), 3);
119 }
120}