microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
9c33427155ee7a0d2f2beebc2f03d7c4609b6e4f

Branches

Tags

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

Clone

HTTPS

Download ZIP

library/src/tests/math.rs

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