arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/math/tests/rescaling_rns.rs
math/tests/rescaling_rns.rsRaw
  1use math::poly::PolyRNS;
  2use math::ring::RingRNS;
  3use num_bigint::BigInt;
  4use math::num_bigint::Div;
  5use sampling::source::Source;
  6use itertools::izip;
  7
  8#[test]
  9fn rescaling_rns_u64() {
 10    let n = 1 << 10;
 11    let moduli: Vec<u64> = vec![0x1fffffffffc80001u64, 0x1fffffffffe00001u64, 0x1fffffffffb40001, 0x1fffffffff500001];
 12    let ring_rns: RingRNS<u64> = RingRNS::new(n, moduli);
 13
 14 
 15    sub_test("test_div_by_last_modulus::<ROUND:false, NTT:false>", ||{test_div_by_last_modulus::<false, false>(&ring_rns)});
 16    sub_test("test_div_by_last_modulus::<ROUND:false, NTT:true>", ||{test_div_by_last_modulus::<false, true>(&ring_rns)});
 17    sub_test("test_div_by_last_modulus::<ROUND:true, NTT:false>", ||{test_div_by_last_modulus::<true, false>(&ring_rns)});
 18    sub_test("test_div_by_last_modulus::<ROUND:true, NTT:true>", ||{test_div_by_last_modulus::<true, true>(&ring_rns)});
 19    sub_test("test_div_by_last_modulus_inplace::<ROUND:false, NTT:false>", ||{test_div_by_last_modulus_inplace::<false, false>(&ring_rns)});
 20    sub_test("test_div_by_last_modulus_inplace::<ROUND:false, NTT:true>", ||{test_div_by_last_modulus_inplace::<false, true>(&ring_rns)});
 21    sub_test("test_div_by_last_modulus_inplace::<ROUND:true, NTT:true>", ||{test_div_by_last_modulus_inplace::<true, true>(&ring_rns)});
 22    sub_test("test_div_by_last_modulus_inplace::<ROUND:true, NTT:false>", ||{test_div_by_last_modulus_inplace::<true, false>(&ring_rns)});
 23
 24
 25    
 26    
 27
 28
 29    //sub_test("test_div_by_last_moduli::<ROUND:false, NTT:false>", ||{test_div_by_last_moduli::<false, false>(&ring_rns)});
 30}
 31
 32fn sub_test<F: FnOnce()>(name: &str, f: F) {
 33    println!("Running {}", name);
 34    f();
 35}
 36
 37fn test_div_by_last_modulus<const ROUND:bool, const NTT:bool>(ring_rns: &RingRNS<u64>){
 38
 39    let seed: [u8; 32] = [0; 32];
 40    let mut source: Source = Source::new(seed);
 41
 42    let mut a: PolyRNS<u64> = ring_rns.new_polyrns();
 43    let mut b: PolyRNS<u64> = ring_rns.new_polyrns();
 44    let mut c: PolyRNS<u64> = ring_rns.at_level(ring_rns.level() - 1).new_polyrns();
 45
 46    // Allocates a random PolyRNS
 47    ring_rns.fill_uniform(&mut source, &mut a);
 48
 49    // Maps PolyRNS to [BigInt]
 50    let mut coeffs_a: Vec<BigInt> = (0..a.n()).map(|i| BigInt::from(i)).collect();
 51    ring_rns
 52        .at_level(a.level())
 53        .to_bigint_inplace(&a, 1, &mut coeffs_a);
 54
 55    // Performs c = intt(ntt(a) / q_level)
 56    if NTT {
 57        ring_rns.ntt_inplace::<false>(&mut a);
 58    }
 59
 60    ring_rns.div_by_last_modulus::<ROUND,NTT>(&a, &mut b, &mut c);
 61    
 62
 63    if NTT {
 64        ring_rns.at_level(c.level()).intt_inplace::<false>(&mut c);
 65    }
 66
 67    // Exports c to coeffs_c
 68    let mut coeffs_c = vec![BigInt::from(0); c.n()];
 69    ring_rns
 70        .at_level(c.level())
 71        .to_bigint_inplace(&c, 1, &mut coeffs_c);
 72
 73    // Performs floor division on a
 74    let scalar_big = BigInt::from(ring_rns.0[ring_rns.level()].modulus.q);
 75    coeffs_a.iter_mut().for_each(|a| {
 76        if ROUND{
 77            *a = a.div_round(&scalar_big);
 78        }else{
 79            *a = a.div_floor(&scalar_big);
 80        }    
 81    });
 82
 83    izip!(coeffs_a, coeffs_c).for_each(|(a, b)| assert_eq!(a, b));
 84}
 85
 86fn test_div_by_last_modulus_inplace<const ROUND:bool, const NTT:bool>(ring_rns: &RingRNS<u64>) {
 87
 88    let seed: [u8; 32] = [0; 32];
 89    let mut source: Source = Source::new(seed);
 90
 91    let mut a: PolyRNS<u64> = ring_rns.new_polyrns();
 92    let mut buf: PolyRNS<u64> = ring_rns.new_polyrns();
 93
 94    // Allocates a random PolyRNS
 95    ring_rns.fill_uniform(&mut source, &mut a);
 96
 97    // Maps PolyRNS to [BigInt]
 98    let mut coeffs_a: Vec<BigInt> = (0..a.n()).map(|i| BigInt::from(i)).collect();
 99    ring_rns
100        .at_level(a.level())
101        .to_bigint_inplace(&a, 1, &mut coeffs_a);
102
103    // Performs c = intt(ntt(a) / q_level)
104    if NTT {
105        ring_rns.ntt_inplace::<false>(&mut a);
106    }
107
108    ring_rns.div_by_last_modulus_inplace::<ROUND,NTT>(&mut buf, &mut a);
109
110    if NTT {
111        ring_rns.at_level(a.level()-1).intt_inplace::<false>(&mut a);
112    }
113
114    // Exports c to coeffs_c
115    let mut coeffs_c = vec![BigInt::from(0); a.n()];
116    ring_rns
117        .at_level(a.level()-1)
118        .to_bigint_inplace(&a, 1, &mut coeffs_c);
119
120    // Performs floor division on a
121    let scalar_big = BigInt::from(ring_rns.0[ring_rns.level()].modulus.q);
122    coeffs_a.iter_mut().for_each(|a| {
123        if ROUND{
124            *a = a.div_round(&scalar_big);
125        }else{
126            *a = a.div_floor(&scalar_big);
127        }    
128    });
129
130    izip!(coeffs_a, coeffs_c).for_each(|(a, b)| assert_eq!(a, b));
131}
132
133
134fn test_div_by_last_moduli<const ROUND:bool, const NTT:bool>(ring_rns: &RingRNS<u64>){
135
136    let seed: [u8; 32] = [0; 32];
137    let mut source: Source = Source::new(seed);
138
139    let nb_moduli: usize = ring_rns.level();
140
141    let mut a: PolyRNS<u64> = ring_rns.new_polyrns();
142    let mut buf: PolyRNS<u64> = ring_rns.new_polyrns();
143    let mut c: PolyRNS<u64> = ring_rns.at_level(ring_rns.level() - nb_moduli).new_polyrns();
144
145    // Allocates a random PolyRNS
146    ring_rns.fill_uniform(&mut source, &mut a);
147
148    // Maps PolyRNS to [BigInt]
149    let mut coeffs_a: Vec<BigInt> = (0..a.n()).map(|i| BigInt::from(i)).collect();
150    ring_rns
151        .at_level(a.level())
152        .to_bigint_inplace(&a, 1, &mut coeffs_a);
153
154    // Performs c = intt(ntt(a) / q_level)
155    if NTT {
156        ring_rns.ntt_inplace::<false>(&mut a);
157    }
158
159    ring_rns.div_by_last_moduli::<ROUND,NTT>(nb_moduli, &a, &mut buf, &mut c);
160
161    if NTT {
162        ring_rns.at_level(c.level()).intt_inplace::<false>(&mut c);
163    }
164
165    // Exports c to coeffs_c
166    let mut coeffs_c = vec![BigInt::from(0); a.n()];
167    ring_rns
168        .at_level(c.level())
169        .to_bigint_inplace(&c, 1, &mut coeffs_c);
170
171    // Performs floor division on a
172    let mut scalar_big = BigInt::from(1);
173    (0..nb_moduli).for_each(|i|{scalar_big *= BigInt::from(ring_rns.0[ring_rns.level()-i].modulus.q)});
174    coeffs_a.iter_mut().for_each(|a| {
175        if ROUND{
176            *a = a.div_round(&scalar_big);
177        }else{
178            *a = a.div_floor(&scalar_big);
179        }    
180    });
181
182    izip!(coeffs_a, coeffs_c).for_each(|(a, b)| assert_eq!(a, b));
183}
184
185/* 
186fn test_div_floor_by_last_moduli_inplace<const NTT: bool>(ring_rns: &RingRNS<u64>) {
187    let seed: [u8; 32] = [0; 32];
188    let mut source: Source = Source::new(seed);
189
190    let nb_moduli: usize = ring_rns.level();
191
192    let mut a: PolyRNS<u64> = ring_rns.new_polyrns();
193    let mut b: PolyRNS<u64> = ring_rns.new_polyrns();
194
195    // Allocates a random PolyRNS
196    ring_rns.fill_uniform(&mut source, &mut a);
197
198    // Maps PolyRNS to [BigInt]
199    let mut coeffs_a: Vec<BigInt> = (0..a.n()).map(|i| BigInt::from(i)).collect();
200    ring_rns
201        .at_level(a.level())
202        .to_bigint_inplace(&a, 1, &mut coeffs_a);
203
204    // Performs c = intt(ntt(a) / q_level)
205    if NTT {
206        ring_rns.ntt_inplace::<false>(&mut a);
207    }
208
209    ring_rns.div_floor_by_last_moduli_inplace::<NTT>(nb_moduli, &mut b, &mut a);
210
211    if NTT {
212        ring_rns.at_level(a.level()-nb_moduli).intt_inplace::<false>(&mut a);
213    }
214
215    // Exports c to coeffs_c
216    let mut coeffs_c = vec![BigInt::from(0); a.n()];
217    ring_rns
218        .at_level(a.level()-nb_moduli)
219        .to_bigint_inplace(&a, 1, &mut coeffs_c);
220
221    // Performs floor division on a
222    let mut scalar_big = BigInt::from(1);
223    (0..nb_moduli).for_each(|i|{scalar_big *= BigInt::from(ring_rns.0[ring_rns.level()-i].modulus.q)});
224    coeffs_a.iter_mut().for_each(|a| {a.div_floor(&scalar_big)});
225
226    assert!(coeffs_a == coeffs_c, "test_div_floor_by_last_moduli_inplace");
227}
228*/