microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.18.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

library/src/tests/math.rs

1207lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use super::test_expression;
5use core::f64::consts::E;
6use num_bigint::BigInt;
7use qsc::interpret::Value;
8use std::{f64::consts::PI, str::FromStr};
9
10#[test]
11fn check_pi() {
12 test_expression(
13 "Microsoft.Quantum.Math.PI()",
14 &Value::Double(std::f64::consts::PI),
15 );
16}
17
18#[test]
19fn check_e() {
20 test_expression(
21 "Microsoft.Quantum.Math.E()",
22 &Value::Double(std::f64::consts::E),
23 );
24}
25
26#[test]
27fn check_log_of_2() {
28 test_expression(
29 "Microsoft.Quantum.Math.LogOf2()",
30 &Value::Double(std::f64::consts::LN_2),
31 );
32}
33
34//
35// Special numbers in IEEE floating-point representation
36//
37
38#[test]
39fn check_is_nan() {
40 test_expression(
41 "Microsoft.Quantum.Math.IsNaN(0.0 / 0.0)",
42 &Value::Bool(true),
43 );
44 test_expression("Microsoft.Quantum.Math.IsNaN(1.0)", &Value::Bool(false));
45 test_expression(
46 "Microsoft.Quantum.Math.IsNaN(Microsoft.Quantum.Math.ArcSin(2.0))",
47 &Value::Bool(true),
48 );
49}
50
51#[test]
52fn check_is_infinite() {
53 test_expression(
54 "Microsoft.Quantum.Math.IsInfinite(1.0 / 0.0)",
55 &Value::Bool(true),
56 );
57 test_expression(
58 "Microsoft.Quantum.Math.IsInfinite(0.0 / 0.0)",
59 &Value::Bool(false),
60 );
61 test_expression(
62 "Microsoft.Quantum.Math.IsInfinite(-1.0 / 0.0)",
63 &Value::Bool(true),
64 );
65}
66
67//
68// Sign, Abs, Min, Max, etc.
69//
70
71#[test]
72fn check_sign_i() {
73 test_expression("Microsoft.Quantum.Math.SignI(0)", &Value::Int(0));
74 test_expression("Microsoft.Quantum.Math.SignI(1000)", &Value::Int(1));
75 test_expression("Microsoft.Quantum.Math.SignI(-1000)", &Value::Int(-1));
76}
77
78#[test]
79fn check_sign_d() {
80 test_expression("Microsoft.Quantum.Math.SignD(0.0)", &Value::Int(0));
81 test_expression("Microsoft.Quantum.Math.SignD(0.005)", &Value::Int(1));
82 test_expression("Microsoft.Quantum.Math.SignD(-0.005)", &Value::Int(-1));
83}
84
85#[test]
86fn check_sign_l() {
87 test_expression("Microsoft.Quantum.Math.SignL(0L)", &Value::Int(0));
88 test_expression(
89 "Microsoft.Quantum.Math.SignL(9999999999999999999999999999999999999999L)",
90 &Value::Int(1),
91 );
92 test_expression(
93 "Microsoft.Quantum.Math.SignL(-9999999999999999999999999999999999999999L)",
94 &Value::Int(-1),
95 );
96}
97
98#[test]
99fn check_abs_i() {
100 test_expression("Microsoft.Quantum.Math.AbsI(0)", &Value::Int(0));
101 test_expression("Microsoft.Quantum.Math.AbsI(1000)", &Value::Int(1000));
102 test_expression("Microsoft.Quantum.Math.AbsI(-1000)", &Value::Int(1000));
103 test_expression(
104 "Microsoft.Quantum.Math.AbsI(-0x8000_0000_0000_0000)",
105 &Value::Int(-0x8000_0000_0000_0000),
106 );
107}
108
109#[test]
110fn check_abs_d() {
111 test_expression("Microsoft.Quantum.Math.AbsD(0.0)", &Value::Double(0.0));
112 test_expression("Microsoft.Quantum.Math.AbsD(0.005)", &Value::Double(0.005));
113 test_expression("Microsoft.Quantum.Math.AbsD(-0.005)", &Value::Double(0.005));
114}
115
116#[test]
117fn check_abs_l() {
118 test_expression(
119 "Microsoft.Quantum.Math.AbsL(0L)",
120 &Value::BigInt(BigInt::from(0)),
121 );
122 test_expression(
123 "Microsoft.Quantum.Math.AbsL(9999L)",
124 &Value::BigInt(BigInt::from(9999)),
125 );
126 test_expression(
127 "Microsoft.Quantum.Math.AbsL(-9999L)",
128 &Value::BigInt(BigInt::from(9999)),
129 );
130}
131
132#[test]
133fn check_max_i() {
134 test_expression("Microsoft.Quantum.Math.MaxI(-5,7)", &Value::Int(7));
135 test_expression("Microsoft.Quantum.Math.MaxI(-7,0)", &Value::Int(0));
136}
137
138#[test]
139fn check_max_d() {
140 test_expression("Microsoft.Quantum.Math.MaxD(-5.0,7.0)", &Value::Double(7.0));
141 test_expression("Microsoft.Quantum.Math.MaxD(-7.0,0.0)", &Value::Double(0.0));
142}
143
144#[test]
145fn check_max_l() {
146 test_expression(
147 "Microsoft.Quantum.Math.MaxL(-5L,7L)",
148 &Value::BigInt(BigInt::from(7)),
149 );
150 test_expression(
151 "Microsoft.Quantum.Math.MaxL(-7L,0L)",
152 &Value::BigInt(BigInt::from(0)),
153 );
154}
155
156#[test]
157fn check_min_i() {
158 test_expression("Microsoft.Quantum.Math.MinI(-5,7)", &Value::Int(-5));
159 test_expression("Microsoft.Quantum.Math.MinI(-7,0)", &Value::Int(-7));
160}
161
162#[test]
163fn check_min_d() {
164 test_expression(
165 "Microsoft.Quantum.Math.MinD(-5.0,7.0)",
166 &Value::Double(-5.0),
167 );
168 test_expression(
169 "Microsoft.Quantum.Math.MinD(-7.0,0.0)",
170 &Value::Double(-7.0),
171 );
172}
173
174#[test]
175fn check_min_l() {
176 test_expression(
177 "Microsoft.Quantum.Math.MinL(-5L,7L)",
178 &Value::BigInt(BigInt::from(-5)),
179 );
180 test_expression(
181 "Microsoft.Quantum.Math.MinL(-7L,0L)",
182 &Value::BigInt(BigInt::from(-7)),
183 );
184}
185
186#[test]
187fn check_min() {
188 test_expression(
189 "Microsoft.Quantum.Math.Min([-5, 7, 1, 10])",
190 &Value::Int(-5),
191 );
192 test_expression("Microsoft.Quantum.Math.Min([5, 7, 1, 10])", &Value::Int(1));
193 test_expression("Microsoft.Quantum.Math.Min([1])", &Value::Int(1));
194}
195
196#[test]
197fn check_max() {
198 test_expression(
199 "Microsoft.Quantum.Math.Max([10, 7, 1, -20])",
200 &Value::Int(10),
201 );
202 test_expression("Microsoft.Quantum.Math.Max([5, 7, 1, 20])", &Value::Int(20));
203 test_expression("Microsoft.Quantum.Math.Max([1])", &Value::Int(1));
204}
205
206//
207// Trigonometric functions
208//
209
210#[test]
211fn check_arccos() {
212 test_expression(
213 "Microsoft.Quantum.Math.ArcCos(0.43)",
214 &Value::Double(0.43_f64.acos()),
215 );
216}
217
218#[test]
219fn check_arcsin() {
220 test_expression(
221 "Microsoft.Quantum.Math.ArcSin(0.43)",
222 &Value::Double(0.43_f64.asin()),
223 );
224}
225
226#[test]
227fn check_arctan() {
228 test_expression(
229 "Microsoft.Quantum.Math.ArcTan(43.43)",
230 &Value::Double(43.43_f64.atan()),
231 );
232}
233
234#[test]
235fn check_arctan2() {
236 test_expression(
237 "Microsoft.Quantum.Math.ArcTan2(43.0,17.0)",
238 &Value::Double(43.0_f64.atan2(17.0)),
239 );
240}
241
242#[test]
243fn check_cos() {
244 test_expression(
245 "Microsoft.Quantum.Math.Cos(1.11)",
246 &Value::Double(1.11_f64.cos()),
247 );
248}
249
250#[test]
251fn check_cosh() {
252 test_expression(
253 "Microsoft.Quantum.Math.Cosh(1.11)",
254 &Value::Double(1.11_f64.cosh()),
255 );
256}
257
258#[test]
259fn check_sin() {
260 test_expression(
261 "Microsoft.Quantum.Math.Sin(2.22)",
262 &Value::Double(2.22_f64.sin()),
263 );
264}
265
266#[test]
267fn check_sinh() {
268 test_expression(
269 "Microsoft.Quantum.Math.Sinh(2.22)",
270 &Value::Double(2.22_f64.sinh()),
271 );
272}
273
274#[test]
275fn check_tan() {
276 test_expression(
277 "Microsoft.Quantum.Math.Tan(1.23)",
278 &Value::Double(1.23_f64.tan()),
279 );
280}
281
282#[test]
283fn check_tanh() {
284 test_expression(
285 "Microsoft.Quantum.Math.Tanh(1.23)",
286 &Value::Double(1.23_f64.tanh()),
287 );
288}
289
290#[test]
291fn check_arccosh() {
292 test_expression(
293 "Microsoft.Quantum.Math.ArcCosh(1.234)",
294 &Value::Double(1.234_f64.acosh()),
295 );
296}
297
298#[test]
299fn check_arcsinh() {
300 test_expression(
301 "Microsoft.Quantum.Math.ArcSinh(10.0)",
302 &Value::Double(10.0_f64.asinh()),
303 );
304}
305
306#[test]
307fn check_arctanh() {
308 test_expression(
309 "Microsoft.Quantum.Math.ArcTanh(0.5)",
310 &Value::Double(0.5_f64.atanh()),
311 );
312}
313
314//
315// Sqrt, Log, exp, etc.
316//
317
318#[test]
319fn check_sqrt() {
320 test_expression(
321 "Microsoft.Quantum.Math.Sqrt(57121.0)",
322 &Value::Double(239.0),
323 );
324}
325
326#[test]
327fn check_log() {
328 test_expression(
329 "Microsoft.Quantum.Math.Log(57121.0)",
330 &Value::Double(57121.0_f64.ln()),
331 );
332}
333
334#[test]
335fn check_log10() {
336 test_expression("Microsoft.Quantum.Math.Log10(1.0)", &Value::Double(0.0));
337 test_expression("Microsoft.Quantum.Math.Log10(10.0)", &Value::Double(1.0));
338}
339
340#[test]
341fn check_lg() {
342 test_expression("Microsoft.Quantum.Math.Lg(1.0)", &Value::Double(0.0));
343 test_expression("Microsoft.Quantum.Math.Lg(2.0)", &Value::Double(1.0));
344}
345
346//
347// Truncation and Rounding
348//
349
350#[test]
351fn check_truncate() {
352 test_expression("Microsoft.Quantum.Math.Truncate(3.1)", &Value::Int(3));
353 test_expression("Microsoft.Quantum.Math.Truncate(-3.7)", &Value::Int(-3));
354}
355
356#[test]
357fn check_ceiling() {
358 test_expression("Microsoft.Quantum.Math.Ceiling(3.1)", &Value::Int(4));
359 test_expression("Microsoft.Quantum.Math.Ceiling(-3.7)", &Value::Int(-3));
360}
361
362#[test]
363fn check_floor() {
364 test_expression("Microsoft.Quantum.Math.Floor(3.7)", &Value::Int(3));
365 test_expression("Microsoft.Quantum.Math.Floor(-3.1)", &Value::Int(-4));
366}
367
368#[test]
369fn check_round() {
370 test_expression("Std.Math.Round(0.5-1.0e-16)", &Value::Int(0));
371 test_expression("Std.Math.Round(0.5)", &Value::Int(0));
372 test_expression("Std.Math.Round(0.5+1.0e-16)", &Value::Int(1));
373 test_expression("Std.Math.Round(3.1)", &Value::Int(3));
374 test_expression("Std.Math.Round(-3.7)", &Value::Int(-4));
375 test_expression("Std.Math.Round(-3.5)", &Value::Int(-3));
376}
377
378#[test]
379fn check_round_away_from_zero() {
380 test_expression(
381 "Std.Math.RoundHalfAwayFromZero(0.5-1.0e-16)",
382 &Value::Int(0),
383 );
384 test_expression("Std.Math.RoundHalfAwayFromZero(0.5)", &Value::Int(1));
385 test_expression(
386 "Std.Math.RoundHalfAwayFromZero(0.5+1.0e-16)",
387 &Value::Int(1),
388 );
389 test_expression("Std.Math.RoundHalfAwayFromZero(3.1)", &Value::Int(3));
390 test_expression("Std.Math.RoundHalfAwayFromZero(-3.7)", &Value::Int(-4));
391 test_expression("Std.Math.RoundHalfAwayFromZero(-3.5)", &Value::Int(-4));
392}
393
394//
395// Modular arithmetic
396//
397
398#[test]
399fn check_divrem_i() {
400 test_expression(
401 "Microsoft.Quantum.Math.DivRemI(20, 3)",
402 &Value::Tuple(vec![Value::Int(6), Value::Int(2)].into()),
403 );
404 test_expression(
405 "Microsoft.Quantum.Math.DivRemI(-20, 3)",
406 &Value::Tuple(vec![Value::Int(-6), Value::Int(-2)].into()),
407 );
408}
409
410#[test]
411fn check_divrem_l() {
412 test_expression(
413 "Microsoft.Quantum.Math.DivRemL(20L, 3L)",
414 &Value::Tuple(
415 vec![
416 Value::BigInt(BigInt::from(6)),
417 Value::BigInt(BigInt::from(2)),
418 ]
419 .into(),
420 ),
421 );
422 test_expression(
423 "Microsoft.Quantum.Math.DivRemL(-20L, 3L)",
424 &Value::Tuple(
425 vec![
426 Value::BigInt(BigInt::from(-6)),
427 Value::BigInt(BigInt::from(-2)),
428 ]
429 .into(),
430 ),
431 );
432}
433
434#[test]
435fn check_modulus_i() {
436 test_expression("Microsoft.Quantum.Math.ModulusI(20, 3)", &Value::Int(2));
437 test_expression("Microsoft.Quantum.Math.ModulusI(-20, 3)", &Value::Int(1));
438}
439
440#[test]
441fn check_modulus_l() {
442 test_expression(
443 "Microsoft.Quantum.Math.ModulusL(20L, 3L)",
444 &Value::BigInt(BigInt::from(2)),
445 );
446 test_expression(
447 "Microsoft.Quantum.Math.ModulusL(-20L, 3L)",
448 &Value::BigInt(BigInt::from(1)),
449 );
450}
451
452#[test]
453fn check_exp_mod_i() {
454 test_expression("Microsoft.Quantum.Math.ExpModI(1,10,10)", &Value::Int(1));
455 test_expression("Microsoft.Quantum.Math.ExpModI(10,0,10)", &Value::Int(1));
456 test_expression("Microsoft.Quantum.Math.ExpModI(2,10,10)", &Value::Int(4));
457}
458
459#[test]
460fn check_exp_mod_l() {
461 test_expression(
462 "Microsoft.Quantum.Math.ExpModL(1L,10L,10L)",
463 &Value::BigInt(BigInt::from(1)),
464 );
465 test_expression(
466 "Microsoft.Quantum.Math.ExpModL(10L,0L,10L)",
467 &Value::BigInt(BigInt::from(1)),
468 );
469 test_expression(
470 "Microsoft.Quantum.Math.ExpModL(2L,10L,10L)",
471 &Value::BigInt(BigInt::from(4)),
472 );
473}
474
475#[test]
476fn check_inverse_mod_i() {
477 test_expression("Microsoft.Quantum.Math.InverseModI(2,5)", &Value::Int(3));
478 test_expression("Microsoft.Quantum.Math.InverseModI(3,10)", &Value::Int(7));
479 test_expression("Microsoft.Quantum.Math.InverseModI(-1,5)", &Value::Int(4));
480}
481
482#[test]
483fn check_inverse_mod_l() {
484 test_expression(
485 "Microsoft.Quantum.Math.InverseModL(2L,5L)",
486 &Value::BigInt(BigInt::from(3)),
487 );
488 test_expression(
489 "Microsoft.Quantum.Math.InverseModL(3L,10L)",
490 &Value::BigInt(BigInt::from(7)),
491 );
492 test_expression(
493 "Microsoft.Quantum.Math.InverseModL(-1L,5L)",
494 &Value::BigInt(BigInt::from(4)),
495 );
496}
497
498//
499// GCD, etc.
500//
501#[test]
502fn check_gcd_i() {
503 test_expression(
504 "Microsoft.Quantum.Math.GreatestCommonDivisorI(0,0)",
505 &Value::Int(0),
506 );
507 test_expression(
508 "Microsoft.Quantum.Math.GreatestCommonDivisorI(2*3*5,2*3*7)",
509 &Value::Int(2 * 3),
510 );
511 test_expression(
512 "Microsoft.Quantum.Math.GreatestCommonDivisorI(39088169,63245986)",
513 &Value::Int(1),
514 );
515}
516
517#[test]
518fn check_gcd_l() {
519 test_expression(
520 "Microsoft.Quantum.Math.GreatestCommonDivisorL(0L,0L)",
521 &Value::BigInt(BigInt::from(0)),
522 );
523 test_expression(
524 "Microsoft.Quantum.Math.GreatestCommonDivisorL(2L*3L*5L,2L*3L*7L)",
525 &Value::BigInt(BigInt::from(2 * 3)),
526 );
527 test_expression("Microsoft.Quantum.Math.GreatestCommonDivisorL(222232244629420445529739893461909967206666939096499764990979600L,359579325206583560961765665172189099052367214309267232255589801L)", &Value::BigInt(
528 BigInt::from(1)));
529}
530
531#[test]
532fn check_is_coprime_i() {
533 test_expression(
534 "Microsoft.Quantum.Math.IsCoprimeI(44,35)",
535 &Value::Bool(true),
536 );
537 test_expression(
538 "Microsoft.Quantum.Math.IsCoprimeI(6,9)",
539 &Value::Bool(false),
540 );
541 test_expression(
542 "Microsoft.Quantum.Math.IsCoprimeI(1, -1)",
543 &Value::Bool(true),
544 );
545}
546
547#[test]
548fn check_is_coprime_l() {
549 test_expression(
550 "Microsoft.Quantum.Math.IsCoprimeL(739696442014594807059393047166976L,7609583501588058567047119140625L)",
551 &Value::Bool(true),
552 );
553 test_expression(
554 "Microsoft.Quantum.Math.IsCoprimeL(6L,9L)",
555 &Value::Bool(false),
556 );
557 test_expression(
558 "Microsoft.Quantum.Math.IsCoprimeL(1L, -1L)",
559 &Value::Bool(true),
560 );
561}
562
563#[test]
564fn check_cfc_i() {
565 // NOTE: It is not important if the function returns -3/-4 or 3/4,
566 // we can ignore this implementation details or update a function
567 // to return canonical result.
568 test_expression(
569 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 2)",
570 &Value::Tuple(vec![Value::Int(-1), Value::Int(-1)].into()),
571 );
572 test_expression(
573 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 3)",
574 &Value::Tuple(vec![Value::Int(2), Value::Int(3)].into()),
575 );
576 test_expression(
577 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 4)",
578 &Value::Tuple(vec![Value::Int(-3), Value::Int(-4)].into()),
579 );
580 test_expression(
581 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 7)",
582 &Value::Tuple(vec![Value::Int(5), Value::Int(7)].into()),
583 );
584 test_expression(
585 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 25)",
586 &Value::Tuple(vec![Value::Int(-18), Value::Int(-25)].into()),
587 );
588}
589
590#[test]
591fn check_cfc_l() {
592 // NOTE: It is not important if the function returns -3/-4 or 3/4,
593 // we can ignore this implementation details or update a function
594 // to return canonical result.
595 test_expression(
596 "Microsoft.Quantum.Math.ContinuedFractionConvergentL((72L,100L), 2L)",
597 &Value::Tuple(
598 vec![
599 Value::BigInt(BigInt::from(-1)),
600 Value::BigInt(BigInt::from(-1)),
601 ]
602 .into(),
603 ),
604 );
605 test_expression(
606 "Microsoft.Quantum.Math.ContinuedFractionConvergentL((72L,100L), 3L)",
607 &Value::Tuple(
608 vec![
609 Value::BigInt(BigInt::from(2)),
610 Value::BigInt(BigInt::from(3)),
611 ]
612 .into(),
613 ),
614 );
615 test_expression(
616 "Microsoft.Quantum.Math.ContinuedFractionConvergentL((72L,100L), 25L)",
617 &Value::Tuple(
618 vec![
619 Value::BigInt(BigInt::from(-18)),
620 Value::BigInt(BigInt::from(-25)),
621 ]
622 .into(),
623 ),
624 );
625 test_expression(
626 "Microsoft.Quantum.Math.ContinuedFractionConvergentL((170141183460469231731687303715884105727L,331780596164137120496034969018767441441L), 2L)",
627 &Value::Tuple(vec![Value::BigInt(BigInt::from(1)), Value::BigInt(BigInt::from(2))].into()),
628 );
629 test_expression(
630 "Microsoft.Quantum.Math.ContinuedFractionConvergentL((170141183460469231731687303715884105727L,331780596164137120496034969018767441441L), 1000000L)",
631 &Value::Tuple(vec![Value::BigInt(BigInt::from(33_781)), Value::BigInt(BigInt::from(65_874))].into()),
632 );
633}
634
635#[test]
636fn check_real_mod() {
637 test_expression(
638 "{ import Std.Math.*;
639 RealMod(5.5 * PI(), 2.0 * PI(), 0.0) }",
640 &Value::Double(1.5 * PI),
641 );
642 test_expression(
643 "{ import Std.Math.*;
644 RealMod(0.5 * PI(), 2.0 * PI(), -PI()/2.0) }",
645 &Value::Double(0.5 * PI),
646 );
647 test_expression(
648 "Microsoft.Quantum.Math.RealMod(10.5, 2.3, 1.2)",
649 &Value::Double(1.3),
650 );
651 test_expression(
652 "Microsoft.Quantum.Math.RealMod(3.6, 2.4, -1.2)",
653 &Value::Double(-1.2),
654 );
655}
656
657#[test]
658fn check_bitsize_i() {
659 test_expression("Microsoft.Quantum.Math.BitSizeI(0)", &Value::Int(0));
660 test_expression("Microsoft.Quantum.Math.BitSizeI(1)", &Value::Int(1));
661 test_expression("Microsoft.Quantum.Math.BitSizeI(2)", &Value::Int(2));
662 test_expression("Microsoft.Quantum.Math.BitSizeI(3)", &Value::Int(2));
663 test_expression(
664 "Microsoft.Quantum.Math.BitSizeI(0x7FFFFFFFFFFFFFFF)",
665 &Value::Int(63),
666 );
667}
668
669#[test]
670fn check_bitsize_l() {
671 test_expression("Microsoft.Quantum.Math.BitSizeL(0L)", &Value::Int(0));
672 test_expression("Microsoft.Quantum.Math.BitSizeL(1L)", &Value::Int(1));
673 test_expression("Microsoft.Quantum.Math.BitSizeL(2L)", &Value::Int(2));
674 test_expression("Microsoft.Quantum.Math.BitSizeL(3L)", &Value::Int(2));
675 test_expression(
676 "Microsoft.Quantum.Math.BitSizeL(0x7FFFFFFFFFFFFFFFL)",
677 &Value::Int(63),
678 );
679 test_expression(
680 "Microsoft.Quantum.Math.BitSizeL(0x8FFFFFFFFFFFFFFFL)",
681 &Value::Int(64),
682 );
683}
684
685#[test]
686fn check_trailing_zero_count_i() {
687 test_expression(
688 "Microsoft.Quantum.Math.TrailingZeroCountI(7)",
689 &Value::Int(0),
690 );
691 test_expression(
692 "Microsoft.Quantum.Math.TrailingZeroCountI(2)",
693 &Value::Int(1),
694 );
695 test_expression(
696 "Microsoft.Quantum.Math.TrailingZeroCountI(7616)",
697 &Value::Int(6),
698 );
699}
700
701#[test]
702fn check_trailing_zero_count_l() {
703 test_expression(
704 "Microsoft.Quantum.Math.TrailingZeroCountL(7L)",
705 &Value::Int(0),
706 );
707 test_expression(
708 "Microsoft.Quantum.Math.TrailingZeroCountL(2L)",
709 &Value::Int(1),
710 );
711 test_expression(
712 "Microsoft.Quantum.Math.TrailingZeroCountL(1L<<<163)",
713 &Value::Int(163),
714 );
715}
716
717#[test]
718fn check_hamming_weight() {
719 test_expression("Microsoft.Quantum.Math.HammingWeightI(2)", &Value::Int(1));
720 test_expression("Microsoft.Quantum.Math.HammingWeightI(14)", &Value::Int(3));
721 test_expression(
722 "Microsoft.Quantum.Math.HammingWeightI(1<<<5)",
723 &Value::Int(1),
724 );
725}
726
727//
728// Combinatorics
729//
730
731#[test]
732fn check_factorial_i() {
733 test_expression("Microsoft.Quantum.Math.FactorialI(0)", &Value::Int(1));
734 test_expression("Microsoft.Quantum.Math.FactorialI(1)", &Value::Int(1));
735 test_expression("Microsoft.Quantum.Math.FactorialI(2)", &Value::Int(2));
736 test_expression(
737 "Microsoft.Quantum.Math.FactorialI(10)",
738 &Value::Int(3_628_800),
739 );
740}
741
742#[test]
743fn check_factorial_l() {
744 test_expression(
745 "Microsoft.Quantum.Math.FactorialL(0)",
746 &Value::BigInt(BigInt::from(1)),
747 );
748 test_expression(
749 "Microsoft.Quantum.Math.FactorialL(1)",
750 &Value::BigInt(BigInt::from(1)),
751 );
752 test_expression(
753 "Microsoft.Quantum.Math.FactorialL(2)",
754 &Value::BigInt(BigInt::from(2)),
755 );
756 test_expression(
757 "Microsoft.Quantum.Math.FactorialL(10)",
758 &Value::BigInt(BigInt::from(3_628_800)),
759 );
760 test_expression(
761 "Microsoft.Quantum.Math.FactorialL(170)",
762 &Value::BigInt(BigInt::from_str(
763 "7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000"
764 ).expect("Cannot parse static BigInt in Rust code."))
765 );
766}
767
768#[test]
769fn check_approximate_factorial() {
770 test_expression(
771 "Microsoft.Quantum.Math.ApproximateFactorial(0)",
772 &Value::Double(1.0),
773 );
774 test_expression(
775 "Microsoft.Quantum.Math.ApproximateFactorial(2)",
776 &Value::Double(2.0),
777 );
778 // NOTE: Tests for larger numbers can be added
779 // when approximate comparison is implemented.
780}
781
782#[test]
783fn check_log_gamma_d() {
784 test_expression(
785 "Microsoft.Quantum.Math.LogGammaD(3.14)",
786 &Value::Double(0.826_138_704_777_028),
787 );
788 test_expression(
789 "Microsoft.Quantum.Math.LogGammaD(0.782)",
790 &Value::Double(0.169_806_721_914_044),
791 );
792 test_expression(
793 "Microsoft.Quantum.Math.LogGammaD(1234.567)",
794 &Value::Double(7_551.027_809_984_276),
795 );
796}
797
798#[test]
799fn check_log_factorial_d() {
800 test_expression(
801 "Microsoft.Quantum.Math.LogFactorialD(2000)",
802 &Value::Double(13_206.524_350_513_8),
803 );
804 test_expression(
805 "Microsoft.Quantum.Math.LogFactorialD(4321)",
806 &Value::Double(31_856.241_848_248_7),
807 );
808}
809
810#[test]
811fn check_binom() {
812 test_expression(
813 "Microsoft.Quantum.Math.Binom(31, 7)",
814 &Value::Int(2_629_575),
815 );
816 test_expression("Microsoft.Quantum.Math.Binom(23, 9)", &Value::Int(817_190));
817 test_expression("Microsoft.Quantum.Math.Binom(13, 5)", &Value::Int(1_287));
818 test_expression("Microsoft.Quantum.Math.Binom(4, 0)", &Value::Int(1));
819 test_expression("Microsoft.Quantum.Math.Binom(4, 4)", &Value::Int(1));
820}
821
822#[test]
823fn check_square_norm() {
824 test_expression(
825 "Microsoft.Quantum.Math.SquaredNorm([2.0])",
826 &Value::Double(4.0),
827 );
828 test_expression(
829 "Microsoft.Quantum.Math.SquaredNorm([-1.0, 1.0])",
830 &Value::Double(2.0),
831 );
832 test_expression(
833 "Microsoft.Quantum.Math.SquaredNorm([3.0, 4.0])",
834 &Value::Double(25.0),
835 );
836}
837
838#[test]
839fn check_p_norm() {
840 test_expression(
841 "Microsoft.Quantum.Math.PNorm(1.0, [-0.1, 0.2, 0.3])",
842 &Value::Double(0.6),
843 );
844 test_expression(
845 "Microsoft.Quantum.Math.PNorm(1.5, [0.1, -0.2, 0.3])",
846 &Value::Double(0.433_462_287_211_361),
847 );
848 test_expression(
849 "Microsoft.Quantum.Math.PNorm(2.0, [0.1, 0.2, -0.3])",
850 &Value::Double(0.374_165_738_677_394_17),
851 );
852 test_expression(
853 "Microsoft.Quantum.Math.PNorm(3.0, [0.0, 0.0])",
854 &Value::Double(0.0),
855 );
856}
857
858#[test]
859fn check_p_normalized() {
860 test_expression(
861 "Microsoft.Quantum.Math.PNormalized(1.0, [-0.1, 0.2, 0.5])",
862 &Value::Array(
863 vec![
864 Value::Double(-0.125),
865 Value::Double(0.25),
866 Value::Double(0.625),
867 ]
868 .into(),
869 ),
870 );
871 test_expression(
872 "Microsoft.Quantum.Math.PNormalized(2.0, [3.0, 4.0])",
873 &Value::Array(vec![Value::Double(0.6), Value::Double(0.8)].into()),
874 );
875 test_expression(
876 "Microsoft.Quantum.Math.PNormalized(3.0, [0.0, 0.0])",
877 &Value::Array(vec![Value::Double(0.0), Value::Double(0.0)].into()),
878 );
879}
880
881//
882// Complex numbers
883//
884
885#[test]
886fn check_abs_squared_complex() {
887 test_expression(
888 "{
889 import Std.Math.*;
890 AbsSquaredComplex(Complex(1.0,1.0))}",
891 &Value::Double(2.0),
892 );
893 test_expression(
894 "{
895 import Std.Math.*;
896 AbsSquaredComplex(Complex(-3.0,4.0))}",
897 &Value::Double(25.0),
898 );
899}
900
901#[test]
902fn check_abs_complex() {
903 test_expression(
904 "{
905 import Std.Math.*;
906 AbsComplex(Complex(1.0,1.0))}",
907 &Value::Double(2.0_f64.sqrt()),
908 );
909 test_expression(
910 "{
911 import Std.Math.*;
912 AbsComplex(Complex(-3.0,4.0))}",
913 &Value::Double(5.0),
914 );
915}
916
917#[test]
918fn check_arg_complex() {
919 test_expression(
920 "{
921 import Std.Math.*;
922 ArgComplex(Complex(100.0,0.0))}",
923 &Value::Double(0.0),
924 );
925 test_expression(
926 "{
927 import Std.Math.*;
928 ArgComplex(Complex(1.0,1.0))}",
929 &Value::Double(PI / 4.0),
930 );
931}
932
933#[test]
934fn check_abs_squared_complex_polar() {
935 test_expression(
936 "{
937 import Std.Math.*;
938 AbsSquaredComplexPolar(ComplexPolar(1.0,2.0))}",
939 &Value::Double(1.0),
940 );
941 test_expression(
942 "{
943 import Std.Math.*;
944 AbsSquaredComplexPolar(ComplexPolar(5.0,-1.0))}",
945 &Value::Double(25.0),
946 );
947}
948
949#[test]
950fn check_abs_complex_polar() {
951 test_expression(
952 "{
953 import Std.Math.*;
954 AbsComplexPolar(ComplexPolar(1.0,2.0))}",
955 &Value::Double(1.0),
956 );
957 test_expression(
958 "{
959 import Std.Math.*;
960 AbsComplexPolar(ComplexPolar(5.0,-1.0))}",
961 &Value::Double(5.0),
962 );
963}
964
965#[test]
966fn check_arg_complex_polar() {
967 test_expression(
968 "{
969 import Std.Math.*;
970 ArgComplexPolar(ComplexPolar(1.0,2.0))}",
971 &Value::Double(2.0),
972 );
973 test_expression(
974 "{
975 import Std.Math.*;
976 ArgComplexPolar(ComplexPolar(5.0,-1.0))}",
977 &Value::Double(-1.0),
978 );
979}
980
981#[test]
982fn check_negation_c() {
983 test_expression(
984 "{
985 import Std.Math.*;
986 NegationC(Complex(1.0,2.0))}",
987 &Value::Tuple(vec![Value::Double(-1.0), Value::Double(-2.0)].into()),
988 );
989 test_expression(
990 "{
991 import Std.Math.*;
992 NegationC(Complex(5.0,-1.0))}",
993 &Value::Tuple(vec![Value::Double(-5.0), Value::Double(1.0)].into()),
994 );
995}
996
997#[test]
998fn check_negation_cp() {
999 test_expression(
1000 "{
1001 import Std.Math.*;
1002 NegationCP(ComplexPolar(1.0,0.0))}",
1003 &Value::Tuple(vec![Value::Double(1.0), Value::Double(PI)].into()),
1004 );
1005 test_expression(
1006 "{
1007 import Std.Math.*;
1008 NegationCP(ComplexPolar(5.0,-PI()/2.0))}",
1009 &Value::Tuple(vec![Value::Double(5.0), Value::Double(PI / 2.0)].into()),
1010 );
1011}
1012
1013#[test]
1014fn check_plus_c() {
1015 test_expression(
1016 "{
1017 import Std.Math.*;
1018 PlusC(Complex(1.0,0.0), Complex(0.0,1.0))}",
1019 &Value::Tuple(vec![Value::Double(1.0), Value::Double(1.0)].into()),
1020 );
1021 test_expression(
1022 "{
1023 import Std.Math.*;
1024 PlusC(Complex(10.0,10.0), Complex(-10.0,10.0))}",
1025 &Value::Tuple(vec![Value::Double(0.0), Value::Double(20.0)].into()),
1026 );
1027}
1028
1029#[test]
1030fn check_plus_cp() {
1031 test_expression(
1032 "{
1033 import Std.Math.*;
1034 PlusCP(ComplexPolar(1.0,0.0), ComplexPolar(1.0,PI()/2.0))}",
1035 &Value::Tuple(vec![Value::Double(2.0_f64.sqrt()), Value::Double(PI / 4.0)].into()),
1036 );
1037 test_expression(
1038 "{
1039 import Std.Math.*;
1040 PlusCP(ComplexPolar(10.0,PI()/4.0), ComplexPolar(10.0,3.0*PI()/4.0))}",
1041 &Value::Tuple(vec![Value::Double(200.0_f64.sqrt()), Value::Double(PI / 2.0)].into()),
1042 );
1043}
1044
1045#[test]
1046fn check_minus_c() {
1047 test_expression(
1048 "{
1049 import Std.Math.*;
1050 MinusC(Complex(1.0,0.0), Complex(0.0,1.0))}",
1051 &Value::Tuple(vec![Value::Double(1.0), Value::Double(-1.0)].into()),
1052 );
1053 test_expression(
1054 "{
1055 import Std.Math.*;
1056 MinusC(Complex(10.0,10.0), Complex(-10.0,10.0))}",
1057 &Value::Tuple(vec![Value::Double(20.0), Value::Double(0.0)].into()),
1058 );
1059}
1060
1061#[test]
1062fn check_minus_cp() {
1063 test_expression(
1064 "{
1065 import Std.Math.*;
1066 MinusCP(ComplexPolar(4.0,0.0), ComplexPolar(1.0,-PI()))}",
1067 &Value::Tuple(vec![Value::Double(5.0), Value::Double(0.0)].into()),
1068 );
1069}
1070
1071#[test]
1072fn check_times_c() {
1073 test_expression(
1074 "{
1075 import Std.Math.*;
1076 TimesC(Complex(2.0,0.0), Complex(3.0,0.0))}",
1077 &Value::Tuple(vec![Value::Double(6.0), Value::Double(0.0)].into()),
1078 );
1079 test_expression(
1080 "{
1081 import Std.Math.*;
1082 TimesC(Complex(3.0,0.0), Complex(0.0,1.0))}",
1083 &Value::Tuple(vec![Value::Double(0.0), Value::Double(3.0)].into()),
1084 );
1085 test_expression(
1086 "{
1087 import Std.Math.*;
1088 TimesC(Complex(1.0,2.0), Complex(3.0,4.0))}",
1089 &Value::Tuple(vec![Value::Double(-5.0), Value::Double(10.0)].into()),
1090 );
1091}
1092
1093#[test]
1094fn check_times_cp() {
1095 test_expression(
1096 "{
1097 import Std.Math.*;
1098 TimesCP(ComplexPolar(1.0,0.0), ComplexPolar(1.0,PI()/2.0))}",
1099 &Value::Tuple(vec![Value::Double(1.0), Value::Double(PI / 2.0)].into()),
1100 );
1101 test_expression(
1102 "{
1103 import Std.Math.*;
1104 TimesCP(ComplexPolar(1.0,PI()/4.0), ComplexPolar(2.0,3.0*PI()/4.0))}",
1105 &Value::Tuple(vec![Value::Double(2.0), Value::Double(PI)].into()),
1106 );
1107}
1108
1109#[test]
1110fn check_pow_c() {
1111 test_expression(
1112 "{
1113 import Std.Math.*;
1114 PowC(Complex(2.0,0.0), Complex(3.0,0.0))}",
1115 &Value::Tuple(vec![Value::Double(8.0), Value::Double(0.0)].into()),
1116 );
1117 test_expression(
1118 "{
1119 import Std.Math.*;
1120 PowC(Complex(0.0,1.0), Complex(0.0,1.0))}",
1121 &Value::Tuple(vec![Value::Double(E.powf(-PI / 2.0)), Value::Double(0.0)].into()),
1122 );
1123}
1124
1125#[test]
1126fn check_pow_cp() {
1127 test_expression(
1128 "{
1129 import Std.Math.*;
1130 PowCP(ComplexPolar(2.0,0.0), ComplexPolar(3.0,0.0))}",
1131 &Value::Tuple(vec![Value::Double(8.0), Value::Double(0.0)].into()),
1132 );
1133}
1134
1135#[test]
1136fn check_divide_by_c() {
1137 test_expression(
1138 "{
1139 import Std.Math.*;
1140 DividedByC(Complex(1.0,0.0), Complex(2.0,0.0))}",
1141 &Value::Tuple(vec![Value::Double(0.5), Value::Double(0.0)].into()),
1142 );
1143 test_expression(
1144 "{
1145 import Std.Math.*;
1146 DividedByC(Complex(3.0,0.0), Complex(0.0,1.0))}",
1147 &Value::Tuple(vec![Value::Double(0.0), Value::Double(-3.0)].into()),
1148 );
1149 test_expression(
1150 "{
1151 import Std.Math.*;
1152 DividedByC(Complex(1.0,2.0), Complex(3.0,4.0))}",
1153 &Value::Tuple(vec![Value::Double(0.44), Value::Double(0.08)].into()),
1154 );
1155}
1156
1157#[test]
1158fn check_devide_by_cp() {
1159 test_expression(
1160 "{
1161 import Std.Math.*;
1162 DividedByCP(ComplexPolar(1.0,0.0), ComplexPolar(1.0,PI()/2.0))}",
1163 &Value::Tuple(vec![Value::Double(1.0), Value::Double(-PI / 2.0)].into()),
1164 );
1165 test_expression(
1166 "{
1167 import Std.Math.*;
1168 DividedByCP(ComplexPolar(1.0,PI()/4.0), ComplexPolar(2.0,3.0*PI()/4.0))}",
1169 &Value::Tuple(vec![Value::Double(0.5), Value::Double(-PI / 2.0)].into()),
1170 );
1171}
1172
1173//
1174// Fixed point
1175//
1176
1177#[test]
1178fn check_smallest_fixed_point() {
1179 test_expression(
1180 "Microsoft.Quantum.Math.SmallestFixedPoint(1,0)",
1181 &Value::Double(-1.0),
1182 );
1183 test_expression(
1184 "Microsoft.Quantum.Math.SmallestFixedPoint(0,1)",
1185 &Value::Double(-0.5),
1186 );
1187 test_expression(
1188 "Microsoft.Quantum.Math.SmallestFixedPoint(10,5)",
1189 &Value::Double(-512.0),
1190 );
1191}
1192
1193#[test]
1194fn check_largest_fixed_point() {
1195 test_expression(
1196 "Microsoft.Quantum.Math.LargestFixedPoint(1,0)",
1197 &Value::Double(0.0),
1198 );
1199 test_expression(
1200 "Microsoft.Quantum.Math.LargestFixedPoint(0,1)",
1201 &Value::Double(0.0),
1202 );
1203 test_expression(
1204 "Microsoft.Quantum.Math.LargestFixedPoint(10,5)",
1205 &Value::Double(511.96875),
1206 );
1207}
1208