1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT license.
3 
4 using Microsoft.Research.SEAL;
5 using Microsoft.VisualStudio.TestTools.UnitTesting;
6 using System;
7 using System.Collections.Generic;
8 using System.Linq;
9 using System.Numerics;
10 
11 namespace SEALNetTest
12 {
13     [TestClass]
14     public class EvaluatorTests
15     {
16         [TestMethod]
CreateTest()17         public void CreateTest()
18         {
19             Evaluator evaluator = new Evaluator(GlobalContext.BFVContext);
20             Assert.IsNotNull(evaluator);
21         }
22 
23         [TestMethod]
NegateTest()24         public void NegateTest()
25         {
26             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
27             {
28                 PolyModulusDegree = 64,
29                 PlainModulus = new Modulus(1 << 6),
30                 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
31             };
32             SEALContext context = new SEALContext(parms,
33                 expandModChain: false,
34                 secLevel: SecLevelType.None);
35             KeyGenerator keygen = new KeyGenerator(context);
36             Assert.IsTrue(context.ParametersSet);
37             keygen.CreatePublicKey(out PublicKey publicKey);
38 
39             Encryptor encryptor = new Encryptor(context, publicKey);
40             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
41             Evaluator evaluator = new Evaluator(context);
42 
43             Ciphertext encrypted = new Ciphertext();
44             Ciphertext encdestination = new Ciphertext();
45             Plaintext plain = new Plaintext("3x^2 + 2x^1 + 1");
46             Plaintext plaindest = new Plaintext();
47             encryptor.Encrypt(plain, encrypted);
48             evaluator.Negate(encrypted, encdestination);
49             decryptor.Decrypt(encdestination, plaindest);
50 
51             // coefficients are negated (modulo 64)
52             Assert.AreEqual(0x3Ful, plaindest[0]);
53             Assert.AreEqual(0x3Eul, plaindest[1]);
54             Assert.AreEqual(0x3Dul, plaindest[2]);
55 
56             plain = new Plaintext("6x^3 + 7x^2 + 8x^1 + 9");
57             encryptor.Encrypt(plain, encrypted);
58             evaluator.NegateInplace(encrypted);
59             decryptor.Decrypt(encrypted, plain);
60 
61             // coefficients are negated (modulo 64)
62             Assert.AreEqual(0x37ul, plain[0]);
63             Assert.AreEqual(0x38ul, plain[1]);
64             Assert.AreEqual(0x39ul, plain[2]);
65             Assert.AreEqual(0x3Aul, plain[3]);
66         }
67 
68         [TestMethod]
AddTest()69         public void AddTest()
70         {
71             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
72             {
73                 PolyModulusDegree = 64,
74                 PlainModulus = new Modulus(1 << 6),
75                 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
76             };
77             SEALContext context = new SEALContext(parms,
78                 expandModChain: false,
79                 secLevel: SecLevelType.None);
80             KeyGenerator keygen = new KeyGenerator(context);
81             keygen.CreatePublicKey(out PublicKey publicKey);
82 
83             Encryptor encryptor = new Encryptor(context, publicKey);
84             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
85             Evaluator evaluator = new Evaluator(context);
86 
87             Ciphertext encrypted1 = new Ciphertext();
88             Ciphertext encrypted2 = new Ciphertext();
89             Ciphertext encdestination = new Ciphertext();
90 
91             Plaintext plain1 = new Plaintext("5x^4 + 4x^3 + 3x^2 + 2x^1 + 1");
92             Plaintext plain2 = new Plaintext("4x^7 + 5x^6 + 6x^5 + 7x^4 + 8x^3 + 9x^2 + Ax^1 + B");
93             Plaintext plaindest = new Plaintext();
94 
95             encryptor.Encrypt(plain1, encrypted1);
96             encryptor.Encrypt(plain2, encrypted2);
97             evaluator.Add(encrypted1, encrypted2, encdestination);
98             decryptor.Decrypt(encdestination, plaindest);
99 
100             Assert.AreEqual(12ul, plaindest[0]);
101             Assert.AreEqual(12ul, plaindest[1]);
102             Assert.AreEqual(12ul, plaindest[2]);
103             Assert.AreEqual(12ul, plaindest[3]);
104             Assert.AreEqual(12ul, plaindest[4]);
105             Assert.AreEqual(6ul, plaindest[5]);
106             Assert.AreEqual(5ul, plaindest[6]);
107             Assert.AreEqual(4ul, plaindest[7]);
108 
109             plain1 = new Plaintext("1x^2 + 2x^1 + 3");
110             plain2 = new Plaintext("2x^3 + 2x^2 + 2x^1 + 2");
111 
112             encryptor.Encrypt(plain1, encrypted1);
113             encryptor.Encrypt(plain2, encrypted2);
114             evaluator.AddInplace(encrypted1, encrypted2);
115             decryptor.Decrypt(encrypted1, plaindest);
116 
117             Assert.AreEqual(5ul, plaindest[0]);
118             Assert.AreEqual(4ul, plaindest[1]);
119             Assert.AreEqual(3ul, plaindest[2]);
120             Assert.AreEqual(2ul, plaindest[3]);
121         }
122 
123         [TestMethod]
AddPlainTest()124         public void AddPlainTest()
125         {
126             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
127             {
128                 PolyModulusDegree = 64,
129                 PlainModulus = new Modulus(1 << 6),
130                 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
131             };
132             SEALContext context = new SEALContext(parms,
133                 expandModChain: false,
134                 secLevel: SecLevelType.None);
135             KeyGenerator keygen = new KeyGenerator(context);
136             keygen.CreatePublicKey(out PublicKey publicKey);
137 
138             Encryptor encryptor = new Encryptor(context, publicKey);
139             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
140             Evaluator evaluator = new Evaluator(context);
141 
142             Ciphertext encrypted = new Ciphertext();
143             Ciphertext encdest = new Ciphertext();
144             Plaintext plain = new Plaintext("3x^2 + 2x^1 + 1");
145             Plaintext plaindest = new Plaintext();
146 
147             encryptor.Encrypt(new Plaintext("2x^2 + 2x^1 + 2"), encrypted);
148             evaluator.AddPlain(encrypted, plain, encdest);
149             decryptor.Decrypt(encdest, plaindest);
150 
151             Assert.AreEqual(3ul, plaindest[0]);
152             Assert.AreEqual(4ul, plaindest[1]);
153             Assert.AreEqual(5ul, plaindest[2]);
154 
155             plain.Set("1x^2 + 1x^1 + 1");
156             encryptor.Encrypt(new Plaintext("2x^3 + 2x^2 + 2x^1 + 2"), encrypted);
157             evaluator.AddPlainInplace(encrypted, plain);
158             decryptor.Decrypt(encrypted, plaindest);
159 
160             Assert.AreEqual(4ul, plaindest.CoeffCount);
161             Assert.AreEqual(3ul, plaindest[0]);
162             Assert.AreEqual(3ul, plaindest[1]);
163             Assert.AreEqual(3ul, plaindest[2]);
164             Assert.AreEqual(2ul, plaindest[3]);
165         }
166 
167         [TestMethod]
AddManyTest()168         public void AddManyTest()
169         {
170             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
171             {
172                 PolyModulusDegree = 64,
173                 PlainModulus = new Modulus(1 << 6),
174                 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
175             };
176             SEALContext context = new SEALContext(parms,
177                 expandModChain: false,
178                 secLevel: SecLevelType.None);
179             KeyGenerator keygen = new KeyGenerator(context);
180             keygen.CreatePublicKey(out PublicKey publicKey);
181 
182             Encryptor encryptor = new Encryptor(context, publicKey);
183             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
184             Evaluator evaluator = new Evaluator(context);
185 
186             Ciphertext[] encrypteds = new Ciphertext[6];
187 
188             for(int i = 0; i < encrypteds.Length; i++)
189             {
190                 encrypteds[i] = new Ciphertext();
191                 encryptor.Encrypt(new Plaintext((i + 1).ToString()), encrypteds[i]);
192             }
193 
194             Ciphertext encdest = new Ciphertext();
195             Plaintext plaindest = new Plaintext();
196             evaluator.AddMany(encrypteds, encdest);
197             decryptor.Decrypt(encdest, plaindest);
198 
199             // 1+2+3+4+5+6
200             Assert.AreEqual(21ul, plaindest[0]);
201         }
202 
203         [TestMethod]
SubTest()204         public void SubTest()
205         {
206             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
207             {
208                 PolyModulusDegree = 64,
209                 PlainModulus = new Modulus(1 << 6),
210                 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
211             };
212             SEALContext context = new SEALContext(parms,
213                 expandModChain: false,
214                 secLevel: SecLevelType.None);
215             KeyGenerator keygen = new KeyGenerator(context);
216             keygen.CreatePublicKey(out PublicKey publicKey);
217 
218             Encryptor encryptor = new Encryptor(context, publicKey);
219             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
220             Evaluator evaluator = new Evaluator(context);
221 
222             Ciphertext encrypted1 = new Ciphertext();
223             Ciphertext encrypted2 = new Ciphertext();
224             Ciphertext encdest = new Ciphertext();
225             Plaintext plain1 = new Plaintext("Ax^2 + Bx^1 + C");
226             Plaintext plain2 = new Plaintext("5x^3 + 5x^2 + 5x^1 + 5");
227             Plaintext plaindest = new Plaintext();
228 
229             encryptor.Encrypt(plain1, encrypted1);
230             encryptor.Encrypt(plain2, encrypted2);
231             evaluator.Sub(encrypted1, encrypted2, encdest);
232             decryptor.Decrypt(encdest, plaindest);
233 
234             Assert.AreEqual(7ul, plaindest[0]);
235             Assert.AreEqual(6ul, plaindest[1]);
236             Assert.AreEqual(5ul, plaindest[2]);
237             Assert.AreEqual(0x3Bul, plaindest[3]);
238 
239             plain1.Set("Ax^3 + Bx^2 + Cx^1 + D");
240             plain2.Set("5x^2 + 5x^1 + 5");
241 
242             encryptor.Encrypt(plain1, encrypted1);
243             encryptor.Encrypt(plain2, encrypted2);
244             evaluator.SubInplace(encrypted1, encrypted2);
245             decryptor.Decrypt(encrypted1, plaindest);
246 
247             Assert.AreEqual(8ul, plaindest[0]);
248             Assert.AreEqual(7ul, plaindest[1]);
249             Assert.AreEqual(6ul, plaindest[2]);
250             Assert.AreEqual(10ul, plaindest[3]);
251         }
252 
253         [TestMethod]
SubPlainTest()254         public void SubPlainTest()
255         {
256             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
257             {
258                 PolyModulusDegree = 64,
259                 PlainModulus = new Modulus(1 << 6),
260                 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
261             };
262             SEALContext context = new SEALContext(parms,
263                 expandModChain: false,
264                 secLevel: SecLevelType.None);
265             KeyGenerator keygen = new KeyGenerator(context);
266             keygen.CreatePublicKey(out PublicKey publicKey);
267 
268             Encryptor encryptor = new Encryptor(context, publicKey);
269             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
270             Evaluator evaluator = new Evaluator(context);
271 
272             Ciphertext encrypted = new Ciphertext();
273             Ciphertext encdest = new Ciphertext();
274             Plaintext plain = new Plaintext("5x^2 + 4x^1 + 3");
275             Plaintext plaindest = new Plaintext();
276 
277             encryptor.Encrypt(new Plaintext("3x^1 + 4"), encrypted);
278             evaluator.SubPlain(encrypted, plain, encdest);
279             decryptor.Decrypt(encdest, plaindest);
280 
281             Assert.AreEqual(3ul, plaindest.CoeffCount);
282             Assert.AreEqual(1ul, plaindest[0]);
283             Assert.AreEqual(0x3Ful, plaindest[1]); // -1
284             Assert.AreEqual(0x3Bul, plaindest[2]); // -5
285 
286             plain.Set("6x^3 + 1x^2 + 7x^1 + 2");
287             encryptor.Encrypt(new Plaintext("Ax^2 + Bx^1 + C"), encrypted);
288             evaluator.SubPlainInplace(encrypted, plain);
289             decryptor.Decrypt(encrypted, plaindest);
290 
291             Assert.AreEqual(4ul, plaindest.CoeffCount);
292             Assert.AreEqual(10ul, plaindest[0]);
293             Assert.AreEqual(4ul, plaindest[1]);
294             Assert.AreEqual(9ul, plaindest[2]);
295             Assert.AreEqual(0x3Aul, plaindest[3]); // -6
296         }
297 
298         [TestMethod]
MultiplyTest()299         public void MultiplyTest()
300         {
301             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
302             {
303                 PolyModulusDegree = 64,
304                 PlainModulus = new Modulus(1 << 6),
305                 CoeffModulus = CoeffModulus.Create(64, new int[] { 40 })
306             };
307             SEALContext context = new SEALContext(parms,
308                 expandModChain: false,
309                 secLevel: SecLevelType.None);
310             KeyGenerator keygen = new KeyGenerator(context);
311             keygen.CreatePublicKey(out PublicKey publicKey);
312 
313             Encryptor encryptor = new Encryptor(context, publicKey);
314             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
315             Evaluator evaluator = new Evaluator(context);
316 
317             Ciphertext encrypted1 = new Ciphertext();
318             Ciphertext encrypted2 = new Ciphertext();
319             Ciphertext encdest = new Ciphertext();
320             Plaintext plaindest = new Plaintext();
321 
322             encryptor.Encrypt(new Plaintext("1x^4 + 2x^3 + 3x^2 + 4x^1 + 5"), encrypted1);
323             encryptor.Encrypt(new Plaintext("3x^2 + 2x^1 + 1"), encrypted2);
324             evaluator.Multiply(encrypted1, encrypted2, encdest);
325             decryptor.Decrypt(encdest, plaindest);
326 
327             // {3x^6 + 8x^5 + Ex^4 + 14x^3 + 1Ax^2 + Ex^1 + 5}
328             Assert.AreEqual(7ul, plaindest.CoeffCount);
329             Assert.AreEqual(5ul, plaindest[0]);
330             Assert.AreEqual(14ul, plaindest[1]);
331             Assert.AreEqual(26ul, plaindest[2]);
332             Assert.AreEqual(20ul, plaindest[3]);
333             Assert.AreEqual(14ul, plaindest[4]);
334             Assert.AreEqual(8ul, plaindest[5]);
335             Assert.AreEqual(3ul, plaindest[6]);
336 
337             encryptor.Encrypt(new Plaintext("2x^2 + 3x^1 + 4"), encrypted1);
338             encryptor.Encrypt(new Plaintext("4x^1 + 5"), encrypted2);
339             evaluator.MultiplyInplace(encrypted1, encrypted2);
340             decryptor.Decrypt(encrypted1, plaindest);
341 
342             // {8x^3 + 16x^2 + 1Fx^1 + 14}
343             Assert.AreEqual(4ul, plaindest.CoeffCount);
344             Assert.AreEqual(20ul, plaindest[0]);
345             Assert.AreEqual(31ul, plaindest[1]);
346             Assert.AreEqual(22ul, plaindest[2]);
347             Assert.AreEqual(8ul, plaindest[3]);
348         }
349 
350         [TestMethod]
MultiplyManyTest()351         public void MultiplyManyTest()
352         {
353             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
354             {
355                 PolyModulusDegree = 128,
356                 PlainModulus = new Modulus(1 << 6),
357                 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 })
358             };
359             SEALContext context = new SEALContext(parms,
360                 expandModChain: false,
361                 secLevel: SecLevelType.None);
362             KeyGenerator keygen = new KeyGenerator(context);
363             keygen.CreatePublicKey(out PublicKey publicKey);
364             keygen.CreateRelinKeys(out RelinKeys relinKeys);
365 
366             Encryptor encryptor = new Encryptor(context, publicKey);
367             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
368             Evaluator evaluator = new Evaluator(context);
369 
370             Ciphertext[] encrypteds = new Ciphertext[4];
371             Ciphertext encdest = new Ciphertext();
372             Plaintext plaindest = new Plaintext();
373 
374             for (int i = 0; i < encrypteds.Length; i++)
375             {
376                 encrypteds[i] = new Ciphertext();
377                 encryptor.Encrypt(new Plaintext((i + 1).ToString()), encrypteds[i]);
378             }
379 
380             evaluator.MultiplyMany(encrypteds, relinKeys, encdest);
381             decryptor.Decrypt(encdest, plaindest);
382 
383             Assert.AreEqual(1ul, plaindest.CoeffCount);
384             Assert.AreEqual(24ul, plaindest[0]);
385 
386             Utilities.AssertThrows<ArgumentException>(() =>
387             {
388                 // Uninitialized memory pool handle
389                 MemoryPoolHandle pool = new MemoryPoolHandle();
390                 evaluator.MultiplyMany(encrypteds, relinKeys, encdest, pool);
391             });
392         }
393 
394         [TestMethod]
MultiplyPlainTest()395         public void MultiplyPlainTest()
396         {
397             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
398             {
399                 PolyModulusDegree = 128,
400                 PlainModulus = new Modulus(1 << 6),
401                 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 })
402             };
403             SEALContext context = new SEALContext(parms,
404                 expandModChain: false,
405                 secLevel: SecLevelType.None);
406             KeyGenerator keygen = new KeyGenerator(context);
407             keygen.CreatePublicKey(out PublicKey publicKey);
408             keygen.CreateRelinKeys(out RelinKeys relinKeys);
409 
410             Encryptor encryptor = new Encryptor(context, publicKey);
411             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
412             Evaluator evaluator = new Evaluator(context);
413 
414             Ciphertext encrypted = new Ciphertext();
415             Ciphertext encdest = new Ciphertext();
416             Plaintext plain = new Plaintext("2x^2 + 1");
417             Plaintext plaindest = new Plaintext();
418 
419             encryptor.Encrypt(new Plaintext("3x^2 + 2"), encrypted);
420             evaluator.MultiplyPlain(encrypted, plain, encdest);
421             decryptor.Decrypt(encdest, plaindest);
422 
423             // {6x^4 + 7x^2 + 2}
424             Assert.AreEqual(5ul, plaindest.CoeffCount);
425             Assert.AreEqual(2ul, plaindest[0]);
426             Assert.AreEqual(0ul, plaindest[1]);
427             Assert.AreEqual(7ul, plaindest[2]);
428             Assert.AreEqual(0ul, plaindest[3]);
429             Assert.AreEqual(6ul, plaindest[4]);
430 
431             encryptor.Encrypt(new Plaintext("4x^1 + 3"), encrypted);
432             plain.Set("2x^2 + 1");
433             evaluator.MultiplyPlainInplace(encrypted, plain);
434             decryptor.Decrypt(encrypted, plaindest);
435 
436             // {8x^3 + 6x^2 + 4x^1 + 3}
437             Assert.AreEqual(4ul, plaindest.CoeffCount);
438             Assert.AreEqual(3ul, plaindest[0]);
439             Assert.AreEqual(4ul, plaindest[1]);
440             Assert.AreEqual(6ul, plaindest[2]);
441             Assert.AreEqual(8ul, plaindest[3]);
442 
443             encryptor.Encrypt(new Plaintext("4x^1 + 3"), encrypted);
444             plain.Set("3x^5");
445             evaluator.MultiplyPlainInplace(encrypted, plain);
446             decryptor.Decrypt(encrypted, plaindest);
447 
448             // {Cx^6 + 9x^5}
449             Assert.AreEqual(7ul, plaindest.CoeffCount);
450             Assert.AreEqual(2ul, plaindest.NonZeroCoeffCount);
451             Assert.AreEqual(0ul, plaindest[0]);
452             Assert.AreEqual(0ul, plaindest[1]);
453             Assert.AreEqual(0ul, plaindest[2]);
454             Assert.AreEqual(0ul, plaindest[3]);
455             Assert.AreEqual(0ul, plaindest[4]);
456             Assert.AreEqual(9ul, plaindest[5]);
457             Assert.AreEqual(12ul, plaindest[6]);
458 
459             Utilities.AssertThrows<ArgumentException>(() =>
460             {
461                 // Uninitialized pool
462                 MemoryPoolHandle pool = new MemoryPoolHandle();
463                 evaluator.MultiplyPlain(encrypted, plain, encdest, pool);
464             });
465         }
466 
467         [TestMethod]
SquareTest()468         public void SquareTest()
469         {
470             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
471             {
472                 PolyModulusDegree = 128,
473                 PlainModulus = new Modulus(1 << 6),
474                 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 })
475             };
476             SEALContext context = new SEALContext(parms,
477                 expandModChain: false,
478                 secLevel: SecLevelType.None);
479             KeyGenerator keygen = new KeyGenerator(context);
480             keygen.CreatePublicKey(out PublicKey publicKey);
481 
482             Encryptor encryptor = new Encryptor(context, publicKey);
483             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
484             Evaluator evaluator = new Evaluator(context);
485 
486             Ciphertext encrypted = new Ciphertext();
487             Ciphertext encdest = new Ciphertext();
488             Plaintext plain = new Plaintext("2x^2 + 3x^1 + 4");
489             Plaintext plaindest = new Plaintext();
490 
491             encryptor.Encrypt(plain, encrypted);
492             evaluator.Square(encrypted, encdest);
493             decryptor.Decrypt(encdest, plaindest);
494 
495             // {4x^4 + Cx^3 + 19x^2 + 18x^1 + 10}
496             Assert.AreEqual(5ul, plaindest.CoeffCount);
497             Assert.AreEqual(16ul, plaindest[0]);
498             Assert.AreEqual(24ul, plaindest[1]);
499             Assert.AreEqual(25ul, plaindest[2]);
500             Assert.AreEqual(12ul, plaindest[3]);
501             Assert.AreEqual(4ul, plaindest[4]);
502 
503             encryptor.Encrypt(new Plaintext("3x^1 + 2"), encrypted);
504             evaluator.SquareInplace(encrypted);
505             decryptor.Decrypt(encrypted, plaindest);
506 
507             // {9x^2 + Cx^1 + 4}
508             Assert.AreEqual(3ul, plaindest.CoeffCount);
509             Assert.AreEqual(4ul, plaindest[0]);
510             Assert.AreEqual(12ul, plaindest[1]);
511             Assert.AreEqual(9ul, plaindest[2]);
512         }
513 
514         [TestMethod]
ExponentiateTest()515         public void ExponentiateTest()
516         {
517             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
518             {
519                 PolyModulusDegree = 128,
520                 PlainModulus = new Modulus(1 << 6),
521                 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 })
522             };
523             SEALContext context = new SEALContext(parms,
524                 expandModChain: false,
525                 secLevel: SecLevelType.None);
526             KeyGenerator keygen = new KeyGenerator(context);
527             keygen.CreatePublicKey(out PublicKey publicKey);
528             keygen.CreateRelinKeys(out RelinKeys relinKeys);
529 
530             Encryptor encryptor = new Encryptor(context, publicKey);
531             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
532             Evaluator evaluator = new Evaluator(context);
533 
534             Ciphertext encrypted = new Ciphertext();
535             Ciphertext encdest = new Ciphertext();
536             Plaintext plain = new Plaintext();
537 
538             encryptor.Encrypt(new Plaintext("2x^2 + 1"), encrypted);
539             evaluator.Exponentiate(encrypted, 3, relinKeys, encdest);
540             decryptor.Decrypt(encdest, plain);
541 
542             // {8x^6 + Cx^4 + 6x^2 + 1}
543             Assert.AreEqual(7ul, plain.CoeffCount);
544             Assert.AreEqual(1ul, plain[0]);
545             Assert.AreEqual(0ul, plain[1]);
546             Assert.AreEqual(6ul, plain[2]);
547             Assert.AreEqual(0ul, plain[3]);
548             Assert.AreEqual(12ul, plain[4]);
549             Assert.AreEqual(0ul, plain[5]);
550             Assert.AreEqual(8ul, plain[6]);
551 
552             encryptor.Encrypt(new Plaintext("3x^3 + 2"), encrypted);
553             evaluator.ExponentiateInplace(encrypted, 4, relinKeys);
554             decryptor.Decrypt(encrypted, plain);
555 
556             // {11x^12 + 18x^9 + 18x^6 + 20x^3 + 10}
557             Assert.AreEqual(13ul, plain.CoeffCount);
558             Assert.AreEqual(16ul, plain[0]);
559             Assert.AreEqual(0ul, plain[1]);
560             Assert.AreEqual(0ul, plain[2]);
561             Assert.AreEqual(32ul, plain[3]);
562             Assert.AreEqual(0ul, plain[4]);
563             Assert.AreEqual(0ul, plain[5]);
564             Assert.AreEqual(24ul, plain[6]);
565             Assert.AreEqual(0ul, plain[7]);
566             Assert.AreEqual(0ul, plain[8]);
567             Assert.AreEqual(24ul, plain[9]);
568             Assert.AreEqual(0ul, plain[10]);
569             Assert.AreEqual(0ul, plain[11]);
570             Assert.AreEqual(17ul, plain[12]);
571         }
572 
573         [TestMethod]
ApplyGaloisTest()574         public void ApplyGaloisTest()
575         {
576             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
577             {
578                 PolyModulusDegree = 8,
579                 PlainModulus = new Modulus(257),
580                 CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 })
581             };
582             SEALContext context = new SEALContext(parms,
583                 expandModChain: false,
584                 secLevel: SecLevelType.None);
585             KeyGenerator keygen = new KeyGenerator(context);
586             keygen.CreatePublicKey(out PublicKey publicKey);
587             keygen.CreateGaloisKeys(galoisElts: new uint[] { 1u, 3u, 5u, 15u }, out GaloisKeys galoisKeys);
588 
589             Encryptor encryptor = new Encryptor(context, publicKey);
590             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
591             Evaluator evaluator = new Evaluator(context);
592 
593             Plaintext plain = new Plaintext("1");
594             Plaintext plaindest = new Plaintext();
595             Ciphertext encrypted = new Ciphertext();
596             Ciphertext encdest = new Ciphertext();
597 
598             encryptor.Encrypt(plain, encrypted);
599             evaluator.ApplyGalois(encrypted, galoisElt: 1, galoisKeys: galoisKeys, destination: encdest);
600             decryptor.Decrypt(encdest, plaindest);
601 
602             Assert.AreEqual(1ul, plaindest.CoeffCount);
603             Assert.AreEqual(1ul, plaindest[0]);
604 
605             plain.Set("1x^1");
606             encryptor.Encrypt(plain, encrypted);
607             evaluator.ApplyGalois(encrypted, galoisElt: 1, galoisKeys: galoisKeys, destination: encdest);
608             decryptor.Decrypt(encdest, plaindest);
609 
610             // {1x^1}
611             Assert.AreEqual(2ul, plaindest.CoeffCount);
612             Assert.AreEqual(0ul, plaindest[0]);
613             Assert.AreEqual(1ul, plaindest[1]);
614 
615             evaluator.ApplyGalois(encdest, galoisElt: 3, galoisKeys: galoisKeys, destination: encrypted);
616             decryptor.Decrypt(encrypted, plaindest);
617 
618             // {1x^3}
619             Assert.AreEqual(4ul, plaindest.CoeffCount);
620             Assert.AreEqual(0ul, plaindest[0]);
621             Assert.AreEqual(0ul, plaindest[1]);
622             Assert.AreEqual(0ul, plaindest[2]);
623             Assert.AreEqual(1ul, plaindest[3]);
624 
625             evaluator.ApplyGalois(encrypted, galoisElt: 5, galoisKeys: galoisKeys, destination: encdest);
626             decryptor.Decrypt(encdest, plaindest);
627 
628             // {100x^7}
629             Assert.AreEqual(8ul, plaindest.CoeffCount);
630             Assert.AreEqual(0ul, plaindest[0]);
631             Assert.AreEqual(0ul, plaindest[1]);
632             Assert.AreEqual(0ul, plaindest[2]);
633             Assert.AreEqual(0ul, plaindest[3]);
634             Assert.AreEqual(0ul, plaindest[4]);
635             Assert.AreEqual(0ul, plaindest[5]);
636             Assert.AreEqual(0ul, plaindest[6]);
637             Assert.AreEqual(256ul, plaindest[7]);
638 
639             plain.Set("1x^2");
640             encryptor.Encrypt(plain, encrypted);
641             evaluator.ApplyGaloisInplace(encrypted, 1, galoisKeys);
642             decryptor.Decrypt(encrypted, plaindest);
643 
644             // {1x^2}
645             Assert.AreEqual(3ul, plaindest.CoeffCount);
646             Assert.AreEqual(0ul, plaindest[0]);
647             Assert.AreEqual(0ul, plaindest[1]);
648             Assert.AreEqual(1ul, plaindest[2]);
649 
650             evaluator.ApplyGaloisInplace(encrypted, 3, galoisKeys);
651             decryptor.Decrypt(encrypted, plaindest);
652 
653             // {1x^6}
654             Assert.AreEqual(7ul, plaindest.CoeffCount);
655             Assert.AreEqual(0ul, plaindest[0]);
656             Assert.AreEqual(0ul, plaindest[1]);
657             Assert.AreEqual(0ul, plaindest[2]);
658             Assert.AreEqual(0ul, plaindest[3]);
659             Assert.AreEqual(0ul, plaindest[4]);
660             Assert.AreEqual(0ul, plaindest[5]);
661             Assert.AreEqual(1ul, plaindest[6]);
662 
663             evaluator.ApplyGaloisInplace(encrypted, 5, galoisKeys);
664             decryptor.Decrypt(encrypted, plaindest);
665 
666             // {100x^6}
667             Assert.AreEqual(7ul, plaindest.CoeffCount);
668             Assert.AreEqual(0ul, plaindest[0]);
669             Assert.AreEqual(0ul, plaindest[1]);
670             Assert.AreEqual(0ul, plaindest[2]);
671             Assert.AreEqual(0ul, plaindest[3]);
672             Assert.AreEqual(0ul, plaindest[4]);
673             Assert.AreEqual(0ul, plaindest[5]);
674             Assert.AreEqual(256ul, plaindest[6]);
675         }
676 
677         [TestMethod]
TransformPlainToNTTTest()678         public void TransformPlainToNTTTest()
679         {
680             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
681             {
682                 PolyModulusDegree = 128,
683                 PlainModulus = new Modulus(1 << 6),
684                 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 })
685             };
686             SEALContext context = new SEALContext(parms,
687                 expandModChain: false,
688                 secLevel: SecLevelType.None);
689             Evaluator evaluator = new Evaluator(context);
690 
691             Plaintext plain = new Plaintext("0");
692             Plaintext plaindest = new Plaintext();
693             Assert.IsFalse(plain.IsNTTForm);
694 
695             evaluator.TransformToNTT(plain, context.FirstParmsId, plaindest);
696             Assert.IsTrue(plaindest.IsZero);
697             Assert.IsTrue(plaindest.IsNTTForm);
698             Assert.IsTrue(plaindest.ParmsId == context.FirstParmsId);
699 
700             plain = new Plaintext("1");
701             Assert.IsFalse(plain.IsNTTForm);
702 
703             evaluator.TransformToNTTInplace(plain, context.FirstParmsId);
704             Assert.IsTrue(plain.IsNTTForm);
705 
706             for (ulong i = 0; i < 256; i++)
707             {
708                 Assert.AreEqual(1ul, plain[i]);
709             }
710         }
711 
712         [TestMethod]
TransformEncryptedToNTTTest()713         public void TransformEncryptedToNTTTest()
714         {
715             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
716             {
717                 PolyModulusDegree = 128,
718                 PlainModulus = new Modulus(1 << 6),
719                 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40 })
720             };
721             SEALContext context = new SEALContext(parms,
722                 expandModChain: false,
723                 secLevel: SecLevelType.None);
724             KeyGenerator keygen = new KeyGenerator(context);
725             keygen.CreatePublicKey(out PublicKey publicKey);
726 
727             Encryptor encryptor = new Encryptor(context, publicKey);
728             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
729             Evaluator evaluator = new Evaluator(context);
730 
731             Ciphertext encrypted = new Ciphertext();
732             Ciphertext encdest = new Ciphertext();
733             Ciphertext encdest2 = new Ciphertext();
734             Plaintext plaindest = new Plaintext();
735 
736             encryptor.Encrypt(new Plaintext("0"), encrypted);
737             Assert.IsFalse(encrypted.IsNTTForm);
738 
739             evaluator.TransformToNTT(encrypted, encdest);
740             Assert.IsTrue(encdest.IsNTTForm);
741 
742             evaluator.TransformFromNTT(encdest, encdest2);
743             Assert.IsFalse(encdest2.IsNTTForm);
744 
745             decryptor.Decrypt(encdest2, plaindest);
746             Assert.AreEqual(1ul, plaindest.CoeffCount);
747             Assert.AreEqual(0ul, plaindest[0]);
748             Assert.AreEqual(context.FirstParmsId, encdest2.ParmsId);
749 
750             encryptor.Encrypt(new Plaintext("1"), encrypted);
751             Assert.IsFalse(encrypted.IsNTTForm);
752 
753             evaluator.TransformToNTTInplace(encrypted);
754             Assert.IsTrue(encrypted.IsNTTForm);
755 
756             evaluator.TransformFromNTTInplace(encrypted);
757             Assert.IsFalse(encrypted.IsNTTForm);
758 
759             decryptor.Decrypt(encrypted, plaindest);
760 
761             Assert.AreEqual(1ul, plaindest.CoeffCount);
762             Assert.AreEqual(1ul, plaindest[0]);
763             Assert.AreEqual(context.FirstParmsId, encrypted.ParmsId);
764         }
765 
766         [TestMethod]
ModSwitchToNextTest()767         public void ModSwitchToNextTest()
768         {
769             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
770             {
771                 PolyModulusDegree = 128,
772                 PlainModulus = new Modulus(1 << 6),
773                 CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30 })
774             };
775             SEALContext context = new SEALContext(parms,
776                 expandModChain: true,
777                 secLevel: SecLevelType.None);
778             KeyGenerator keygen = new KeyGenerator(context);
779             keygen.CreatePublicKey(out PublicKey publicKey);
780 
781             Encryptor encryptor = new Encryptor(context, publicKey);
782             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
783             Evaluator evaluator = new Evaluator(context);
784 
785             Ciphertext encrypted = new Ciphertext(context);
786             Ciphertext encdest = new Ciphertext();
787             Plaintext plain = new Plaintext();
788 
789             plain.Set("0");
790             encryptor.Encrypt(plain, encrypted);
791             evaluator.ModSwitchToNext(encrypted, encdest);
792             decryptor.Decrypt(encdest, plain);
793 
794             Assert.AreEqual(1ul, plain.CoeffCount);
795             Assert.AreEqual(0ul, plain[0]);
796 
797             plain.Set("1");
798             encryptor.Encrypt(plain, encrypted);
799             evaluator.ModSwitchToNextInplace(encrypted);
800             decryptor.Decrypt(encrypted, plain);
801 
802             Assert.AreEqual(1ul, plain.CoeffCount);
803             Assert.AreEqual(1ul, plain[0]);
804         }
805 
806         [TestMethod]
ModSwitchToTest()807         public void ModSwitchToTest()
808         {
809             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
810             {
811                 PolyModulusDegree = 128,
812                 PlainModulus = new Modulus(1 << 6),
813                 CoeffModulus = CoeffModulus.Create(128, new int[] { 30, 30, 30, 30 })
814             };
815             SEALContext context = new SEALContext(parms,
816                 expandModChain: true,
817                 secLevel: SecLevelType.None);
818             KeyGenerator keygen = new KeyGenerator(context);
819             keygen.CreatePublicKey(out PublicKey publicKey);
820 
821             Encryptor encryptor = new Encryptor(context, publicKey);
822             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
823             Evaluator evaluator = new Evaluator(context);
824 
825             Ciphertext encrypted = new Ciphertext(context);
826             Ciphertext encdest = new Ciphertext(context);
827             Plaintext plaindest = new Plaintext();
828 
829             encryptor.Encrypt(new Plaintext("1"), encrypted);
830             ParmsId destParmsId = context.FirstContextData.NextContextData
831                 .NextContextData.ParmsId;
832 
833             evaluator.ModSwitchTo(encrypted, context.FirstParmsId, encdest);
834             decryptor.Decrypt(encdest, plaindest);
835 
836             Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId);
837             Assert.IsTrue(encdest.ParmsId == context.FirstParmsId);
838             Assert.AreEqual(1ul, plaindest.CoeffCount);
839             Assert.AreEqual(1ul, plaindest[0]);
840 
841             evaluator.ModSwitchTo(encrypted, destParmsId, encdest);
842             decryptor.Decrypt(encdest, plaindest);
843 
844             Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId);
845             Assert.IsTrue(encdest.ParmsId == destParmsId);
846             Assert.AreEqual(1ul, plaindest.CoeffCount);
847             Assert.AreEqual(1ul, plaindest[0]);
848 
849             encryptor.Encrypt(new Plaintext("3x^2 + 2x^1 + 1"), encrypted);
850             evaluator.ModSwitchToInplace(encrypted, context.FirstParmsId);
851             decryptor.Decrypt(encrypted, plaindest);
852 
853             Assert.IsTrue(encrypted.ParmsId == context.FirstParmsId);
854             Assert.AreEqual(3ul, plaindest.CoeffCount);
855             Assert.AreEqual(1ul, plaindest[0]);
856             Assert.AreEqual(2ul, plaindest[1]);
857             Assert.AreEqual(3ul, plaindest[2]);
858 
859             evaluator.ModSwitchToInplace(encrypted, destParmsId);
860             decryptor.Decrypt(encrypted, plaindest);
861 
862             Assert.IsTrue(encrypted.ParmsId == destParmsId);
863             Assert.AreEqual(3ul, plaindest.CoeffCount);
864             Assert.AreEqual(1ul, plaindest[0]);
865             Assert.AreEqual(2ul, plaindest[1]);
866             Assert.AreEqual(3ul, plaindest[2]);
867         }
868 
869         [TestMethod]
ModSwitchToPlainTest()870         public void ModSwitchToPlainTest()
871         {
872             EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
873             {
874                 PolyModulusDegree = 1024,
875                 CoeffModulus = CoeffModulus.Create(1024, new int[] { 40, 40, 40, 40, 40 })
876             };
877 
878             SEALContext context = new SEALContext(parms,
879                 expandModChain: true,
880                 secLevel: SecLevelType.None);
881             CKKSEncoder encoder = new CKKSEncoder(context);
882             KeyGenerator keygen = new KeyGenerator(context);
883             SecretKey secretKey = keygen.SecretKey;
884             keygen.CreatePublicKey(out PublicKey publicKey);
885             keygen.CreateRelinKeys(out RelinKeys relinKeys);
886 
887             Encryptor encryptor = new Encryptor(context, publicKey);
888             Evaluator evaluator = new Evaluator(context);
889             Decryptor decryptor = new Decryptor(context, secretKey);
890 
891             double scale = parms.CoeffModulus.Last().Value;
892             Plaintext coeff1 = new Plaintext();
893             Plaintext coeff2 = new Plaintext();
894             Plaintext coeff3 = new Plaintext();
895             encoder.Encode(2.0, scale, coeff1);
896             encoder.Encode(3.0, scale, coeff2);
897             encoder.Encode(1.0, scale, coeff3);
898 
899             Ciphertext encX1 = new Ciphertext();
900             Ciphertext encX2 = new Ciphertext();
901             Ciphertext encX3 = new Ciphertext();
902             encryptor.Encrypt(coeff1, encX1);
903             evaluator.Square(encX1, encX3);
904             evaluator.MultiplyPlain(encX1, coeff2, encX2);
905             evaluator.RelinearizeInplace(encX3, relinKeys);
906             evaluator.RescaleToNextInplace(encX3);
907             evaluator.RelinearizeInplace(encX2, relinKeys);
908             evaluator.RescaleToInplace(encX2, encX3.ParmsId);
909 
910             evaluator.ModSwitchToInplace(coeff3, encX3.ParmsId);
911             evaluator.ModSwitchToNextInplace(coeff2);
912 
913             evaluator.MultiplyPlainInplace(encX3, coeff3);
914 
915             Plaintext result = new Plaintext();
916             decryptor.Decrypt(encX3, result);
917             Assert.IsNotNull(result);
918 
919             List<double> destination = new List<double>();
920             encoder.Decode(result, destination);
921 
922             Assert.IsNotNull(destination);
923             foreach(double val in destination)
924             {
925                 Assert.AreEqual(4.0, val, delta: 0.001);
926             }
927 
928             encoder.Decode(coeff2, destination);
929 
930             foreach(double val in destination)
931             {
932                 Assert.AreEqual(3.0, val, delta: 0.001);
933             }
934 
935             decryptor.Decrypt(encX2, result);
936             encoder.Decode(result, destination);
937 
938             foreach (double val in destination)
939             {
940                 Assert.AreEqual(6.0, val, delta: 0.001);
941             }
942         }
943 
944         [TestMethod]
RotateMatrixTest()945         public void RotateMatrixTest()
946         {
947             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
948             {
949                 PolyModulusDegree = 8,
950                 PlainModulus = new Modulus(257),
951                 CoeffModulus = CoeffModulus.Create(8, new int[] { 40, 40 })
952             };
953             SEALContext context = new SEALContext(parms,
954                 expandModChain: false,
955                 secLevel: SecLevelType.None);
956             KeyGenerator keygen = new KeyGenerator(context);
957             keygen.CreateGaloisKeys(out GaloisKeys galoisKeys);
958             keygen.CreatePublicKey(out PublicKey publicKey);
959 
960             Encryptor encryptor = new Encryptor(context, publicKey);
961             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
962             Evaluator evaluator = new Evaluator(context);
963             BatchEncoder encoder = new BatchEncoder(context);
964 
965             Plaintext plain = new Plaintext();
966             List<ulong> vec = new List<ulong>
967             {
968                 1, 2, 3, 4,
969                 5, 6, 7, 8
970             };
971 
972             encoder.Encode(vec, plain);
973 
974             Ciphertext encrypted = new Ciphertext();
975             Ciphertext encdest = new Ciphertext();
976             Plaintext plaindest = new Plaintext();
977 
978             encryptor.Encrypt(plain, encrypted);
979             evaluator.RotateColumns(encrypted, galoisKeys, encdest);
980             decryptor.Decrypt(encdest, plaindest);
981             encoder.Decode(plaindest, vec);
982 
983             Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
984             {
985                 5, 6, 7, 8,
986                 1, 2, 3, 4
987             }));
988 
989             evaluator.RotateRows(encdest, -1, galoisKeys, encrypted);
990             decryptor.Decrypt(encrypted, plaindest);
991             encoder.Decode(plaindest, vec);
992 
993             Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
994             {
995                 8, 5, 6, 7,
996                 4, 1, 2, 3
997             }));
998 
999             evaluator.RotateRowsInplace(encrypted, 2, galoisKeys);
1000             decryptor.Decrypt(encrypted, plaindest);
1001             encoder.Decode(plaindest, vec);
1002 
1003             Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
1004             {
1005                 6, 7, 8, 5,
1006                 2, 3, 4, 1
1007             }));
1008 
1009             evaluator.RotateColumnsInplace(encrypted, galoisKeys);
1010             decryptor.Decrypt(encrypted, plaindest);
1011             encoder.Decode(plaindest, vec);
1012 
1013             Assert.IsTrue(AreCollectionsEqual(vec, new List<ulong>
1014             {
1015                 2, 3, 4, 1,
1016                 6, 7, 8, 5
1017             }));
1018         }
1019 
1020         [TestMethod]
RelinearizeTest()1021         public void RelinearizeTest()
1022         {
1023             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
1024             {
1025                 PolyModulusDegree = 128,
1026                 PlainModulus = new Modulus(1 << 6),
1027                 CoeffModulus = CoeffModulus.Create(128, new int[] { 40, 40, 40 })
1028             };
1029             SEALContext context = new SEALContext(parms,
1030                 expandModChain: false,
1031                 secLevel: SecLevelType.None);
1032             KeyGenerator keygen = new KeyGenerator(context);
1033             keygen.CreateRelinKeys(out RelinKeys relinKeys);
1034             keygen.CreatePublicKey(out PublicKey publicKey);
1035 
1036             Encryptor encryptor = new Encryptor(context, publicKey);
1037             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
1038             Evaluator evaluator = new Evaluator(context);
1039 
1040             Ciphertext encrypted1 = new Ciphertext(context);
1041             Ciphertext encrypted2 = new Ciphertext(context);
1042             Plaintext plain1 = new Plaintext();
1043             Plaintext plain2 = new Plaintext();
1044 
1045             plain1.Set(0);
1046             encryptor.Encrypt(plain1, encrypted1);
1047             evaluator.SquareInplace(encrypted1);
1048             evaluator.RelinearizeInplace(encrypted1, relinKeys);
1049             decryptor.Decrypt(encrypted1, plain2);
1050 
1051             Assert.AreEqual(1ul, plain2.CoeffCount);
1052             Assert.AreEqual(0ul, plain2[0]);
1053 
1054             plain1.Set("1x^10 + 2");
1055             encryptor.Encrypt(plain1, encrypted1);
1056             evaluator.SquareInplace(encrypted1);
1057             evaluator.RelinearizeInplace(encrypted1, relinKeys);
1058             evaluator.SquareInplace(encrypted1);
1059             evaluator.Relinearize(encrypted1, relinKeys, encrypted2);
1060             decryptor.Decrypt(encrypted2, plain2);
1061 
1062             // {1x^40 + 8x^30 + 18x^20 + 20x^10 + 10}
1063             Assert.AreEqual(41ul, plain2.CoeffCount);
1064             Assert.AreEqual(16ul, plain2[0]);
1065             Assert.AreEqual(32ul, plain2[10]);
1066             Assert.AreEqual(24ul, plain2[20]);
1067             Assert.AreEqual(8ul,  plain2[30]);
1068             Assert.AreEqual(1ul,  plain2[40]);
1069         }
1070 
1071         [TestMethod]
RotateVectorTest()1072         public void RotateVectorTest()
1073         {
1074             int slotSize = 4;
1075             EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
1076             {
1077                 PolyModulusDegree = 2 * (ulong)slotSize,
1078                 CoeffModulus = CoeffModulus.Create(2 * (ulong)slotSize, new int[] { 40, 40, 40, 40 })
1079             };
1080             SEALContext context = new SEALContext(parms,
1081                 expandModChain: false,
1082                 secLevel: SecLevelType.None);
1083             KeyGenerator keygen = new KeyGenerator(context);
1084             keygen.CreateGaloisKeys(out GaloisKeys galoisKeys);
1085             keygen.CreatePublicKey(out PublicKey publicKey);
1086 
1087             Encryptor encryptor = new Encryptor(context, publicKey);
1088             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
1089             Evaluator evaluator = new Evaluator(context);
1090             CKKSEncoder encoder = new CKKSEncoder(context);
1091 
1092             const double delta = 1ul << 30;
1093 
1094             Ciphertext encrypted = new Ciphertext();
1095             Plaintext plain = new Plaintext();
1096 
1097             List<Complex> input = new List<Complex>
1098             {
1099                 new Complex(1, 1),
1100                 new Complex(2, 2),
1101                 new Complex(3, 3),
1102                 new Complex(4, 4)
1103             };
1104 
1105             List<Complex> output = new List<Complex>();
1106 
1107             encoder.Encode(input, context.FirstParmsId, delta, plain);
1108 
1109             int shift = 1;
1110             encryptor.Encrypt(plain, encrypted);
1111             evaluator.RotateVectorInplace(encrypted, shift, galoisKeys);
1112             decryptor.Decrypt(encrypted, plain);
1113             encoder.Decode(plain, output);
1114 
1115             for (int i = 0; i < slotSize; i++)
1116             {
1117                 Assert.AreEqual(input[(i + shift) % slotSize].Real, Math.Round(output[i].Real), delta: 0.1);
1118                 Assert.AreEqual(input[(i + shift) % slotSize].Imaginary, Math.Round(output[i].Imaginary), delta: 0.1);
1119             }
1120 
1121             encoder.Encode(input, context.FirstParmsId, delta, plain);
1122             shift = 3;
1123             encryptor.Encrypt(plain, encrypted);
1124             evaluator.RotateVectorInplace(encrypted, shift, galoisKeys);
1125             decryptor.Decrypt(encrypted, plain);
1126             encoder.Decode(plain, output);
1127 
1128             for (int i = 0; i < slotSize; i++)
1129             {
1130                 Assert.AreEqual(input[(i + shift) % slotSize].Real, Math.Round(output[i].Real), delta: 0.1);
1131                 Assert.AreEqual(input[(i + shift) % slotSize].Imaginary, Math.Round(output[i].Imaginary), delta: 0.1);
1132             }
1133         }
1134 
1135         [TestMethod]
ComplexConjugateTest()1136         public void ComplexConjugateTest()
1137         {
1138             int slotSize = 4;
1139             EncryptionParameters parms = new EncryptionParameters(SchemeType.CKKS)
1140             {
1141                 PolyModulusDegree = 2 * (ulong)slotSize,
1142                 CoeffModulus = CoeffModulus.Create(2 * (ulong)slotSize, new int[] { 40, 40, 40, 40 })
1143             };
1144             SEALContext context = new SEALContext(parms,
1145                 expandModChain: false,
1146                 secLevel: SecLevelType.None);
1147             KeyGenerator keygen = new KeyGenerator(context);
1148             keygen.CreateGaloisKeys(out GaloisKeys galoisKeys);
1149             keygen.CreatePublicKey(out PublicKey publicKey);
1150 
1151             Encryptor encryptor = new Encryptor(context, publicKey);
1152             Decryptor decryptor = new Decryptor(context, keygen.SecretKey);
1153             Evaluator evaluator = new Evaluator(context);
1154             CKKSEncoder encoder = new CKKSEncoder(context);
1155 
1156             const double delta = 1ul << 30;
1157 
1158             Ciphertext encrypted = new Ciphertext();
1159             Plaintext plain = new Plaintext();
1160 
1161             List<Complex> input = new List<Complex>
1162             {
1163                 new Complex(1, 1),
1164                 new Complex(2, 2),
1165                 new Complex(3, 3),
1166                 new Complex(4, 4)
1167             };
1168 
1169             List<Complex> output = new List<Complex>();
1170 
1171             encoder.Encode(input, context.FirstParmsId, delta, plain);
1172             encryptor.Encrypt(plain, encrypted);
1173             evaluator.ComplexConjugateInplace(encrypted, galoisKeys);
1174             decryptor.Decrypt(encrypted, plain);
1175             encoder.Decode(plain, output);
1176 
1177             for (int i = 0; i < slotSize; i++)
1178             {
1179                 Assert.AreEqual(input[i].Real, output[i].Real, delta: 0.1);
1180                 Assert.AreEqual(-input[i].Imaginary, output[i].Imaginary, delta: 0.1);
1181             }
1182         }
1183 
1184         [TestMethod]
ExceptionsTest()1185         public void ExceptionsTest()
1186         {
1187             EncryptionParameters parms = new EncryptionParameters(SchemeType.BFV)
1188             {
1189                 PolyModulusDegree = 64,
1190                 PlainModulus = new Modulus(65537ul),
1191                 CoeffModulus = CoeffModulus.Create(64, new int[] { 40, 40 })
1192             };
1193             SEALContext context = new SEALContext(parms,
1194                 expandModChain: false,
1195                 secLevel: SecLevelType.None);
1196 
1197             Evaluator evaluator = null;
1198             Utilities.AssertThrows<ArgumentNullException>(() => evaluator = new Evaluator(null));
1199             evaluator = new Evaluator(context);
1200 
1201             KeyGenerator keygen = new KeyGenerator(context);
1202             keygen.CreateGaloisKeys(out GaloisKeys galoisKeys);
1203             keygen.CreateRelinKeys(out RelinKeys relinKeys);
1204 
1205             Ciphertext encrypted1 = new Ciphertext();
1206             Ciphertext encrypted2 = new Ciphertext();
1207             Ciphertext encrypted3 = new Ciphertext();
1208             Plaintext plain1 = new Plaintext();
1209             Plaintext plain2 = new Plaintext();
1210             List<Ciphertext> encrypteds = new List<Ciphertext>();
1211 
1212             MemoryPoolHandle pool = MemoryManager.GetPool(MMProfOpt.ForceGlobal);
1213 
1214             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(null, encrypted2, encrypted3));
1215             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(encrypted1, null, encrypted3));
1216             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Add(encrypted1, encrypted2, null));
1217             Utilities.AssertThrows<ArgumentException>(() => evaluator.Add(encrypted1, encrypted2, encrypted3));
1218 
1219             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddInplace(encrypted1, null));
1220             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddInplace(null, encrypted2));
1221 
1222             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddMany(encrypteds, null));
1223             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddMany(null, encrypted2));
1224 
1225             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(encrypted1, plain1, null));
1226             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(encrypted1, null, encrypted2));
1227             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlain(null, plain1, encrypted2));
1228             Utilities.AssertThrows<ArgumentException>(() => evaluator.AddPlain(encrypted1, plain1, encrypted2));
1229 
1230             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.AddPlainInplace(encrypted1, null));
1231 
1232             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(encrypted1, 1, galoisKeys, null));
1233             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(encrypted1, 1, null, encrypted2));
1234             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGalois(null, 1, galoisKeys, encrypted2));
1235             Utilities.AssertThrows<ArgumentException>(() => evaluator.ApplyGalois(encrypted1, 1, galoisKeys, encrypted2, pool));
1236 
1237             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGaloisInplace(encrypted1, 1, null));
1238             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ApplyGaloisInplace(null, 1, galoisKeys));
1239 
1240             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(encrypted1, galoisKeys, null));
1241             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(encrypted1, null, encrypted2));
1242             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugate(null, galoisKeys, encrypted2));
1243 
1244             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugateInplace(encrypted1, null));
1245             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ComplexConjugateInplace(null, galoisKeys));
1246 
1247             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(encrypted1, 2, relinKeys, null));
1248             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(encrypted1, 2, null, encrypted2));
1249             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Exponentiate(null, 2, relinKeys, encrypted2));
1250 
1251             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ExponentiateInplace(encrypted1, 2, null));
1252             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ExponentiateInplace(null, 2, relinKeys));
1253 
1254             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(plain1, ParmsId.Zero, null));
1255             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(plain1, null, plain2));
1256             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(null, ParmsId.Zero, plain2));
1257 
1258             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(encrypted1, ParmsId.Zero, null));
1259             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(encrypted1, null, encrypted2));
1260             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchTo(null, ParmsId.Zero, encrypted2));
1261             Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchTo(encrypted1, ParmsId.Zero, encrypted2, pool));
1262 
1263             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(encrypted1, null));
1264             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(encrypted: null, parmsId: ParmsId.Zero));
1265             Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToInplace(encrypted1, ParmsId.Zero, pool));
1266 
1267             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(plain1, null));
1268             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToInplace(plain: null, parmsId: ParmsId.Zero));
1269 
1270             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(plain1, null));
1271             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(null, plain2));
1272 
1273             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNextInplace(null));
1274 
1275             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(encrypted1, null));
1276             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNext(null, encrypted2));
1277             Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToNext(encrypted1, encrypted2, pool));
1278 
1279             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.ModSwitchToNextInplace(encrypted: null));
1280             Utilities.AssertThrows<ArgumentException>(() => evaluator.ModSwitchToNextInplace(encrypted1, pool));
1281 
1282             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(encrypted1, encrypted2, null));
1283             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(encrypted1, null, encrypted3));
1284             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Multiply(null, encrypted2, encrypted3));
1285             Utilities.AssertThrows<ArgumentException>(() => evaluator.Multiply(encrypted1, encrypted2, encrypted3, pool));
1286 
1287             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyInplace(encrypted1, null));
1288             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyInplace(null, encrypted2));
1289             Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyInplace(encrypted1, encrypted2, pool));
1290 
1291             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(encrypteds, relinKeys, null));
1292             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(encrypteds, null, encrypted2));
1293             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyMany(null, relinKeys, encrypted2));
1294             Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyMany(encrypteds, relinKeys, encrypted2, pool));
1295 
1296             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(encrypted1, plain1, null));
1297             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(encrypted1, null, encrypted2));
1298             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlain(null, plain1, encrypted2));
1299             Utilities.AssertThrows<ArgumentException>(() => evaluator.MultiplyPlain(encrypted1, plain1, encrypted2, pool));
1300 
1301             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlainInplace(encrypted1, null));
1302             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.MultiplyPlainInplace(null, plain1));
1303 
1304             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Negate(encrypted1, null));
1305             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Negate(null, encrypted2));
1306             Utilities.AssertThrows<ArgumentException>(() => evaluator.Negate(encrypted1, encrypted2));
1307 
1308             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.NegateInplace(null));
1309 
1310             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(encrypted1, relinKeys, null));
1311             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(encrypted1, null, encrypted2));
1312             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Relinearize(null, relinKeys, encrypted2));
1313             Utilities.AssertThrows<ArgumentException>(() => evaluator.Relinearize(encrypted1, relinKeys, encrypted2, pool));
1314 
1315             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RelinearizeInplace(encrypted1, null));
1316             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RelinearizeInplace(null, relinKeys));
1317             Utilities.AssertThrows<ArgumentException>(() => evaluator.RelinearizeInplace(encrypted1, relinKeys, pool));
1318 
1319             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(encrypted1, ParmsId.Zero, null));
1320             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(encrypted1, null, encrypted2));
1321             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleTo(null, ParmsId.Zero, encrypted2));
1322             Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleTo(encrypted1, ParmsId.Zero, encrypted2, pool));
1323 
1324             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToInplace(encrypted1, null));
1325             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToInplace(null, ParmsId.Zero));
1326             Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToInplace(encrypted1, ParmsId.Zero, pool));
1327 
1328             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNext(encrypted1, null));
1329             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNext(null, encrypted2));
1330             Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToNext(encrypted1, encrypted2, pool));
1331 
1332             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RescaleToNextInplace(null));
1333             Utilities.AssertThrows<ArgumentException>(() => evaluator.RescaleToNextInplace(encrypted1, pool));
1334 
1335             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(encrypted1, galoisKeys, null));
1336             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(encrypted1, null, encrypted2));
1337             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumns(null, galoisKeys, encrypted2));
1338             Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateColumns(encrypted1, galoisKeys, encrypted2, pool));
1339 
1340             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumnsInplace(encrypted1, null));
1341             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateColumnsInplace(null, galoisKeys));
1342             Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateColumnsInplace(encrypted1, galoisKeys, pool));
1343 
1344             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(encrypted1, 1, galoisKeys, null));
1345             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(encrypted1, 1, null, encrypted2));
1346             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRows(null, 1, galoisKeys, encrypted2));
1347             Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateRows(encrypted1, 1, galoisKeys, encrypted2, pool));
1348 
1349             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRowsInplace(encrypted1, 1, null));
1350             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateRowsInplace(null, 1, galoisKeys));
1351             Utilities.AssertThrows<ArgumentException>(() => evaluator.RotateRowsInplace(encrypted1, 1, galoisKeys, pool));
1352 
1353             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(encrypted1, 1, galoisKeys, null));
1354             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(encrypted1, 1, null, encrypted2));
1355             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVector(null, 1, galoisKeys, encrypted2));
1356 
1357             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVectorInplace(encrypted1, 1, null));
1358             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.RotateVectorInplace(null, 1, galoisKeys));
1359 
1360             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Square(encrypted1, null));
1361             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Square(null, encrypted2));
1362             Utilities.AssertThrows<ArgumentException>(() => evaluator.Square(encrypted1, encrypted2, pool));
1363 
1364             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SquareInplace(null));
1365             Utilities.AssertThrows<ArgumentException>(() => evaluator.SquareInplace(encrypted1, pool));
1366 
1367             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(encrypted1, encrypted2, null));
1368             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(encrypted1, null, encrypted3));
1369             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.Sub(null, encrypted2, encrypted3));
1370             Utilities.AssertThrows<ArgumentException>(() => evaluator.Sub(encrypted1, encrypted2, encrypted3));
1371 
1372             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubInplace(encrypted1, null));
1373             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubInplace(null, encrypted2));
1374 
1375             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(encrypted1, plain1, null));
1376             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(encrypted1, null, encrypted2));
1377             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlain(null, plain1, encrypted2));
1378             Utilities.AssertThrows<ArgumentException>(() => evaluator.SubPlain(encrypted1, plain1, encrypted2));
1379 
1380             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.SubPlainInplace(encrypted1, null));
1381 
1382             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTT(encrypted1, null));
1383             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTT(null, encrypted2));
1384             Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformFromNTT(encrypted1, encrypted2));
1385 
1386             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformFromNTTInplace(null));
1387 
1388             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(encrypted1, null));
1389             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(null, encrypted2));
1390 
1391             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(null));
1392 
1393             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(plain1, ParmsId.Zero, null));
1394             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(plain1, null, plain2));
1395             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTT(null, ParmsId.Zero, plain2));
1396             Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformToNTT(plain1, ParmsId.Zero, plain2, pool));
1397 
1398             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(plain1, null));
1399             Utilities.AssertThrows<ArgumentNullException>(() => evaluator.TransformToNTTInplace(null, ParmsId.Zero));
1400             Utilities.AssertThrows<ArgumentException>(() => evaluator.TransformToNTTInplace(plain1, ParmsId.Zero, pool));
1401         }
1402 
1403         /// <summary>
1404         /// Returns true if the two given collections have equivalent elements, false otherwise
1405         /// </summary>
AreCollectionsEqual(IEnumerable<T> coll1, IEnumerable<T> coll2)1406         private static bool AreCollectionsEqual<T>(IEnumerable<T> coll1, IEnumerable<T> coll2)
1407         {
1408             int size1 = coll1.Count();
1409             int size2 = coll2.Count();
1410 
1411             if (size1 != size2)
1412                 return false;
1413 
1414             IEnumerator<T> en1 = coll1.GetEnumerator();
1415             IEnumerator<T> en2 = coll2.GetEnumerator();
1416 
1417             while (en1.MoveNext() && en2.MoveNext())
1418             {
1419                 if (!en1.Current.Equals(en2.Current))
1420                     return false;
1421             }
1422 
1423             return true;
1424         }
1425     }
1426 }
1427