-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPCM20210805_SICP_1.2.5_GreatestCommonDivisors.jl
2340 lines (1872 loc) · 82.7 KB
/
PCM20210805_SICP_1.2.5_GreatestCommonDivisors.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
### A Pluto.jl notebook ###
# v0.20.4
using Markdown
using InteractiveUtils
# ╔═╡ d3577a0d-ec2b-4bec-b330-eebab7c35f1e
begin
using Pluto
using Plots
using LaTeXStrings
using GraphRecipes
#----------------------------------------------------------------
println("pkgversion(Pluto) = ", pkgversion(Pluto))
println("pkgversion(Plots) = ", pkgversion(Plots))
println("pkgversion(LaTeXStrings) = ", pkgversion(LaTeXStrings))
println("pkgversion(GraphRecipes) = ", pkgversion(GraphRecipes))
end # begin
# ╔═╡ cea33580-f5f4-11eb-292b-3d35bf7a4518
md"
===================================================================================
#### SICP: [1.2.5 Greatest Common Divisors](https://sarabander.github.io/sicp/html/1_002e2.xhtml#g_t1_002e2_002e5)
##### file: PCM20210805\_SICP\_1.2.5\_GreatestCommonDivisors
##### Julia/Pluto.jl (1.11.3/0.20.4) code by PCM *** 2025/01/25 ***
===================================================================================
"
# ╔═╡ 42c23ec6-f975-4e6a-bb57-b241df46bf43
md"
##### 0. Introduction
*... the Euclidean algorithm, ... or Euclid's algorithm, is an efficient method for computing the greatest common divisor (GCD) of two integers, the largest number that divides them both without a remainder. It is named after the ancient Greek mathematician Euclid, who first described it in his Elements (c. 300 BC). It is an example of an algorithm, a step-by-step procedure for performing a calculation according to well-defined rules, and is one of the oldest algorithms in common use. It can be used to reduce fractions to their simplest form, and is a part of many other number-theoretic and cryptographic calculations.*([*Wikipedia*](https://en.wikipedia.org/wiki/Euclidean_algorithm))
"
# ╔═╡ 491a8572-cfa8-4bbb-89f6-c5fa6de0e633
md"
---
##### 1. Topics
- *Renaming* of functions
- *functions* $mod, rem, remainder$
- *type* $Rational$
- *parametrized* type $Rational\{Int64\}$
- *transformation* of *Boolean* expressions
- *Lamé's theorem*
- *big*-$O$ of $gcd(n, m)$
- case analysis $if ... else ... end$
- *output* $println$
- string *interpolation* with $
"
# ╔═╡ 86fe0183-5901-4199-a33e-ad7919fbbadb
md"
---
##### 2. Libraries
"
# ╔═╡ 6e72fc42-e689-46b6-9028-f28dfc9d6eaf
md"
##### 3. SICP-Scheme-like *functional* Julia
###### 3.1 Definitions
Here we provide definitions with increasing complexity:
- *The greatest common divisor (GCD) of two integers a and b is defined to be the largest integer that divides both a and b with no remainder.*(SICP, 196, 2016)
This *informal* definition in SICP postulates that $a, b$ are two *integers*. This in contrast to the Scheme-script provided by SICP which expects two *nonnegative* integers. For other arguments the script may fail.
Another definition includes *negative* integers:
- *...the greatest common divisor (GCD), ..., of two or more integers, which are not all zero, is the largest positive integer that divides each of the integers.* ([*Wikipedia*](https://en.wikipedia.org/wiki/Greatest_common_divisor))
This definition does not cover the cases where inputs are *zero*. So we quote a further definition. This includes the specification of a *divisor* or *factor* $d$:
- *The greatest common divisor (GCD) of integers a and b, at least one of which is nonzero, is the greatest positive integer d such that d is a divisor of both a and b; that is, there are integers e and f such that a = de and b = df, and d is the largest such integer.*
- *When one of a and b is zero, the GCD is the absolute value of the nonzero integer: $gcd(a, 0) = gcd(0, a) = |a|$. This case is important as the terminating step of the Euclidean algorithm.*([Wikipedia](https://en.wikipedia.org/wiki/Greatest_common_divisor))
This definition leaves out the case where $gcd(0, 0)$:
- *The above definition is unsuitable for defining $gcd(0, 0)$, since there is no greatest integer $n$ such that $0 × n = 0$. However, zero is its own greatest divisor if greatest is understood in the context of the divisibility relation, so $gcd(0, 0)$ is commonly defined as $0$.*([Wikipedia](https://en.wikipedia.org/wiki/Greatest_common_divisor))
Now we can combine all cases for $a, b, d, e, f \in \mathbb N$:
$gcd(a, b) =
\begin{cases}
0 & \text{if } a = b = 0 \\
b & \text{if } a = 0 \\
a & \text{if } b = 0 \\
arg\underset{d}max \left(a = d\cdot e, b = d \cdot f \right)
\end{cases}$
"
# ╔═╡ 401f5a11-12b2-4733-8c10-109f0d9abacc
md"
---
###### 3.2 Euclid's Algorithm
The above case analysis leads directly to a correct but not very efficient algorithm. We are looking for the *greatest common divisor* $d$:
$arg\underset{d}max \left(a = d\cdot e, b = d \cdot f \right).$
This *gcd* $d$ remains the same when we reduce the greater argument by subtraction $a - b$ if $a > b$:
$a - b = d \cdot e - d \cdot f = d(e - f).$
Now we are looking for partial *reduced* arguments:
$arg\underset{d}max \left(a - b = d(e - f), b = d f \right).$
This leads directly to a *tail recursive* algorithm with *subtraction* as a main *decreasing* operation.
This function is correct for $a, b \in \mathbb N \text{ with } a \ge b > 0$. It *will keep subtracting the smaller argument from the larger until hitting a boundary* (Rawlins, 1992, p.363)
$gcd_{Euclid}(a, b) :=
\begin{cases}
0 & \text{if } a = b = 0 \\
b & \text{if } a = 0 \\
a & \text{if } b = 0 \\
1 & \text{if } (a = 1) \lor (b = 1) \\
gcd_{Euclid}(-(a, b), b) & \text{if } a \ge b > 1 \\
gcd_{Euclid}(a, -(b, a)) & \text{if } b \ge a > 1 \\
\end{cases}$
Using *subtraction* is not very efficient in languages without [*tco*](https://en.wikipedia.org/wiki/Tail_call) because the danger of *stack overflow*.
The implementation is:
"
# ╔═╡ bba620c5-3ec8-4c1c-be62-3ee5d4610555
function myEuklidsGCD(a, b) # a ≥ b ≥ 0
#--------------------------------------------------------------------------
==(a, 0) && ==(b, 0) ? 0 :
==(a, 0) ? b :
==(b, 0) ? a :
==(a, 1) || ==(b, 1) ? 1 :
≥(a, b) && >(b, 1) ? myEuklidsGCD(-(a, b), b) :
≥(b, a) && >(a, 1) ? myEuklidsGCD(a, -(b, abs(a))) :
error("condition a ≥ b ≥ 0 ignored")
#--------------------------------------------------------------------------
end # function EuklidsGCD
# ╔═╡ 15e862ef-8cc7-4bc9-add5-9f9856c2c17e
myEuklidsGCD(0, 0), myEuklidsGCD(1, 1) # ==> (0, 1) --> :)
# ╔═╡ 9db61e2e-69c7-49b5-b499-8e19ca0e73da
myEuklidsGCD(6, 0), myEuklidsGCD(0, 6) # ==> (6, 6) --> :)
# ╔═╡ fbf4a874-f02c-4b44-8181-7e0625ac31e2
myEuklidsGCD(6, 9), myEuklidsGCD(9, 6) # ==> (3, 3) --> :)
# ╔═╡ 7f5ecaab-4160-4475-a91d-a1881351e8f6
myEuklidsGCD(206, 40) # ==> 2 --> :) SICP's example
# ╔═╡ 07ffa78d-50f3-4910-aaf4-6f98112865d0
md"
**269, 271** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ 825c2a1f-885b-4fe5-bcc5-c8ae5a14a7c5
myEuklidsGCD(269, 271) # ==> 1 --> :)
# ╔═╡ 6edf7ce7-3a8a-4af2-964a-8dfa5ed282e9
md"
**7907 7919** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ 4a5746da-d4be-486f-b955-8b226ee264ac
myEuklidsGCD(7907, 7919) # ==> 1 --> :)
# ╔═╡ 761b3197-1d94-447f-8e9a-965e6d650854
md"
###### *difficult* problems lead to *stack overflow*
"
# ╔═╡ 570bd207-d64a-4bb6-b1e9-7010e6928202
# euklidsGCD(987654321, 123456789),euklidsGCD(-987654321, 123456789) # stack overflow
# ╔═╡ eec014b2-522f-4f54-aa4f-2912dcbd3e24
# euklidsGCD(987654321, -123456789), euklidsGCD(-987654321, -123456789) # overflow
# ╔═╡ 23b966a5-54ac-4175-a6fe-cac6185bbb7a
md"
---
###### 3.3 [*SICP's gcd*-Algorithm](https://mitp-content-server.mit.edu/books/content/sectbyfn/books_pres_0/6515/sicp.zip/full-text/book/book-Z-H-11.html#%_sec_1.2.5) as a *Generic* (*Polymorphic*) *Tail-Recursive* Algorithm
The algorithm presented in SICP substitutes *subtraction* by computing the *remainder* $rem = a\ mod\ b.$
This function is correct for $a, b \in \mathbb Z$ and even $a, b \in \mathbb Q$ if we replace $a \text{ by } abs(a)$ !
$gcd_{SICP}(a, b) :=
\begin{cases}
|a| & \text{if } b = 0 \\
gcd_{SICP}(b, r(a, b)) & \text{where } r = remainder(a, b) = a \mod b \\
\end{cases}$
In cases where $a, b \not\in \mathbb N$ the program fails. This happens e.g. when $(b < 0) \lor (a < 0) \land (b = 0)$.
"
# ╔═╡ 22ff69e2-4a1e-4422-ba08-60b4a2f1c3aa
function sicpGCD(a, b) # fails, e.g. when b is negative or (a < 0) and (b = 0)
#-----------------------------------------------------------------------------
remainder = rem # local renaming
#-----------------------------------------------------------------------------
==(b, 0) ?
abs(a) : # nonSICP: replacement of a by abs(a)
sicpGCD(b, remainder(a, b))
#-----------------------------------------------------------------------------
end # function SICPsGCD
# ╔═╡ b2fd82ec-d1be-43d8-ad9a-702c8052d8d8
sicpGCD(0, 0)
# ╔═╡ 28f7b82d-780d-43c9-83aa-ceb9e579817d
sicpGCD(6, 0), sicpGCD(-6, 0) # ==> (6, 6) --> :)
# ╔═╡ 9383d9cf-3ef4-4696-a0df-273d6b1372bb
sicpGCD(0, 6), sicpGCD(0, -6) # ==> (6, 6) --> :)
# ╔═╡ 84067cf7-71c5-4183-ac1c-37bf761f33ce
sicpGCD(6, 9), sicpGCD(-6, 9) # ==> (3, 3) --> :)
# ╔═╡ ba182453-1e0a-4ddb-8347-21528a9cf4e0
sicpGCD(6, -9), sicpGCD(-6, 9), sicpGCD(-6, -9) # ==> (3, 3, 3) --> :)
# ╔═╡ 82c3d9ae-8614-4ade-a461-af3cbfe19463
sicpGCD(9, 6), sicpGCD(-9, 6) # ==> (3, 3) --> :)
# ╔═╡ 23c81845-b61c-4cc6-881b-fc37a4793dbf
sicpGCD(9, -6), sicpGCD(-9, 6), sicpGCD(-9, -6) # ==> (3, 3, 3) --> :)
# ╔═╡ 316cca38-a8e4-4a30-9635-0b3c0c19808d
sicpGCD(21, 13)
# ╔═╡ 8ee624a2-2069-42ba-8591-f69ae9e885c9
sicpGCD(206, 40) # ==> 2 --> :) SICP's example
# ╔═╡ d1cc56d5-3fec-4cd5-a4d0-788c8a2e56db
sicpGCD(40, 206) # ==> 2 --> :) SICP's example
# ╔═╡ 10448f52-1fc8-409b-b4bc-9ef231155b8c
md"
**269, 271** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ 1fbfa230-9209-4506-9bae-88cd25820bae
sicpGCD(269, 271), sicpGCD(-269, 271), sicpGCD(269, -271), sicpGCD(-269, -271)
# ╔═╡ 6ebf2de0-13f2-46f3-b713-fbf01af53080
md"
**7907 7919** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ f7ad98ed-87dd-4a44-ae07-51267eb7abaa
sicpGCD(7907, 7919), sicpGCD(-7907, 7919), sicpGCD(7907, -7919), sicpGCD(-7907, -7919)
# ╔═╡ 83782367-d27d-4aa9-8e6b-4ec8ff6aead9
md"
###### Difficult Problems
"
# ╔═╡ 8d4b0b84-b5e5-412f-92be-57471fb27a96
sicpGCD(987654321, 123456789), sicpGCD(-987654321, 123456789) # ==> (9, 9) --> :)
# ╔═╡ fcaf8363-d5bd-465c-8045-c08655fd5313
sicpGCD(987654321, -123456789), sicpGCD(-987654321, -123456789) # ==> (9, 9) --> :)
# ╔═╡ f17491ba-332e-47ff-a550-0f3e9d0f5b4a
md"
###### Rational Input: $a, b \in \mathbb Q$
"
# ╔═╡ e1163af9-2c3f-4361-964d-1febb18c0b10
sicpGCD(2//3, 2), sicpGCD(2//3, -2) # ==> (2//3, 2//3) --> :)
# ╔═╡ 51ef4341-3263-4c89-b8e7-78a8fb8ec6c1
sicpGCD(-2//3, 2), sicpGCD(-2//3, -2) # ==> (2//3, 2//3) --> :)
# ╔═╡ c1b1f764-02da-487b-be8a-1e4582643806
sicpGCD(72//120, 42//70) # ==> 3//5
# ╔═╡ f9f7dfe7-c3db-47be-b079-62fa873f8f4b
md"
###### 3.4 *Generic* (*Polymorphic*) *Tail-recursive* $gcd$ for *Integer* and *Rational* Inputs (Definition 3.2)
This specification is an extension of the specification in *3.1*. It is correct for *integers* $a, b \in \mathbb Z$ and even for *rational* numbers $a, b \in \mathbb Q$. We transform the *negation* of the four *stop* conditions into the *run* condition of the the iterative $while$ loop in *4,1, 4.2*.
$gcd(a, b) =
\begin{cases}
0 & \text{if } a = b = 0 \\
|b| & \text{if } a = 0 \\
|a| & \text{if } b = 0 \\
1 & \text{if } (a = 1) \lor (b = 1) \\
arg\underset{d}max \left(a = d\cdot e, b = d \cdot f \right)
\end{cases}$
where: $d \in \mathbb N \text{ and } a, b \in \mathbb Q$
"
# ╔═╡ b7bb02fa-22ad-46f5-9e1b-30fe6e37b157
function myGCD(a, b) # gcd is the Julia function
#------------------------------------------------------
remainder = mod # local renaming
#------------------------------------------------------
==(a, 0) && ==(b, 0) ? 0 :
==(a, 0) ? abs(b) :
==(b, 0) ? abs(a) :
==(a, 1) || ==(b, 1) ? 1 :
myGCD(b, remainder(a, b))
end # function myGCD
# ╔═╡ 82564968-efcf-4656-a81b-dd30e365bcc1
myGCD(0, 0)
# ╔═╡ 961ed92e-669e-42e0-9c80-77a04c2f5f03
myGCD(6, 0), myGCD(-6, 0) # ==> (6, 6) --> :)
# ╔═╡ 78426838-2478-4fc0-8d1b-bdff3b78c02b
myGCD(0, 6), myGCD(0, -6) # ==> (6, 6) --> :)
# ╔═╡ b1635893-2d53-4dd6-879b-ce6fe2d79b29
myGCD(6, 9), myGCD(-6, 9) # ==> (3, 3) --> :)
# ╔═╡ 8a42c258-4e28-44c9-aae5-c6a9e933e9bd
myGCD(6, 9), myGCD(6, -9) # ==> (3, 3) --> :)
# ╔═╡ b379a394-dbb8-4e9b-8546-a82d52cbb94d
myGCD(-6, -9) # ==> 3 --> :)
# ╔═╡ baed6744-f6e3-4862-898d-9d1c8f84ec65
myGCD(206, 40) # ==> 2 --> :) SICP's example
# ╔═╡ f5f1726e-be92-4e6a-bc03-573401d8457b
md"
**269, 271** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ 3be00d9d-a76c-46a9-99cc-f57f1e1ae285
myGCD(269, 271), myGCD(-269, 271), myGCD(269, -271), myGCD(-269, -271)
# ╔═╡ 15522f43-48ad-4067-b0c2-1cf82e177ac2
md"
**7907 7919** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ 5ec142a1-4148-490f-851a-e9c1211057ff
myGCD(7907, 7919), myGCD(-7907, 7919), myGCD(7907, -7919), myGCD(-7907, -7919)
# ╔═╡ 6c25b150-f081-4c86-8815-238e71bfefe6
md"
###### *difficult* problems
"
# ╔═╡ fd2b06f5-520d-45f0-b46c-de0f1da99aca
myGCD(987654321, 123456789), myGCD(-987654321, 123456789) # ==> (9, 9) --> :)
# ╔═╡ 22eb7d2d-6eaf-4406-a2af-fce6734e04cc
myGCD(987654321, -123456789), myGCD(-987654321, -123456789) # ==> (9, 9) --> :)
# ╔═╡ d98f169d-2155-4b5f-b6bb-1b1902ee3d70
md"
###### Rational Input: $a, b \in \mathbb Q$
"
# ╔═╡ e10235c1-b81b-474c-a6ee-17162611fdc1
myGCD(2//3, 2), myGCD(2//3, -2) # ==> (2//3, 2//3) --> :)
# ╔═╡ db38373d-790a-4ca9-8a2e-972c28950ee2
myGCD(-2//3, 2), myGCD(-2//3, -2) # ==> (2//3, 2//3) --> :)
# ╔═╡ 0e41dd63-022e-491d-9934-cf6d9a99f1db
myGCD(72//120, 42//70) # ==> 3//5
# ╔═╡ fcb61a42-36eb-4b1a-8e8d-79f57e536864
md"
---
##### 4. Idiomatic *Imperative* Julia
###### 4.1 Iterative Algorithm $myGCD2$
... with $while$ and parallel assignment
To get the *iterative* transformation of the *tail-recursive* function $myGCD$ in *3.4* we have to transform the *stop-conditions* of $myGCD$ into the *run-condition* of the $while$-loop here. The *run*-condition is the negation of the *stop*-condition:
The *stop*-condition of $myGCD$ is a *disjunction*:
$((a = 0) \land (b = 0)) \lor (a = 0) \lor (b = 0) \lor \left((a =1) \lor (b = 1)\right).$
The *run*-condition of the $while$-loop is the *negation* of the *stop*-condition:
$\neg[((a = 0) \land (b = 0) \lor (a = 0) \lor (b = 0) \lor \left((a =1) \lor (b = 1)\right)] =$
$= \neg((a = 0) \land (b = 0)) \neg \land (a = 0) \neg\land (b = 0) \neg\land \left((a =1) \lor (b = 1)\right)=$
$= (\neg(a = 0) \neg\lor (b = 0)) \neg \land (a = 0) \neg\land (b = 0) \land\neg(a =1) \land \neg (b = 1)=$
$= ((a \neq 0) \lor (b \neq 0)) \land (a \neq 0) \land (b \neq 0) \land(a \neq 1) \land (b \neq 1)=$
$= (a \neq 0) \land (a \neq 0) \land (b \neq 0) \land(a \neq 1) \land (b \neq 1) \lor ...$
$...\lor (b \neq 0) \land (a \neq 0) \land (b \neq 0) \land(a \neq 1) \land (b \neq 1)=$
$=(a \neq 0) \land (b \neq 0) \land(a \neq 1) \land (b \neq 1) \lor ...$
$...\lor (a \neq 0) \land (b \neq 0) \land(a \neq 1) \land (b \neq 1)=$
$=(a \neq 0) \land (b \neq 0) \land(a \neq 1) \land (b \neq 1)\;\; \square$
"
# ╔═╡ 3faf3840-71d0-4b37-893f-99cca1c0f3eb
function myGCD2(a, b)
#--------------------------------------------------------
# while run condition is negated stop condition of myGCD
while !=(a, 0) && !=(b, 0) && !=(a, 1) && !=(b, 1)
a, b = b, rem(a, b) # parallel assignment
end # while
#--------------------------------------------------------
==(a, 0) && ==(b, 0) ? 0 :
==(a, 0) ? abs(b) :
==(b, 0) ? abs(a) :
==(a, 1) || ==(b, 1) ? 1 : error("missing case")
end # function myGCD2
# ╔═╡ 7f6a7544-b5a7-47d6-8b4e-4b6e2ad8c9c6
myGCD2(0, 0), myGCD2(-0, -0)
# ╔═╡ 11b064cb-73c0-449c-939c-918f87d8719d
myGCD2(6, 0), myGCD2(-6, 0) # ==> (6, 6) --> :)
# ╔═╡ bbc0be78-e798-4c4e-ab62-6bbe66feff50
myGCD2(0, 6), myGCD2(0, -6) # ==> (6, 6) --> :)
# ╔═╡ 51a6e03d-54aa-4e40-b49e-3d18f25dcc56
myGCD2(9, 3), myGCD2(-9, 3), myGCD2(9, -3), myGCD2(-9, -3) # ==> (3, 3, 3, 3) --> :)
# ╔═╡ cf46b648-8c3d-4f27-8613-867bc1f98f1a
myGCD2(3, 9), myGCD2(3, -9), myGCD2(-3, 9), myGCD2(-3, -9) # ==> (3, 3, 3, 3) --> :)
# ╔═╡ 5f3dfe93-b54d-431b-8d71-8c9319962a97
myGCD2(206, 40) # ==> 2 --> :) SICP's example
# ╔═╡ be1224ce-25ea-4cc5-9f93-d20dbf530fa4
md"
**269, 271** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ d614584b-a54c-4fa5-8276-19961301c7c8
myGCD2(269, 271), myGCD2(-269, 271), myGCD2(269, -271), myGCD2(-269, -271)
# ╔═╡ fc72cd2b-abb9-4d12-a0ff-c3b1f8fd706f
myGCD2(271, 269), myGCD2(271, -269), myGCD2(-271, 269), myGCD2(-271, -269)
# ╔═╡ 158f96db-81d1-4ff9-98d4-b3dea1a0a0c9
md"
**7907 7919** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ 837b66a7-0fd6-4775-90c1-5f7ee26694c5
myGCD2(7907, 7919), myGCD2(-7907, 7919), myGCD2(7907, -7919), myGCD2(-7907, -7919)
# ╔═╡ f6285029-bdd9-4147-b373-30ba9c71d99f
myGCD2(7919, 7907), myGCD2(7919, -7907), myGCD2(-7919, 7907), myGCD2(-7919, -7907)
# ╔═╡ 235a2931-fad7-4b77-aa73-1d1bc6c76554
md"
###### *difficult* problems
"
# ╔═╡ f6cd510f-90b1-46a0-969b-dc577b47c951
myGCD2(987654321, 123456789), myGCD2(-987654321, 123456789) # ==> (9, 9) --> :)
# ╔═╡ e2c8c871-ae11-42ac-9ac7-f03ace653353
myGCD2(987654321, -123456789), myGCD2(-987654321, -123456789) # ==> (9, 9) --> :)
# ╔═╡ 993f7649-5936-4045-9355-d56d80c11252
md"
###### Rational Input: $a, b \in \mathbb Q$
"
# ╔═╡ f5cd25aa-baf9-42b7-a2ae-0e95a009420a
myGCD2(2//3, 2), myGCD2(2//3, -2) # ==> (2//3, 2//3) --> :)
# ╔═╡ 34b2dc9a-981a-422c-ae89-c7d86c5869c7
myGCD2(-2//3, 2), myGCD2(-2//3, -2) # ==> (2//3, 2//3) --> :)
# ╔═╡ 258af27c-b40d-47ef-9194-e84d9b13db3a
myGCD2(72//120, 42//70) # ==> 3//5
# ╔═╡ 15bc2039-0a35-4071-bfce-54932b75959a
md"
---
###### 4.3 Iterative Algorithm $myGCD3$
... with $isone, iszero$ and parallel assignment
"
# ╔═╡ 06312cce-0bea-490a-ae59-8d94548c2e7e
function myGCD3(a, b)
#-------------------------------------------------------
while !(iszero(a) || iszero(b) || isone(a) || isone(b))
a, b = b, rem(a, b) # parallel assignment
end # while
#-------------------------------------------------------
iszero(a) && iszero(b) ? 0 :
iszero(a) ? abs(b) :
iszero(b) ? abs(a) :
isone(a) || isone(b) ? 1 : error("missing case")
end # function myGCD3
# ╔═╡ ec4712f8-8348-45af-949d-a7555ec35cd9
myGCD3(0, 0), myGCD3(-0, -0) # ==> (0, 0) --> :)
# ╔═╡ 7a0b869e-8f8b-4b04-8b23-902f3025b9eb
myGCD3(6, 0), myGCD3(-6, 0) # ==> (6, 6) --> :)
# ╔═╡ 11c8eb97-363a-47e7-8363-8bde4da89d89
myGCD3(0, 6), myGCD3(0, -6) # ==> (6, 6) --> :)
# ╔═╡ 7dd27471-7201-45d2-adbd-653061a02fef
myGCD3(9, 3), myGCD3(-9, 3), myGCD3(9, -3), myGCD3(-9, -3) # ==> (3, 3, 3, 3) --> :)
# ╔═╡ a7bb1b00-ac1e-48b5-b529-3d7efcd6f273
myGCD3(3, 9), myGCD3(3, -9), myGCD3(-3, 9), myGCD3(-3, -9) # ==> (3, 3, 3, 3) --> :)
# ╔═╡ 4852ac5e-9163-4fe5-a83f-4d23283674f6
myGCD3(206, 40) # ==> 2 --> :) SICP's example
# ╔═╡ 57a1dac8-94fd-4f4b-8664-1230320e4790
md"
**269, 271** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ 0123f711-b3af-4404-997c-e07866826451
myGCD3(269, 271), myGCD3(-269, 271), myGCD3(269, -271), myGCD3(-269, -271)
# ╔═╡ 6540922f-698b-4dba-a26d-ba594e8d0c51
myGCD3(271, 269), myGCD3(271, -269), myGCD3(-271, 269), myGCD3(-271, -269)
# ╔═╡ 71a43de5-b947-4acb-bac3-b6d76c1a5256
md"
**7907 7919** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ 1d080491-d6d7-46be-864d-e922005ce7c8
myGCD3(7907, 7919), myGCD3(-7907, 7919), myGCD3(7907, -7919), myGCD3(-7907, -7919)
# ╔═╡ c472a1c8-3f78-4153-b0f2-a0ac36d31845
myGCD3(7919, 7907), myGCD3(7919, -7907), myGCD3(-7919, 7907), myGCD3(-7919, -7907)
# ╔═╡ fb59f402-ccd9-4b11-955e-b20b69ed0180
md"
###### *difficult* problems
"
# ╔═╡ 6ddc8b71-329f-4d4d-a6a9-bba549bf51eb
myGCD3(987654321, 123456789), myGCD3(-987654321, 123456789) # ==> (9, 9) --> :)
# ╔═╡ f41268e0-032a-4082-b456-d782a99c4dc2
myGCD3(987654321, -123456789), myGCD3(-987654321, -123456789) # ==> (9, 9) --> :)
# ╔═╡ 37179d18-d6d3-463c-9af2-8d04568e186f
md"
###### Rational Input: $a, b \in \mathbb Q$
"
# ╔═╡ f7939ab8-66dc-45fe-9c5e-2f5f5fab11c7
myGCD3(2//3, 2), myGCD3(2//3, -2) # ==> (2//3, 2//3) --> :)
# ╔═╡ 0fd881e7-2148-4c0f-a002-8c4a937eab71
myGCD3(-2//3, 2), myGCD3(-2//3, -2) # ==> (2//3, 2//3) --> :)
# ╔═╡ 574e38b6-9c59-4d4c-af42-007670155c60
myGCD3(72//120, 42//70) # ==> 3//5
# ╔═╡ 736211ef-956b-4168-83a4-57bbc444d7e6
md"
---
###### 4.4 Julia's Builtin [*Base.gcd*](https://docs.julialang.org/en/v1/base/math/#Base.gcd)
"
# ╔═╡ 35b018b5-fadd-4f42-abe3-1c0d2d206017
gcd(0, 0) # ==> 0 --> :)
# ╔═╡ e4e78771-abf1-4116-9a64-f1a483914f9e
gcd(6, 0), gcd(-6, 0) # ==> (6, 6) --> :)
# ╔═╡ 758904df-59f0-4d6c-83de-e41dba2c0702
gcd(0, 6), gcd(0, -6) # ==> (6, 6) --> :)
# ╔═╡ 219b1495-2f60-4f6c-aa65-a57433d57218
gcd(6, 9), gcd(6, -9) # ==> (3, 3) --> :)
# ╔═╡ 105ab626-3b06-4e19-b112-630caa7546cf
gcd(206, 40) # ==> 2 --> :) SICP's example
# ╔═╡ 46f83d7a-4690-43a3-9737-66ddf5de6b2b
md"
**269, 271** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ 402c9d2f-480a-43f6-8b28-a39a286d2359
gcd(7907, 7919), gcd(-7907, 7919), gcd(7907, -7919), gcd(-7907, -7919)
# ╔═╡ 66151e66-3136-48b6-81f4-e1e5ff7ffc2b
md"
**7907 7919** ; both are *adjacent* [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers)
"
# ╔═╡ 8bf38756-d278-4f71-ad07-1a5905e3b488
gcd(7919, 7907), gcd(7919, -7907), gcd(-7919, 7907), gcd(-7919, -7907)
# ╔═╡ f4655616-a0a7-470f-8688-43098165d802
md"
###### *difficult* problems
"
# ╔═╡ 1fbfb94a-3167-41f3-a4c5-b5df441e02eb
gcd(987654321, 123456789), gcd(-987654321, 123456789) # ==> (9, 9) --> :)
# ╔═╡ 7eb9b02f-deb0-48bb-b309-1969754095fb
gcd(987654321, -123456789), gcd(-987654321, -123456789) # ==> (9, 9) --> :)
# ╔═╡ 04e0dd59-266e-419d-a663-a1d1e69587bb
md"
###### Rational Input: $a, b \in \mathbb Q$
"
# ╔═╡ 0e3ec5a5-a107-4a29-a7dc-c8dee05aafe2
gcd(1//3, 2//3), gcd(1//3, -2//3) # ==> (1//3, 1//3) --> :)
# ╔═╡ a071d0e3-f252-401c-b16b-1f56f581c313
gcd(2//3, 2), gcd(2//3, -2) # ==> (2//3, 2//3) --> :)
# ╔═╡ 44554b30-90e5-45dd-93ee-8490dc0cb450
gcd(-2//3, 2), gcd(-2//3, -2) # ==> (2//3, 2//3) --> :)
# ╔═╡ db327c24-5443-481d-b2c9-ba7c01b2e46e
typeof(gcd(2//3, 2)) # parametrized type
# ╔═╡ 46897383-0c6c-4c18-b1d7-5e1c6a63dbe0
md"
---
##### 5. *big*-$O$ *complexity* of recursive $gcd$ with $remainder$-*reduction*
###### 5.1 Derivation
By use of [*Lamé*](https://en.wikipedia.org/wiki/Gabriel_Lam%C3%A9)'s theorem (c.f. SICP, 1996, 2016) we can determine an *upper limit* for the number of steps $k = \#steps(gcd(n, m)) \;;\; n>m$ the tail-recursive gcd(n, m) needs computing the *greatest common divisor* of $n, m\;;\; n>m$.
From this *upper limit* for any $k$ we can determine *big*-$O(\#steps(gcd(n, m)))= O(\log_\phi m) = O(\log m)$.
"
# ╔═╡ cc0d5940-5a9b-4515-bdb0-a01e15a975d4
md"
*Lamé*'s theorem states (SICP, 1996, 2016):
$\text{ If } \#steps(gcd(n, m)) = k$
$\text{ then } min(n, m) \ge fib(k).$
As we have seen before we can approximate $fib(k)$ by a *closed* expression:
$min(n, m) \ge fib(k) \approx \left\lceil \frac{\phi^k}{\sqrt 5} \right\rfloor.$
Taking *logarithms* is:
$\log min(n, m) \ge \left\lceil k \log \phi - \log \sqrt 5 \right\rfloor$
and
$\log min(n, m) + \log \sqrt 5 \ge \left\lceil k \log \phi \right\rfloor$
which is:
$\frac{\log min(n, m)}{\log \phi} + \frac{\log \sqrt 5}{\log \phi} \ge \left\lceil k \right\rfloor$
Changing the basis of *logarithms*:
$\log_\phi min(n, m) + \log_\phi \sqrt 5\ge \left\lceil k \right\rfloor$
So
$O(\log_\phi min(n,m) = O(\log min(n,m)) \ge \#steps(gcd(n,m)) = k.$
"
# ╔═╡ 10766977-40bd-4d71-856e-fa22f4b97b44
md"
###### 5.2 Example
For $gcd(21, 13)$ the number of *reduction* steps is $\#steps(gcd, 13) = k = 6$.
And $min(21, 13) = 13 \ge fib(6) = 8$.
Now, we compute the reduction steps with $sicpGCD2:$
"
# ╔═╡ 2eb0ec22-3e4a-4f8f-a38a-042817d13c8b
function sicpGCD2(n, m, reduct_nr)
#-----------------------------------------------------------------------------
remainder = rem # local renaming
#-----------------------------------------------------------------------------
if iszero(m)
abs(n) # nonSICP: replacement of a by abs(a)
else
reduct_nr += 1
r = remainder(n, m)
println("reduct_nr = $reduct_nr ; n = $n, m = $m, r = $r ;") # interpolation
sicpGCD2(m, r, reduct_nr)
end # if
#-----------------------------------------------------------------------------
end # function SICPsGCD
# ╔═╡ f5fbb73e-7f2f-4d9a-810e-8b9d1f236207
sicpGCD2(21, 13, 0)
# ╔═╡ 2d4206e3-6231-48e9-96fa-89d7a8aaeebd
md"
---
##### 6. Summary
We presented different simple $gcd$-algorithms for *natural*, *integer* and even *rational* numbers. Furthermore we demonstrated how to compute the complexity of *Euclid's algorithm* which is $O(\log min(n, m))$.
"
# ╔═╡ 5cd5cdec-238c-47ae-b079-c25804c6c42e
md"
---
##### References
- **Abelson, H., Sussman, G.J. & Sussman, J.**; [*Structure and Interpretation of Computer Programs*](https://mitp-content-server.mit.edu/books/content/sectbyfn/books_pres_0/6515/sicp.zip/full-text/book/book.html), Cambridge, Mass.: MIT Press, (2/e), 1996; last visit 2025/01/21
- **Abelson, H., Sussman, G.J. & Sussman, J.**; [*Structure and Interpretation of Computer Programs*](https://web.mit.edu/6.001/6.037/sicp.pdf); Cambridge, Mass.: MIT Press, (2/e), 2016; last visit 2025/01/21
- **Rawlins, G.J.E.**; *Compared To What ?*, NY.: Computer Science Press, 1992
- **Wikipedia**; [*Euclidean Algorithm*](https://en.wikipedia.org/wiki/Euclidean_algorithm); last visit 2025/01/21
- **Wikipedia**; [*Greatest Common Divisor*](https://en.wikipedia.org/wiki/Greatest_common_divisor); last visit 2025/01/21
- **Wikipedia**; [*Lamé, Gabriel*](https://en.wikipedia.org/wiki/Gabriel_Lam%C3%A9); last visit 2025/01/25
- **Wikipedia**; [*List of Prime Numbers*](https://en.wikipedia.org/wiki/List_of_prime_numbers); last visit 2025/01/21
- **Wikipedia**; [*Tail Call Optimization*](https://en.wikipedia.org/wiki/Tail_call); last visit 2025/01/22
"
# ╔═╡ 96313012-0e76-42e5-8f76-548c0da1535a
md"
---
###### end of ch. 1.2.5
====================================================================================
This is a **draft** under the [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en) license; Comments, suggestions for improvement and bug reports are welcome: **claus.moebus(@)uol.de**
====================================================================================
"
# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
GraphRecipes = "bd48cda9-67a9-57be-86fa-5b3c104eda73"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Pluto = "c3e4b0f8-55cb-11ea-2926-15256bba5781"
[compat]
GraphRecipes = "~0.5.13"
LaTeXStrings = "~1.4.0"
Plots = "~1.40.9"
Pluto = "~0.20.4"
"""
# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised
julia_version = "1.11.3"
manifest_format = "2.0"
project_hash = "2361d1a808db1daa1baaa2da4ba0784d61fe348d"
[[deps.AbstractTrees]]
git-tree-sha1 = "2d9c9a55f9c93e8887ad391fbae72f8ef55e1177"
uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
version = "0.4.5"
[[deps.Adapt]]
deps = ["LinearAlgebra", "Requires"]
git-tree-sha1 = "50c3c56a52972d78e8be9fd135bfb91c9574c140"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "4.1.1"
weakdeps = ["StaticArrays"]
[deps.Adapt.extensions]
AdaptStaticArraysExt = "StaticArrays"
[[deps.AliasTables]]
deps = ["PtrArrays", "Random"]
git-tree-sha1 = "9876e1e164b144ca45e9e3198d0b689cadfed9ff"
uuid = "66dad0bd-aa9a-41b7-9441-69ab47430ed8"
version = "1.1.3"
[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
version = "1.1.2"
[[deps.ArnoldiMethod]]
deps = ["LinearAlgebra", "Random", "StaticArrays"]
git-tree-sha1 = "d57bd3762d308bded22c3b82d033bff85f6195c6"
uuid = "ec485272-7323-5ecc-a04f-4719b315124d"
version = "0.4.0"
[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
version = "1.11.0"
[[deps.AxisAlgorithms]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"]
git-tree-sha1 = "01b8ccb13d68535d73d2b0c23e39bd23155fb712"
uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950"
version = "1.1.0"
[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
version = "1.11.0"
[[deps.BitFlags]]
git-tree-sha1 = "0691e34b3bb8be9307330f88d1a3c3f25466c24d"
uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35"
version = "0.1.9"
[[deps.Bzip2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "8873e196c2eb87962a2048b3b8e08946535864a1"
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
version = "1.0.8+4"
[[deps.Cairo_jll]]
deps = ["Artifacts", "Bzip2_jll", "CompilerSupportLibraries_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "009060c9a6168704143100f36ab08f06c2af4642"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.18.2+1"
[[deps.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra"]
git-tree-sha1 = "1713c74e00545bfe14605d2a2be1712de8fbcb58"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.25.1"
weakdeps = ["SparseArrays"]
[deps.ChainRulesCore.extensions]
ChainRulesCoreSparseArraysExt = "SparseArrays"
[[deps.CodecZlib]]
deps = ["TranscodingStreams", "Zlib_jll"]
git-tree-sha1 = "bce6804e5e6044c6daab27bb533d1295e4a2e759"
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
version = "0.7.6"
[[deps.ColorSchemes]]
deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"]
git-tree-sha1 = "c785dfb1b3bfddd1da557e861b919819b82bbe5b"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.27.1"
[[deps.ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "b10d0b65641d57b8b4d5e234446582de5047050d"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.5"
[[deps.ColorVectorSpace]]
deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"]
git-tree-sha1 = "a1f44953f2382ebb937d60dafbe2deea4bd23249"
uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4"
version = "0.10.0"
[deps.ColorVectorSpace.extensions]
SpecialFunctionsExt = "SpecialFunctions"
[deps.ColorVectorSpace.weakdeps]
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
[[deps.Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "64e15186f0aa277e174aa81798f7eb8598e0157e"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.13.0"
[[deps.Compat]]
deps = ["TOML", "UUIDs"]
git-tree-sha1 = "8ae8d32e09f0dcf42a36b90d4e17f5dd2e4c4215"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "4.16.0"
weakdeps = ["Dates", "LinearAlgebra"]
[deps.Compat.extensions]
CompatLinearAlgebraExt = "LinearAlgebra"
[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
version = "1.1.1+0"
[[deps.ConcurrentUtilities]]
deps = ["Serialization", "Sockets"]
git-tree-sha1 = "f36e5e8fdffcb5646ea5da81495a5a7566005127"
uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb"
version = "2.4.3"
[[deps.Configurations]]
deps = ["ExproniconLite", "OrderedCollections", "TOML"]
git-tree-sha1 = "4358750bb58a3caefd5f37a4a0c5bfdbbf075252"
uuid = "5218b696-f38b-4ac9-8b61-a12ec717816d"
version = "0.17.6"
[[deps.ConstructionBase]]
git-tree-sha1 = "76219f1ed5771adbb096743bff43fb5fdd4c1157"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
version = "1.5.8"
[deps.ConstructionBase.extensions]
ConstructionBaseIntervalSetsExt = "IntervalSets"
ConstructionBaseLinearAlgebraExt = "LinearAlgebra"
ConstructionBaseStaticArraysExt = "StaticArrays"
[deps.ConstructionBase.weakdeps]
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
[[deps.Contour]]
git-tree-sha1 = "439e35b0b36e2e5881738abc8857bd92ad6ff9a8"
uuid = "d38c429a-6771-53c6-b99e-75d170b6e991"
version = "0.6.3"
[[deps.DataAPI]]
git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.16.0"
[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "1d0a14036acb104d9e89698bd408f63ab58cdc82"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.20"
[[deps.DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"
[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
version = "1.11.0"
[[deps.Dbus_jll]]
deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl"]
git-tree-sha1 = "fc173b380865f70627d7dd1190dc2fce6cc105af"
uuid = "ee1fde0b-3d02-5ea6-8484-8dfef6360eab"
version = "1.14.10+0"
[[deps.DelimitedFiles]]
deps = ["Mmap"]
git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae"
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"
version = "1.9.1"
[[deps.Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
version = "1.11.0"
[[deps.DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.9.3"
[[deps.Downloads]]
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
version = "1.6.0"
[[deps.EarCut_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "e3290f2d49e661fbd94046d7e3726ffcb2d41053"
uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.2.4+0"
[[deps.EpollShim_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl"]
git-tree-sha1 = "8a4be429317c42cfae6a7fc03c31bad1970c310d"
uuid = "2702e6a9-849d-5ed8-8c21-79e8b8f9ee43"
version = "0.0.20230411+1"
[[deps.ExceptionUnwrapping]]
deps = ["Test"]
git-tree-sha1 = "d36f682e590a83d63d1c7dbd287573764682d12a"
uuid = "460bff9d-24e4-43bc-9d9f-a8973cb893f4"
version = "0.1.11"
[[deps.Expat_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl"]
git-tree-sha1 = "e51db81749b0777b2147fbe7b783ee79045b8e99"
uuid = "2e619515-83b5-522b-bb60-26c02a35a201"
version = "2.6.4+3"