microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
iadavis/qasm-playground

Branches

Tags

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

Clone

HTTPS

Download ZIP

library/src/tests/math.rs

1221lines · 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(
528 "Microsoft.Quantum.Math.GreatestCommonDivisorL(222232244629420445529739893461909967206666939096499764990979600L,359579325206583560961765665172189099052367214309267232255589801L)",
529 &Value::BigInt(BigInt::from(1)),
530 );
531}
532
533#[test]
534fn check_is_coprime_i() {
535 test_expression(
536 "Microsoft.Quantum.Math.IsCoprimeI(44,35)",
537 &Value::Bool(true),
538 );
539 test_expression(
540 "Microsoft.Quantum.Math.IsCoprimeI(6,9)",
541 &Value::Bool(false),
542 );
543 test_expression(
544 "Microsoft.Quantum.Math.IsCoprimeI(1, -1)",
545 &Value::Bool(true),
546 );
547}
548
549#[test]
550fn check_is_coprime_l() {
551 test_expression(
552 "Microsoft.Quantum.Math.IsCoprimeL(739696442014594807059393047166976L,7609583501588058567047119140625L)",
553 &Value::Bool(true),
554 );
555 test_expression(
556 "Microsoft.Quantum.Math.IsCoprimeL(6L,9L)",
557 &Value::Bool(false),
558 );
559 test_expression(
560 "Microsoft.Quantum.Math.IsCoprimeL(1L, -1L)",
561 &Value::Bool(true),
562 );
563}
564
565#[test]
566fn check_cfc_i() {
567 // NOTE: It is not important if the function returns -3/-4 or 3/4,
568 // we can ignore this implementation details or update a function
569 // to return canonical result.
570 test_expression(
571 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 2)",
572 &Value::Tuple(vec![Value::Int(-1), Value::Int(-1)].into()),
573 );
574 test_expression(
575 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 3)",
576 &Value::Tuple(vec![Value::Int(2), Value::Int(3)].into()),
577 );
578 test_expression(
579 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 4)",
580 &Value::Tuple(vec![Value::Int(-3), Value::Int(-4)].into()),
581 );
582 test_expression(
583 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 7)",
584 &Value::Tuple(vec![Value::Int(5), Value::Int(7)].into()),
585 );
586 test_expression(
587 "Microsoft.Quantum.Math.ContinuedFractionConvergentI((72,100), 25)",
588 &Value::Tuple(vec![Value::Int(-18), Value::Int(-25)].into()),
589 );
590}
591
592#[test]
593fn check_cfc_l() {
594 // NOTE: It is not important if the function returns -3/-4 or 3/4,
595 // we can ignore this implementation details or update a function
596 // to return canonical result.
597 test_expression(
598 "Microsoft.Quantum.Math.ContinuedFractionConvergentL((72L,100L), 2L)",
599 &Value::Tuple(
600 vec![
601 Value::BigInt(BigInt::from(-1)),
602 Value::BigInt(BigInt::from(-1)),
603 ]
604 .into(),
605 ),
606 );
607 test_expression(
608 "Microsoft.Quantum.Math.ContinuedFractionConvergentL((72L,100L), 3L)",
609 &Value::Tuple(
610 vec![
611 Value::BigInt(BigInt::from(2)),
612 Value::BigInt(BigInt::from(3)),
613 ]
614 .into(),
615 ),
616 );
617 test_expression(
618 "Microsoft.Quantum.Math.ContinuedFractionConvergentL((72L,100L), 25L)",
619 &Value::Tuple(
620 vec![
621 Value::BigInt(BigInt::from(-18)),
622 Value::BigInt(BigInt::from(-25)),
623 ]
624 .into(),
625 ),
626 );
627 test_expression(
628 "Microsoft.Quantum.Math.ContinuedFractionConvergentL((170141183460469231731687303715884105727L,331780596164137120496034969018767441441L), 2L)",
629 &Value::Tuple(
630 vec![
631 Value::BigInt(BigInt::from(1)),
632 Value::BigInt(BigInt::from(2)),
633 ]
634 .into(),
635 ),
636 );
637 test_expression(
638 "Microsoft.Quantum.Math.ContinuedFractionConvergentL((170141183460469231731687303715884105727L,331780596164137120496034969018767441441L), 1000000L)",
639 &Value::Tuple(
640 vec![
641 Value::BigInt(BigInt::from(33_781)),
642 Value::BigInt(BigInt::from(65_874)),
643 ]
644 .into(),
645 ),
646 );
647}
648
649#[test]
650fn check_real_mod() {
651 test_expression(
652 "{ import Std.Math.*;
653 RealMod(5.5 * PI(), 2.0 * PI(), 0.0) }",
654 &Value::Double(1.5 * PI),
655 );
656 test_expression(
657 "{ import Std.Math.*;
658 RealMod(0.5 * PI(), 2.0 * PI(), -PI()/2.0) }",
659 &Value::Double(0.5 * PI),
660 );
661 test_expression(
662 "Microsoft.Quantum.Math.RealMod(10.5, 2.3, 1.2)",
663 &Value::Double(1.3),
664 );
665 test_expression(
666 "Microsoft.Quantum.Math.RealMod(3.6, 2.4, -1.2)",
667 &Value::Double(-1.2),
668 );
669}
670
671#[test]
672fn check_bitsize_i() {
673 test_expression("Microsoft.Quantum.Math.BitSizeI(0)", &Value::Int(0));
674 test_expression("Microsoft.Quantum.Math.BitSizeI(1)", &Value::Int(1));
675 test_expression("Microsoft.Quantum.Math.BitSizeI(2)", &Value::Int(2));
676 test_expression("Microsoft.Quantum.Math.BitSizeI(3)", &Value::Int(2));
677 test_expression(
678 "Microsoft.Quantum.Math.BitSizeI(0x7FFFFFFFFFFFFFFF)",
679 &Value::Int(63),
680 );
681}
682
683#[test]
684fn check_bitsize_l() {
685 test_expression("Microsoft.Quantum.Math.BitSizeL(0L)", &Value::Int(0));
686 test_expression("Microsoft.Quantum.Math.BitSizeL(1L)", &Value::Int(1));
687 test_expression("Microsoft.Quantum.Math.BitSizeL(2L)", &Value::Int(2));
688 test_expression("Microsoft.Quantum.Math.BitSizeL(3L)", &Value::Int(2));
689 test_expression(
690 "Microsoft.Quantum.Math.BitSizeL(0x7FFFFFFFFFFFFFFFL)",
691 &Value::Int(63),
692 );
693 test_expression(
694 "Microsoft.Quantum.Math.BitSizeL(0x8FFFFFFFFFFFFFFFL)",
695 &Value::Int(64),
696 );
697}
698
699#[test]
700fn check_trailing_zero_count_i() {
701 test_expression(
702 "Microsoft.Quantum.Math.TrailingZeroCountI(7)",
703 &Value::Int(0),
704 );
705 test_expression(
706 "Microsoft.Quantum.Math.TrailingZeroCountI(2)",
707 &Value::Int(1),
708 );
709 test_expression(
710 "Microsoft.Quantum.Math.TrailingZeroCountI(7616)",
711 &Value::Int(6),
712 );
713}
714
715#[test]
716fn check_trailing_zero_count_l() {
717 test_expression(
718 "Microsoft.Quantum.Math.TrailingZeroCountL(7L)",
719 &Value::Int(0),
720 );
721 test_expression(
722 "Microsoft.Quantum.Math.TrailingZeroCountL(2L)",
723 &Value::Int(1),
724 );
725 test_expression(
726 "Microsoft.Quantum.Math.TrailingZeroCountL(1L<<<163)",
727 &Value::Int(163),
728 );
729}
730
731#[test]
732fn check_hamming_weight() {
733 test_expression("Microsoft.Quantum.Math.HammingWeightI(2)", &Value::Int(1));
734 test_expression("Microsoft.Quantum.Math.HammingWeightI(14)", &Value::Int(3));
735 test_expression(
736 "Microsoft.Quantum.Math.HammingWeightI(1<<<5)",
737 &Value::Int(1),
738 );
739}
740
741//
742// Combinatorics
743//
744
745#[test]
746fn check_factorial_i() {
747 test_expression("Microsoft.Quantum.Math.FactorialI(0)", &Value::Int(1));
748 test_expression("Microsoft.Quantum.Math.FactorialI(1)", &Value::Int(1));
749 test_expression("Microsoft.Quantum.Math.FactorialI(2)", &Value::Int(2));
750 test_expression(
751 "Microsoft.Quantum.Math.FactorialI(10)",
752 &Value::Int(3_628_800),
753 );
754}
755
756#[test]
757fn check_factorial_l() {
758 test_expression(
759 "Microsoft.Quantum.Math.FactorialL(0)",
760 &Value::BigInt(BigInt::from(1)),
761 );
762 test_expression(
763 "Microsoft.Quantum.Math.FactorialL(1)",
764 &Value::BigInt(BigInt::from(1)),
765 );
766 test_expression(
767 "Microsoft.Quantum.Math.FactorialL(2)",
768 &Value::BigInt(BigInt::from(2)),
769 );
770 test_expression(
771 "Microsoft.Quantum.Math.FactorialL(10)",
772 &Value::BigInt(BigInt::from(3_628_800)),
773 );
774 test_expression(
775 "Microsoft.Quantum.Math.FactorialL(170)",
776 &Value::BigInt(BigInt::from_str(
777 "7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000"
778 ).expect("Cannot parse static BigInt in Rust code."))
779 );
780}
781
782#[test]
783fn check_approximate_factorial() {
784 test_expression(
785 "Microsoft.Quantum.Math.ApproximateFactorial(0)",
786 &Value::Double(1.0),
787 );
788 test_expression(
789 "Microsoft.Quantum.Math.ApproximateFactorial(2)",
790 &Value::Double(2.0),
791 );
792 // NOTE: Tests for larger numbers can be added
793 // when approximate comparison is implemented.
794}
795
796#[test]
797fn check_log_gamma_d() {
798 test_expression(
799 "Microsoft.Quantum.Math.LogGammaD(3.14)",
800 &Value::Double(0.826_138_704_777_028),
801 );
802 test_expression(
803 "Microsoft.Quantum.Math.LogGammaD(0.782)",
804 &Value::Double(0.169_806_721_914_044),
805 );
806 test_expression(
807 "Microsoft.Quantum.Math.LogGammaD(1234.567)",
808 &Value::Double(7_551.027_809_984_276),
809 );
810}
811
812#[test]
813fn check_log_factorial_d() {
814 test_expression(
815 "Microsoft.Quantum.Math.LogFactorialD(2000)",
816 &Value::Double(13_206.524_350_513_8),
817 );
818 test_expression(
819 "Microsoft.Quantum.Math.LogFactorialD(4321)",
820 &Value::Double(31_856.241_848_248_7),
821 );
822}
823
824#[test]
825fn check_binom() {
826 test_expression(
827 "Microsoft.Quantum.Math.Binom(31, 7)",
828 &Value::Int(2_629_575),
829 );
830 test_expression("Microsoft.Quantum.Math.Binom(23, 9)", &Value::Int(817_190));
831 test_expression("Microsoft.Quantum.Math.Binom(13, 5)", &Value::Int(1_287));
832 test_expression("Microsoft.Quantum.Math.Binom(4, 0)", &Value::Int(1));
833 test_expression("Microsoft.Quantum.Math.Binom(4, 4)", &Value::Int(1));
834}
835
836#[test]
837fn check_square_norm() {
838 test_expression(
839 "Microsoft.Quantum.Math.SquaredNorm([2.0])",
840 &Value::Double(4.0),
841 );
842 test_expression(
843 "Microsoft.Quantum.Math.SquaredNorm([-1.0, 1.0])",
844 &Value::Double(2.0),
845 );
846 test_expression(
847 "Microsoft.Quantum.Math.SquaredNorm([3.0, 4.0])",
848 &Value::Double(25.0),
849 );
850}
851
852#[test]
853fn check_p_norm() {
854 test_expression(
855 "Microsoft.Quantum.Math.PNorm(1.0, [-0.1, 0.2, 0.3])",
856 &Value::Double(0.6),
857 );
858 test_expression(
859 "Microsoft.Quantum.Math.PNorm(1.5, [0.1, -0.2, 0.3])",
860 &Value::Double(0.433_462_287_211_361),
861 );
862 test_expression(
863 "Microsoft.Quantum.Math.PNorm(2.0, [0.1, 0.2, -0.3])",
864 &Value::Double(0.374_165_738_677_394_17),
865 );
866 test_expression(
867 "Microsoft.Quantum.Math.PNorm(3.0, [0.0, 0.0])",
868 &Value::Double(0.0),
869 );
870}
871
872#[test]
873fn check_p_normalized() {
874 test_expression(
875 "Microsoft.Quantum.Math.PNormalized(1.0, [-0.1, 0.2, 0.5])",
876 &Value::Array(
877 vec![
878 Value::Double(-0.125),
879 Value::Double(0.25),
880 Value::Double(0.625),
881 ]
882 .into(),
883 ),
884 );
885 test_expression(
886 "Microsoft.Quantum.Math.PNormalized(2.0, [3.0, 4.0])",
887 &Value::Array(vec![Value::Double(0.6), Value::Double(0.8)].into()),
888 );
889 test_expression(
890 "Microsoft.Quantum.Math.PNormalized(3.0, [0.0, 0.0])",
891 &Value::Array(vec![Value::Double(0.0), Value::Double(0.0)].into()),
892 );
893}
894
895//
896// Complex numbers
897//
898
899#[test]
900fn check_abs_squared_complex() {
901 test_expression(
902 "{
903 import Std.Math.*;
904 AbsSquaredComplex(Complex(1.0,1.0))}",
905 &Value::Double(2.0),
906 );
907 test_expression(
908 "{
909 import Std.Math.*;
910 AbsSquaredComplex(Complex(-3.0,4.0))}",
911 &Value::Double(25.0),
912 );
913}
914
915#[test]
916fn check_abs_complex() {
917 test_expression(
918 "{
919 import Std.Math.*;
920 AbsComplex(Complex(1.0,1.0))}",
921 &Value::Double(2.0_f64.sqrt()),
922 );
923 test_expression(
924 "{
925 import Std.Math.*;
926 AbsComplex(Complex(-3.0,4.0))}",
927 &Value::Double(5.0),
928 );
929}
930
931#[test]
932fn check_arg_complex() {
933 test_expression(
934 "{
935 import Std.Math.*;
936 ArgComplex(Complex(100.0,0.0))}",
937 &Value::Double(0.0),
938 );
939 test_expression(
940 "{
941 import Std.Math.*;
942 ArgComplex(Complex(1.0,1.0))}",
943 &Value::Double(PI / 4.0),
944 );
945}
946
947#[test]
948fn check_abs_squared_complex_polar() {
949 test_expression(
950 "{
951 import Std.Math.*;
952 AbsSquaredComplexPolar(ComplexPolar(1.0,2.0))}",
953 &Value::Double(1.0),
954 );
955 test_expression(
956 "{
957 import Std.Math.*;
958 AbsSquaredComplexPolar(ComplexPolar(5.0,-1.0))}",
959 &Value::Double(25.0),
960 );
961}
962
963#[test]
964fn check_abs_complex_polar() {
965 test_expression(
966 "{
967 import Std.Math.*;
968 AbsComplexPolar(ComplexPolar(1.0,2.0))}",
969 &Value::Double(1.0),
970 );
971 test_expression(
972 "{
973 import Std.Math.*;
974 AbsComplexPolar(ComplexPolar(5.0,-1.0))}",
975 &Value::Double(5.0),
976 );
977}
978
979#[test]
980fn check_arg_complex_polar() {
981 test_expression(
982 "{
983 import Std.Math.*;
984 ArgComplexPolar(ComplexPolar(1.0,2.0))}",
985 &Value::Double(2.0),
986 );
987 test_expression(
988 "{
989 import Std.Math.*;
990 ArgComplexPolar(ComplexPolar(5.0,-1.0))}",
991 &Value::Double(-1.0),
992 );
993}
994
995#[test]
996fn check_negation_c() {
997 test_expression(
998 "{
999 import Std.Math.*;
1000 NegationC(Complex(1.0,2.0))}",
1001 &Value::Tuple(vec![Value::Double(-1.0), Value::Double(-2.0)].into()),
1002 );
1003 test_expression(
1004 "{
1005 import Std.Math.*;
1006 NegationC(Complex(5.0,-1.0))}",
1007 &Value::Tuple(vec![Value::Double(-5.0), Value::Double(1.0)].into()),
1008 );
1009}
1010
1011#[test]
1012fn check_negation_cp() {
1013 test_expression(
1014 "{
1015 import Std.Math.*;
1016 NegationCP(ComplexPolar(1.0,0.0))}",
1017 &Value::Tuple(vec![Value::Double(1.0), Value::Double(PI)].into()),
1018 );
1019 test_expression(
1020 "{
1021 import Std.Math.*;
1022 NegationCP(ComplexPolar(5.0,-PI()/2.0))}",
1023 &Value::Tuple(vec![Value::Double(5.0), Value::Double(PI / 2.0)].into()),
1024 );
1025}
1026
1027#[test]
1028fn check_plus_c() {
1029 test_expression(
1030 "{
1031 import Std.Math.*;
1032 PlusC(Complex(1.0,0.0), Complex(0.0,1.0))}",
1033 &Value::Tuple(vec![Value::Double(1.0), Value::Double(1.0)].into()),
1034 );
1035 test_expression(
1036 "{
1037 import Std.Math.*;
1038 PlusC(Complex(10.0,10.0), Complex(-10.0,10.0))}",
1039 &Value::Tuple(vec![Value::Double(0.0), Value::Double(20.0)].into()),
1040 );
1041}
1042
1043#[test]
1044fn check_plus_cp() {
1045 test_expression(
1046 "{
1047 import Std.Math.*;
1048 PlusCP(ComplexPolar(1.0,0.0), ComplexPolar(1.0,PI()/2.0))}",
1049 &Value::Tuple(vec![Value::Double(2.0_f64.sqrt()), Value::Double(PI / 4.0)].into()),
1050 );
1051 test_expression(
1052 "{
1053 import Std.Math.*;
1054 PlusCP(ComplexPolar(10.0,PI()/4.0), ComplexPolar(10.0,3.0*PI()/4.0))}",
1055 &Value::Tuple(vec![Value::Double(200.0_f64.sqrt()), Value::Double(PI / 2.0)].into()),
1056 );
1057}
1058
1059#[test]
1060fn check_minus_c() {
1061 test_expression(
1062 "{
1063 import Std.Math.*;
1064 MinusC(Complex(1.0,0.0), Complex(0.0,1.0))}",
1065 &Value::Tuple(vec![Value::Double(1.0), Value::Double(-1.0)].into()),
1066 );
1067 test_expression(
1068 "{
1069 import Std.Math.*;
1070 MinusC(Complex(10.0,10.0), Complex(-10.0,10.0))}",
1071 &Value::Tuple(vec![Value::Double(20.0), Value::Double(0.0)].into()),
1072 );
1073}
1074
1075#[test]
1076fn check_minus_cp() {
1077 test_expression(
1078 "{
1079 import Std.Math.*;
1080 MinusCP(ComplexPolar(4.0,0.0), ComplexPolar(1.0,-PI()))}",
1081 &Value::Tuple(vec![Value::Double(5.0), Value::Double(0.0)].into()),
1082 );
1083}
1084
1085#[test]
1086fn check_times_c() {
1087 test_expression(
1088 "{
1089 import Std.Math.*;
1090 TimesC(Complex(2.0,0.0), Complex(3.0,0.0))}",
1091 &Value::Tuple(vec![Value::Double(6.0), Value::Double(0.0)].into()),
1092 );
1093 test_expression(
1094 "{
1095 import Std.Math.*;
1096 TimesC(Complex(3.0,0.0), Complex(0.0,1.0))}",
1097 &Value::Tuple(vec![Value::Double(0.0), Value::Double(3.0)].into()),
1098 );
1099 test_expression(
1100 "{
1101 import Std.Math.*;
1102 TimesC(Complex(1.0,2.0), Complex(3.0,4.0))}",
1103 &Value::Tuple(vec![Value::Double(-5.0), Value::Double(10.0)].into()),
1104 );
1105}
1106
1107#[test]
1108fn check_times_cp() {
1109 test_expression(
1110 "{
1111 import Std.Math.*;
1112 TimesCP(ComplexPolar(1.0,0.0), ComplexPolar(1.0,PI()/2.0))}",
1113 &Value::Tuple(vec![Value::Double(1.0), Value::Double(PI / 2.0)].into()),
1114 );
1115 test_expression(
1116 "{
1117 import Std.Math.*;
1118 TimesCP(ComplexPolar(1.0,PI()/4.0), ComplexPolar(2.0,3.0*PI()/4.0))}",
1119 &Value::Tuple(vec![Value::Double(2.0), Value::Double(PI)].into()),
1120 );
1121}
1122
1123#[test]
1124fn check_pow_c() {
1125 test_expression(
1126 "{
1127 import Std.Math.*;
1128 PowC(Complex(2.0,0.0), Complex(3.0,0.0))}",
1129 &Value::Tuple(vec![Value::Double(8.0), Value::Double(0.0)].into()),
1130 );
1131 test_expression(
1132 "{
1133 import Std.Math.*;
1134 PowC(Complex(0.0,1.0), Complex(0.0,1.0))}",
1135 &Value::Tuple(vec![Value::Double(E.powf(-PI / 2.0)), Value::Double(0.0)].into()),
1136 );
1137}
1138
1139#[test]
1140fn check_pow_cp() {
1141 test_expression(
1142 "{
1143 import Std.Math.*;
1144 PowCP(ComplexPolar(2.0,0.0), ComplexPolar(3.0,0.0))}",
1145 &Value::Tuple(vec![Value::Double(8.0), Value::Double(0.0)].into()),
1146 );
1147}
1148
1149#[test]
1150fn check_divide_by_c() {
1151 test_expression(
1152 "{
1153 import Std.Math.*;
1154 DividedByC(Complex(1.0,0.0), Complex(2.0,0.0))}",
1155 &Value::Tuple(vec![Value::Double(0.5), Value::Double(0.0)].into()),
1156 );
1157 test_expression(
1158 "{
1159 import Std.Math.*;
1160 DividedByC(Complex(3.0,0.0), Complex(0.0,1.0))}",
1161 &Value::Tuple(vec![Value::Double(0.0), Value::Double(-3.0)].into()),
1162 );
1163 test_expression(
1164 "{
1165 import Std.Math.*;
1166 DividedByC(Complex(1.0,2.0), Complex(3.0,4.0))}",
1167 &Value::Tuple(vec![Value::Double(0.44), Value::Double(0.08)].into()),
1168 );
1169}
1170
1171#[test]
1172fn check_devide_by_cp() {
1173 test_expression(
1174 "{
1175 import Std.Math.*;
1176 DividedByCP(ComplexPolar(1.0,0.0), ComplexPolar(1.0,PI()/2.0))}",
1177 &Value::Tuple(vec![Value::Double(1.0), Value::Double(-PI / 2.0)].into()),
1178 );
1179 test_expression(
1180 "{
1181 import Std.Math.*;
1182 DividedByCP(ComplexPolar(1.0,PI()/4.0), ComplexPolar(2.0,3.0*PI()/4.0))}",
1183 &Value::Tuple(vec![Value::Double(0.5), Value::Double(-PI / 2.0)].into()),
1184 );
1185}
1186
1187//
1188// Fixed point
1189//
1190
1191#[test]
1192fn check_smallest_fixed_point() {
1193 test_expression(
1194 "Microsoft.Quantum.Math.SmallestFixedPoint(1,0)",
1195 &Value::Double(-1.0),
1196 );
1197 test_expression(
1198 "Microsoft.Quantum.Math.SmallestFixedPoint(0,1)",
1199 &Value::Double(-0.5),
1200 );
1201 test_expression(
1202 "Microsoft.Quantum.Math.SmallestFixedPoint(10,5)",
1203 &Value::Double(-512.0),
1204 );
1205}
1206
1207#[test]
1208fn check_largest_fixed_point() {
1209 test_expression(
1210 "Microsoft.Quantum.Math.LargestFixedPoint(1,0)",
1211 &Value::Double(0.0),
1212 );
1213 test_expression(
1214 "Microsoft.Quantum.Math.LargestFixedPoint(0,1)",
1215 &Value::Double(0.0),
1216 );
1217 test_expression(
1218 "Microsoft.Quantum.Math.LargestFixedPoint(10,5)",
1219 &Value::Double(511.96875),
1220 );
1221}
1222