mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-21 20:34:07 +00:00
Compare commits
684 Commits
grind_simp
...
grind_modi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc58ef43ae | ||
|
|
8789e5621b | ||
|
|
fbf096510d | ||
|
|
18cc1cec80 | ||
|
|
404b00a584 | ||
|
|
50ddf85b07 | ||
|
|
9107d27368 | ||
|
|
d51a5b920d | ||
|
|
eb013fb90d | ||
|
|
4c44fdb95f | ||
|
|
d63d1188cc | ||
|
|
a31d686ed1 | ||
|
|
a62dabeb56 | ||
|
|
d2eb1bc9f5 | ||
|
|
38608a672e | ||
|
|
86425f655a | ||
|
|
9757a7be53 | ||
|
|
3ce69e4edb | ||
|
|
2dda33ddb2 | ||
|
|
655a39ceb8 | ||
|
|
8d26a9e8b5 | ||
|
|
72e8970848 | ||
|
|
697ea0bc01 | ||
|
|
4d5fb31dfb | ||
|
|
43dc9f45d1 | ||
|
|
dc1ddda473 | ||
|
|
b5555052bd | ||
|
|
e4ca32174c | ||
|
|
d06fff0f13 | ||
|
|
e74e9694fe | ||
|
|
5bb7818355 | ||
|
|
5bc42bf5ca | ||
|
|
aaec0f584c | ||
|
|
db3fb47109 | ||
|
|
c83674bdff | ||
|
|
2652cc18b8 | ||
|
|
62e00fb5a0 | ||
|
|
2324c0939d | ||
|
|
425bebe99e | ||
|
|
a0613f4d12 | ||
|
|
298bd10f54 | ||
|
|
6810d31602 | ||
|
|
3e11f27ff4 | ||
|
|
a78a34bbd7 | ||
|
|
0803f1e77e | ||
|
|
9e47edd0df | ||
|
|
0f1174d097 | ||
|
|
f180eee7bf | ||
|
|
6a3fc281ad | ||
|
|
06e9f4735a | ||
|
|
0f5f2df11f | ||
|
|
aa0cf78d93 | ||
|
|
4f94972ff1 | ||
|
|
37dd26966b | ||
|
|
1feac1ae92 | ||
|
|
3ff195f7b2 | ||
|
|
5478dcf373 | ||
|
|
ad3e975178 | ||
|
|
cd9865b26b | ||
|
|
8c4db341dd | ||
|
|
a6a02fe6b9 | ||
|
|
741347281c | ||
|
|
a06e6e7f4d | ||
|
|
505d5c6013 | ||
|
|
13e8cb5a3a | ||
|
|
2107f45991 | ||
|
|
a72f9429ea | ||
|
|
321af0e02b | ||
|
|
1718ca21cd | ||
|
|
f4ce319f1b | ||
|
|
340c3da6ae | ||
|
|
afbf52896f | ||
|
|
afcf52e623 | ||
|
|
3c40ea2733 | ||
|
|
c95100e8fd | ||
|
|
be4651a772 | ||
|
|
797985e319 | ||
|
|
c9f08de7b3 | ||
|
|
9be2eab93d | ||
|
|
cc5ff2afb1 | ||
|
|
5651192fa2 | ||
|
|
5ccea92a09 | ||
|
|
3fc3f5d240 | ||
|
|
dca16fb58c | ||
|
|
20d66250df | ||
|
|
47632f27f6 | ||
|
|
dfdd682c01 | ||
|
|
8e828216e5 | ||
|
|
92037b5b1b | ||
|
|
a93e315e72 | ||
|
|
902484988e | ||
|
|
c9727c2d19 | ||
|
|
0d9b7fb6b8 | ||
|
|
db43de7b9d | ||
|
|
17f76f3bd7 | ||
|
|
6f69715f0a | ||
|
|
2b34d5b899 | ||
|
|
0881a8872b | ||
|
|
91a2de1e1e | ||
|
|
4a7def9e5f | ||
|
|
dc5766d27a | ||
|
|
a63d483258 | ||
|
|
1f9bba9d39 | ||
|
|
5daf65ec56 | ||
|
|
9d4665a0bf | ||
|
|
6df94385c5 | ||
|
|
82932ec86a | ||
|
|
3d7d35b588 | ||
|
|
fb23d7b45d | ||
|
|
f12177d01e | ||
|
|
68654c231b | ||
|
|
2adc21f28b | ||
|
|
0528696bbe | ||
|
|
51bba5338a | ||
|
|
561a4510b3 | ||
|
|
0e8838df3b | ||
|
|
385daa99a8 | ||
|
|
7595bc0791 | ||
|
|
9c6b698227 | ||
|
|
962ba9649c | ||
|
|
8c8a6021af | ||
|
|
584ed5f33e | ||
|
|
1523ed1cdb | ||
|
|
facc356a0a | ||
|
|
c4b3f303bb | ||
|
|
1448493489 | ||
|
|
f7a251b75f | ||
|
|
5aa706435a | ||
|
|
a581433d8b | ||
|
|
6683d1eb91 | ||
|
|
504d71f268 | ||
|
|
ca4322ff09 | ||
|
|
d32f04ba21 | ||
|
|
0db795a1dc | ||
|
|
d9a73dd1e3 | ||
|
|
e9f6033467 | ||
|
|
0c9bb4b861 | ||
|
|
9b4911f8f6 | ||
|
|
f678b40660 | ||
|
|
890722f571 | ||
|
|
ef1ca99bff | ||
|
|
26fdc1e19a | ||
|
|
0b0d183c1d | ||
|
|
21f5263f2f | ||
|
|
02edc0bd92 | ||
|
|
45affb5e09 | ||
|
|
6a7111ed0e | ||
|
|
6b4c356c5b | ||
|
|
e3947cbe20 | ||
|
|
d6a43a660f | ||
|
|
b2330fee2b | ||
|
|
105879669e | ||
|
|
679df58329 | ||
|
|
d604c16c0e | ||
|
|
44891fe0c0 | ||
|
|
ee699518fa | ||
|
|
1b213835e6 | ||
|
|
22becc78f7 | ||
|
|
e083771b81 | ||
|
|
1a31aa3d2b | ||
|
|
86dc07c20d | ||
|
|
48365b6052 | ||
|
|
d4a5a2c632 | ||
|
|
8d34dfe914 | ||
|
|
a1cf67edc3 | ||
|
|
d0167f7002 | ||
|
|
90ef90b462 | ||
|
|
cab46ea3d1 | ||
|
|
24cafcd65d | ||
|
|
b75fbe7a40 | ||
|
|
cd729660ed | ||
|
|
f81236185c | ||
|
|
7fa1a8b114 | ||
|
|
8536fe5aa9 | ||
|
|
6b24eb474f | ||
|
|
de493d761d | ||
|
|
b68f3455d3 | ||
|
|
f88d35f6c9 | ||
|
|
89752e2242 | ||
|
|
b8fa6f17ee | ||
|
|
2d4bcf202f | ||
|
|
1b0d83e7fc | ||
|
|
2d52d44710 | ||
|
|
af5322c7ef | ||
|
|
3af9cc3f6f | ||
|
|
688b930bad | ||
|
|
04f9baf4d3 | ||
|
|
19301f83eb | ||
|
|
2e6c1a74e5 | ||
|
|
e4be2b2cad | ||
|
|
48a8dd4a56 | ||
|
|
a805e7e12c | ||
|
|
3c702f38ee | ||
|
|
fe90da5a8d | ||
|
|
fd926cc44e | ||
|
|
f5bab3c8ba | ||
|
|
973885d087 | ||
|
|
1aa59f5579 | ||
|
|
a4496a4a6b | ||
|
|
84fecdc042 | ||
|
|
81a4b0ca99 | ||
|
|
6f7dba167a | ||
|
|
0cc0de9e51 | ||
|
|
010468699f | ||
|
|
4a6004b8fa | ||
|
|
c6df4a4a89 | ||
|
|
ee4cbbeb14 | ||
|
|
0e968f010a | ||
|
|
b0d42e6ac9 | ||
|
|
df898a5c87 | ||
|
|
bdc9124228 | ||
|
|
aad98fe749 | ||
|
|
506d16a603 | ||
|
|
9e1d97c261 | ||
|
|
4c562fc1a3 | ||
|
|
415a58f9fb | ||
|
|
85ba133df0 | ||
|
|
3ee8d35031 | ||
|
|
45fbe4a73d | ||
|
|
287b173844 | ||
|
|
05c1ba291d | ||
|
|
15a065d14d | ||
|
|
35a753dc98 | ||
|
|
06d05d1f46 | ||
|
|
fe7e0859d5 | ||
|
|
76971a88ff | ||
|
|
ddfeca1b1b | ||
|
|
0ab29c7420 | ||
|
|
1ba1424ac3 | ||
|
|
c8dae31ba5 | ||
|
|
49cd03bc29 | ||
|
|
6e1451dbd8 | ||
|
|
6b3aed29b9 | ||
|
|
34fe6b460c | ||
|
|
62f9de5edf | ||
|
|
0c39a50337 | ||
|
|
535435955b | ||
|
|
93e35dc3da | ||
|
|
05e8c856fa | ||
|
|
2e991d3b10 | ||
|
|
f60f946e11 | ||
|
|
253c10c398 | ||
|
|
f8c743e37d | ||
|
|
f80274be6b | ||
|
|
d93cdde938 | ||
|
|
640337e0a0 | ||
|
|
55f9dfad7d | ||
|
|
b9a8dd8f0d | ||
|
|
f973e855e0 | ||
|
|
93e0ebf25c | ||
|
|
21fa5d10f4 | ||
|
|
0046b8b4bb | ||
|
|
639baaaa03 | ||
|
|
6f7ca5e5d3 | ||
|
|
5210cdf43f | ||
|
|
072e3e89e3 | ||
|
|
6e18afac8c | ||
|
|
a9145d3312 | ||
|
|
5801dff9ea | ||
|
|
54dce214d1 | ||
|
|
e5bb854748 | ||
|
|
e9df183e87 | ||
|
|
954957c456 | ||
|
|
dfc8e38a21 | ||
|
|
bf348ae60f | ||
|
|
4df4968538 | ||
|
|
ca05569cd5 | ||
|
|
a157abbbc9 | ||
|
|
5abf4bb651 | ||
|
|
7ea711e043 | ||
|
|
b853166575 | ||
|
|
0725349bbd | ||
|
|
264e451d3c | ||
|
|
5b5bb5174b | ||
|
|
14120a519c | ||
|
|
2875e8f277 | ||
|
|
9a0c1ab2d0 | ||
|
|
f15d531acb | ||
|
|
e0fcaf5e7d | ||
|
|
1b78d8f0a3 | ||
|
|
66772d77fc | ||
|
|
d64637e8c7 | ||
|
|
02fa9641fd | ||
|
|
4506173a27 | ||
|
|
20eea7372f | ||
|
|
79f6bb6f54 | ||
|
|
fc076c5acc | ||
|
|
44d3cfb3dc | ||
|
|
0985326b2e | ||
|
|
cbeef963a9 | ||
|
|
544f9912b7 | ||
|
|
361ca788a7 | ||
|
|
68a249d23d | ||
|
|
95c8f1f866 | ||
|
|
fa17ea2715 | ||
|
|
c970c74d66 | ||
|
|
479da83f57 | ||
|
|
feca9e8103 | ||
|
|
a041ffa702 | ||
|
|
5eafc080e1 | ||
|
|
8558b2d278 | ||
|
|
756f837f82 | ||
|
|
0b838ff2c9 | ||
|
|
ca43608aa0 | ||
|
|
ad471b46b8 | ||
|
|
e6b357e87a | ||
|
|
b676fb1164 | ||
|
|
ca68b84623 | ||
|
|
d6bc78dcb8 | ||
|
|
2104fd7da9 | ||
|
|
c801a9e8cf | ||
|
|
c9a6446041 | ||
|
|
a2f24fac65 | ||
|
|
eaec888dc3 | ||
|
|
69d8cca38a | ||
|
|
04a3968206 | ||
|
|
ae699a6b13 | ||
|
|
9257ef42ba | ||
|
|
63f899a407 | ||
|
|
690cf16aa5 | ||
|
|
aaf831cd93 | ||
|
|
472a0b4954 | ||
|
|
c04323a7d5 | ||
|
|
fac4905e89 | ||
|
|
65e55ac094 | ||
|
|
f23d24ec7c | ||
|
|
e332adf3d5 | ||
|
|
13f00ea8ed | ||
|
|
a14e542ecb | ||
|
|
6065f08528 | ||
|
|
d455b05619 | ||
|
|
d49b941ea9 | ||
|
|
478be16fc5 | ||
|
|
26c1ddf104 | ||
|
|
f759d5dbc1 | ||
|
|
ea09ffc8ce | ||
|
|
6d5ce9b87f | ||
|
|
24d4353ab2 | ||
|
|
822f9e0a80 | ||
|
|
09600f2ca4 | ||
|
|
42e472ff3f | ||
|
|
285d271505 | ||
|
|
dcba6dfa7e | ||
|
|
953a1eefbb | ||
|
|
d5331d4150 | ||
|
|
61ea403bfa | ||
|
|
d5e19f9b28 | ||
|
|
d8c7c9fdb5 | ||
|
|
ed1ca47199 | ||
|
|
885b8bcc60 | ||
|
|
31e05cd2bd | ||
|
|
7fb72a0081 | ||
|
|
f3e3ebba81 | ||
|
|
51b780cd9f | ||
|
|
25b0c5af34 | ||
|
|
6ab20e7f03 | ||
|
|
6846a5179b | ||
|
|
eb5399445a | ||
|
|
83c08880a6 | ||
|
|
172a02557e | ||
|
|
2d3501be61 | ||
|
|
d07ec9a19f | ||
|
|
ed860dfa23 | ||
|
|
09e8079ea3 | ||
|
|
b42a7780e2 | ||
|
|
4ee90bd82f | ||
|
|
12cd4ca742 | ||
|
|
713a46cd75 | ||
|
|
f236328bc3 | ||
|
|
6e06978961 | ||
|
|
8edcfbe776 | ||
|
|
1c60173b69 | ||
|
|
59579bfc3e | ||
|
|
7f22c0883b | ||
|
|
78b941019b | ||
|
|
ae728d84f0 | ||
|
|
3eab35ef22 | ||
|
|
c260435913 | ||
|
|
a5351b5c47 | ||
|
|
718d8acc76 | ||
|
|
e8c3c7b5eb | ||
|
|
8f575bf986 | ||
|
|
cf48c6004d | ||
|
|
d0dc5dfd3d | ||
|
|
af473b085a | ||
|
|
9e778f3a61 | ||
|
|
52855ce1c1 | ||
|
|
22000a703a | ||
|
|
f6f54955fe | ||
|
|
1459d17bfd | ||
|
|
77646f7149 | ||
|
|
1e83f62d31 | ||
|
|
df9ca20339 | ||
|
|
b60f97cc19 | ||
|
|
ab946fdf2c | ||
|
|
d9956a9d05 | ||
|
|
2713c846f1 | ||
|
|
3056848819 | ||
|
|
08c3f3c236 | ||
|
|
a01eda79e8 | ||
|
|
f6e19f1f93 | ||
|
|
bad582ed45 | ||
|
|
18e1cdb7bb | ||
|
|
aa3e50ee76 | ||
|
|
eb6cede35d | ||
|
|
f8cdb03352 | ||
|
|
08ff19d973 | ||
|
|
2ea6b5068c | ||
|
|
4cd917aa65 | ||
|
|
417031fc17 | ||
|
|
416a8372cd | ||
|
|
6eaf406305 | ||
|
|
009bcf1a27 | ||
|
|
335c5ca5c8 | ||
|
|
5b18ea1545 | ||
|
|
d817fb0ef3 | ||
|
|
37bf79b0e2 | ||
|
|
7cdd65d5fb | ||
|
|
1901e2ecfd | ||
|
|
76051ab1fe | ||
|
|
062ac89c34 | ||
|
|
0c686e09db | ||
|
|
4575799f8e | ||
|
|
271c8ab9cb | ||
|
|
ee1854a607 | ||
|
|
9b186297c7 | ||
|
|
c8ef2fae1a | ||
|
|
0aba471758 | ||
|
|
467d905709 | ||
|
|
62f14514da | ||
|
|
5ece18cede | ||
|
|
33eac4497b | ||
|
|
fa449aab14 | ||
|
|
5f20213876 | ||
|
|
28f64e57ae | ||
|
|
5e7c4557f8 | ||
|
|
c517f8fc9e | ||
|
|
3a3c816a27 | ||
|
|
b8e801ecad | ||
|
|
7f17970551 | ||
|
|
0f1fb8bafe | ||
|
|
7931e19572 | ||
|
|
285f0e329f | ||
|
|
9006af4a96 | ||
|
|
5f17e3bf15 | ||
|
|
366b4b2810 | ||
|
|
e3517f1c86 | ||
|
|
fa1da03d50 | ||
|
|
5c2ae7b414 | ||
|
|
6ae31ea2d6 | ||
|
|
edade0cea8 | ||
|
|
969136b0d6 | ||
|
|
1726a61e88 | ||
|
|
9399b2ee36 | ||
|
|
e53f944c83 | ||
|
|
dbfeb9e2da | ||
|
|
ab87a6f797 | ||
|
|
475bd65c90 | ||
|
|
0fe7cc8794 | ||
|
|
2cdb547af0 | ||
|
|
fd25fd70f1 | ||
|
|
8a58037df9 | ||
|
|
e38f0c6990 | ||
|
|
557592aa97 | ||
|
|
e5600afddc | ||
|
|
87dae299b8 | ||
|
|
7034310a3b | ||
|
|
d7e7bd16a6 | ||
|
|
bdd1918cd8 | ||
|
|
30ba416fe3 | ||
|
|
95e753c6b4 | ||
|
|
5d54b0b13f | ||
|
|
d2153064ec | ||
|
|
4d295d85b6 | ||
|
|
8ce0e045a8 | ||
|
|
2be6c75c2b | ||
|
|
af84f76f31 | ||
|
|
dd45a21257 | ||
|
|
8177de88cd | ||
|
|
99dac6aec0 | ||
|
|
30afb0dbec | ||
|
|
309a3c364f | ||
|
|
fcbd1037fd | ||
|
|
aa769e7677 | ||
|
|
737105fd78 | ||
|
|
1285a3c9a7 | ||
|
|
17a477393c | ||
|
|
437b4a4f9b | ||
|
|
eddc3b421e | ||
|
|
98569c7cf0 | ||
|
|
7f39e56a79 | ||
|
|
bc5526cacb | ||
|
|
6300329057 | ||
|
|
15f0cd9527 | ||
|
|
b437232ab6 | ||
|
|
3ff069911e | ||
|
|
e74a97d5a8 | ||
|
|
7f4d673d33 | ||
|
|
81fe5243d3 | ||
|
|
3f19182afc | ||
|
|
ff1d3138bf | ||
|
|
0071bea64e | ||
|
|
5244ac3bb5 | ||
|
|
26be599e65 | ||
|
|
671057eecf | ||
|
|
0ab69a32cb | ||
|
|
6995f280b4 | ||
|
|
73422d52fd | ||
|
|
4875c6447f | ||
|
|
820c1e6f15 | ||
|
|
92b870da4a | ||
|
|
3eaa44dd4d | ||
|
|
e148871087 | ||
|
|
75b5c8b0aa | ||
|
|
4177f123bc | ||
|
|
db292b4c82 | ||
|
|
9669c6d5f1 | ||
|
|
2748633637 | ||
|
|
2075103cd9 | ||
|
|
b7dfda4f45 | ||
|
|
45514a955e | ||
|
|
4fdf74500d | ||
|
|
d8f9463af3 | ||
|
|
ab18c82371 | ||
|
|
68adcdb475 | ||
|
|
3cde12567f | ||
|
|
8d5da6491a | ||
|
|
eea7e50519 | ||
|
|
c4c3497776 | ||
|
|
d45cc674ea | ||
|
|
8a0d036e82 | ||
|
|
9d93b10919 | ||
|
|
2412d52536 | ||
|
|
e686d040ea | ||
|
|
2dce18655d | ||
|
|
6cf22b32aa | ||
|
|
d24219697e | ||
|
|
d353a25a36 | ||
|
|
9dc4dbebe1 | ||
|
|
04be1c6b5c | ||
|
|
e46a3108d9 | ||
|
|
4cbfa485fa | ||
|
|
9328271dd0 | ||
|
|
f137d43931 | ||
|
|
0ba5413266 | ||
|
|
fefc033515 | ||
|
|
d888039468 | ||
|
|
ddc4cf0a97 | ||
|
|
aa5b392e35 | ||
|
|
6346fdb253 | ||
|
|
7d2a7dba81 | ||
|
|
98f05c47d0 | ||
|
|
67bbc947af | ||
|
|
64219ac91e | ||
|
|
dedd9275ec | ||
|
|
4dbe84dc98 | ||
|
|
0cc4c91800 | ||
|
|
548d564c18 | ||
|
|
2d30e3913c | ||
|
|
ec13bb963f | ||
|
|
9006597f59 | ||
|
|
e28569f2a1 | ||
|
|
751947482f | ||
|
|
b7ab7ea745 | ||
|
|
6f5532f069 | ||
|
|
30ca6c82e0 | ||
|
|
968a708a9f | ||
|
|
bb23700f24 | ||
|
|
9a34f6bc95 | ||
|
|
f3e1795175 | ||
|
|
d57d1fcd36 | ||
|
|
e134cfea8f | ||
|
|
8b8561a699 | ||
|
|
51ae98ae30 | ||
|
|
09de5cd70e | ||
|
|
23e88b4e1d | ||
|
|
fcd60e73f8 | ||
|
|
b7f433c5b9 | ||
|
|
f3ac38ff2c | ||
|
|
c5a5c5572f | ||
|
|
2f7c0366f5 | ||
|
|
1a9757d1f6 | ||
|
|
3aaa3beeee | ||
|
|
deef4e8e23 | ||
|
|
c660f63748 | ||
|
|
b7e220039f | ||
|
|
34bd6e8bfd | ||
|
|
5cd5885da4 | ||
|
|
5f4e6a86d5 | ||
|
|
1043569648 | ||
|
|
383256defa | ||
|
|
cdab726e3d | ||
|
|
7b9ead4a1a | ||
|
|
6e191720b3 | ||
|
|
9fc31abb1f | ||
|
|
3878d6da85 | ||
|
|
097952c48f | ||
|
|
e5730e9b7e | ||
|
|
49546687d9 | ||
|
|
2c08280854 | ||
|
|
ebe68faf7f | ||
|
|
65abbd90bf | ||
|
|
119854e248 | ||
|
|
442ef6e64c | ||
|
|
fb462fdf9e | ||
|
|
d667522524 | ||
|
|
c1b5d54737 | ||
|
|
f94d7b333a | ||
|
|
d7ef2880c8 | ||
|
|
f3944a3d49 | ||
|
|
263a77fa89 | ||
|
|
2584b6abf9 | ||
|
|
ca9b804163 | ||
|
|
e9ccdeecd0 | ||
|
|
2ed4f39ffe | ||
|
|
1959e6088b | ||
|
|
ffbb21a032 | ||
|
|
e088549330 | ||
|
|
587979341a | ||
|
|
180bfeaba4 | ||
|
|
e6cce355e3 | ||
|
|
e9b75e34b7 | ||
|
|
e286f20179 | ||
|
|
d4afa3caaa | ||
|
|
e069c9eb0e | ||
|
|
dc2f256448 | ||
|
|
62ded77e81 | ||
|
|
466e8a6c5e | ||
|
|
b131e8b97f | ||
|
|
d7ef2a8d1c | ||
|
|
3b58a7d36b | ||
|
|
e9a318df16 | ||
|
|
166d1c0dab | ||
|
|
0926d27100 | ||
|
|
aa6f22d102 | ||
|
|
6adeab2160 | ||
|
|
6cbdd6b815 | ||
|
|
a8c0348300 | ||
|
|
08d8bed022 | ||
|
|
6e9bc1359d | ||
|
|
aac501a645 | ||
|
|
cf94e1b162 | ||
|
|
96e7ab078d | ||
|
|
9d33f2ad33 | ||
|
|
a4b5eecb8e | ||
|
|
f224452971 | ||
|
|
caf815b009 | ||
|
|
c0079fd9dd | ||
|
|
cfb13b1689 | ||
|
|
105843519c | ||
|
|
97698bfc38 | ||
|
|
7f1869016a | ||
|
|
0931033c72 | ||
|
|
a7789d863c | ||
|
|
bcc6fb54c2 | ||
|
|
b04ee0de57 | ||
|
|
7a83adf10d | ||
|
|
d642880b7d | ||
|
|
74206c755f | ||
|
|
c7b4d843e2 | ||
|
|
c90cc392f7 | ||
|
|
f298360ff9 | ||
|
|
275e483885 | ||
|
|
e87ce2bd5b | ||
|
|
3c6a923f1b | ||
|
|
b25ef7682d | ||
|
|
71b5bf3ef6 | ||
|
|
8dfc71c4fd | ||
|
|
243bbd74a5 | ||
|
|
aba49508f1 | ||
|
|
ae2a9b4688 | ||
|
|
d36fc8df67 | ||
|
|
6c20cd08f1 | ||
|
|
46b04c8405 | ||
|
|
efc101d3b4 | ||
|
|
e2e36087e1 | ||
|
|
d4e11f754a | ||
|
|
837ea41ede | ||
|
|
5778a3c0f2 | ||
|
|
668a892cdb | ||
|
|
0fdb63f258 | ||
|
|
338456e765 | ||
|
|
18a82c04fc | ||
|
|
4520206f4a |
72
.github/workflows/build-template.yml
vendored
72
.github/workflows/build-template.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
include: ${{fromJson(inputs.config)}}
|
||||
# complete all jobs
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: ${{ endsWith(matrix.os, '-with-cache') && fromJSON(format('["{0}", "nscloud-git-mirror-1gb"]', matrix.os)) || matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: ${{ matrix.shell || 'nix develop -c bash -euxo pipefail {0}' }}
|
||||
@@ -69,10 +69,16 @@ jobs:
|
||||
brew install ccache tree zstd coreutils gmp libuv
|
||||
if: runner.os == 'macOS'
|
||||
- name: Checkout
|
||||
if: (!endsWith(matrix.os, '-with-cache'))
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# the default is to use a virtual merge commit between the PR and master: just use the PR
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Namespace Checkout
|
||||
if: endsWith(matrix.os, '-with-cache')
|
||||
uses: namespacelabs/nscloud-checkout-action@v7
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Open Nix shell once
|
||||
run: true
|
||||
if: runner.os == 'Linux'
|
||||
@@ -104,7 +110,7 @@ jobs:
|
||||
# NOTE: must be in sync with `save` below and with `restore-cache` in `update-stage0.yml`
|
||||
path: |
|
||||
.ccache
|
||||
${{ matrix.name == 'Linux Lake' && false && 'build/stage1/**/*.trace
|
||||
${{ matrix.name == 'Linux Lake' && 'build/stage1/**/*.trace
|
||||
build/stage1/**/*.olean*
|
||||
build/stage1/**/*.ilean
|
||||
build/stage1/**/*.ir
|
||||
@@ -119,9 +125,15 @@ jobs:
|
||||
run: |
|
||||
ccache --zero-stats
|
||||
if: runner.os == 'Linux'
|
||||
- name: Set up NPROC
|
||||
- name: Set up env
|
||||
run: |
|
||||
echo "NPROC=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)" >> $GITHUB_ENV
|
||||
if ! diff src/stdlib_flags.h stage0/src/stdlib_flags.h; then
|
||||
echo "src/stdlib_flags.h and stage0/src/stdlib_flags.h differ, will test and pack stage 2"
|
||||
echo "TARGET_STAGE=stage2" >> $GITHUB_ENV
|
||||
else
|
||||
echo "TARGET_STAGE=stage1" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Build
|
||||
run: |
|
||||
ulimit -c unlimited # coredumps
|
||||
@@ -142,6 +154,9 @@ jobs:
|
||||
if [[ -n '${{ matrix.prepare-llvm }}' ]]; then
|
||||
wget -q ${{ matrix.llvm-url }}
|
||||
PREPARE="$(${{ matrix.prepare-llvm }})"
|
||||
if [ "$TARGET_STAGE" == "stage2" ]; then
|
||||
cp -r stage1 stage2
|
||||
fi
|
||||
eval "OPTIONS+=($PREPARE)"
|
||||
fi
|
||||
if [[ -n '${{ matrix.release }}' && -n '${{ inputs.nightly }}' ]]; then
|
||||
@@ -156,10 +171,28 @@ jobs:
|
||||
fi
|
||||
# contortion to support empty OPTIONS with old macOS bash
|
||||
cmake .. --preset ${{ matrix.CMAKE_PRESET || 'release' }} -B . ${{ matrix.CMAKE_OPTIONS }} ${OPTIONS[@]+"${OPTIONS[@]}"} -DLEAN_INSTALL_PREFIX=$PWD/..
|
||||
time make -j$NPROC
|
||||
time make $TARGET_STAGE -j$NPROC
|
||||
# Should be done as early as possible and in particular *before* "Check rebootstrap" which
|
||||
# changes the state of stage1/
|
||||
- name: Save Cache
|
||||
# Caching on cancellation created some mysterious issues perhaps related to improper build
|
||||
# shutdown
|
||||
if: steps.restore-cache.outputs.cache-hit != 'true' && !cancelled()
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
# NOTE: must be in sync with `restore` above
|
||||
path: |
|
||||
.ccache
|
||||
${{ matrix.name == 'Linux Lake' && 'build/stage1/**/*.trace
|
||||
build/stage1/**/*.olean*
|
||||
build/stage1/**/*.ilean
|
||||
build/stage1/**/*.ir
|
||||
build/stage1/**/*.c
|
||||
build/stage1/**/*.c.o*' || '' }}
|
||||
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
|
||||
- name: Install
|
||||
run: |
|
||||
make -C build install
|
||||
make -C build/$TARGET_STAGE install
|
||||
- name: Check Binaries
|
||||
run: ${{ matrix.binary-check }} lean-*/bin/* || true
|
||||
- name: Count binary symbols
|
||||
@@ -190,18 +223,18 @@ jobs:
|
||||
path: pack/*
|
||||
- name: Lean stats
|
||||
run: |
|
||||
build/stage1/bin/lean --stats src/Lean.lean
|
||||
build/$TARGET_STAGE/bin/lean --stats src/Lean.lean -Dexperimental.module=true
|
||||
if: ${{ !matrix.cross }}
|
||||
- name: Test
|
||||
id: test
|
||||
run: |
|
||||
ulimit -c unlimited # coredumps
|
||||
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/stage1 -j$NPROC --output-junit test-results.xml ${{ matrix.CTEST_OPTIONS }}
|
||||
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/$TARGET_STAGE -j$NPROC --output-junit test-results.xml
|
||||
if: (matrix.wasm || !matrix.cross) && (inputs.check-level >= 1 || matrix.test)
|
||||
- name: Test Summary
|
||||
uses: test-summary/action@v2
|
||||
with:
|
||||
paths: build/stage1/test-results.xml
|
||||
paths: build/${{ env.TARGET_STAGE }}/test-results.xml
|
||||
# prefix `if` above with `always` so it's run even if tests failed
|
||||
if: always() && steps.test.conclusion != 'skipped'
|
||||
- name: Check Test Binary
|
||||
@@ -226,8 +259,13 @@ jobs:
|
||||
if: matrix.test-speedcenter
|
||||
- name: Check rebootstrap
|
||||
run: |
|
||||
# clean rebuild in case of Makefile changes
|
||||
make -C build update-stage0 && rm -rf build/stage* && make -C build -j$NPROC
|
||||
set -e
|
||||
# clean rebuild in case of Makefile changes/Lake does not detect uncommited stage 0
|
||||
# changes yet
|
||||
make -C build update-stage0
|
||||
make -C build/stage1 clean-stdlib
|
||||
time make -C build -j$NPROC
|
||||
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/stage1 -j$NPROC
|
||||
if: matrix.check-rebootstrap
|
||||
- name: CCache stats
|
||||
if: always()
|
||||
@@ -239,17 +277,3 @@ jobs:
|
||||
progbin="$(file $c | sed "s/.*execfn: '\([^']*\)'.*/\1/")"
|
||||
echo bt | $GDB/bin/gdb -q $progbin $c || true
|
||||
done
|
||||
- name: Save Cache
|
||||
if: always() && steps.restore-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
# NOTE: must be in sync with `restore` above
|
||||
path: |
|
||||
.ccache
|
||||
${{ matrix.name == 'Linux Lake' && false && 'build/stage1/**/*.trace
|
||||
build/stage1/**/*.olean*
|
||||
build/stage1/**/*.ilean
|
||||
build/stage1/**/*.ir
|
||||
build/stage1/**/*.c
|
||||
build/stage1/**/*.c.o*' || '' }}
|
||||
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
|
||||
|
||||
28
.github/workflows/ci.yml
vendored
28
.github/workflows/ci.yml
vendored
@@ -165,7 +165,7 @@ jobs:
|
||||
{
|
||||
// portable release build: use channel with older glibc (2.26)
|
||||
"name": "Linux release",
|
||||
"os": large && level < 2 ? "nscloud-ubuntu-22.04-amd64-4x16" : "ubuntu-latest",
|
||||
"os": "ubuntu-latest",
|
||||
"release": true,
|
||||
// Special handling for release jobs. We want:
|
||||
// 1. To run it in PRs so developers get PR toolchains (so secondary is sufficient)
|
||||
@@ -181,17 +181,18 @@ jobs:
|
||||
"prepare-llvm": "../script/prepare-llvm-linux.sh lean-llvm*",
|
||||
"binary-check": "ldd -v",
|
||||
// foreign code may be linked against more recent glibc
|
||||
"CTEST_OPTIONS": "-E 'foreign'"
|
||||
"CTEST_OPTIONS": "-E 'foreign'",
|
||||
},
|
||||
{
|
||||
"name": "Linux Lake",
|
||||
"os": large ? "nscloud-ubuntu-22.04-amd64-8x16" : "ubuntu-latest",
|
||||
"os": large ? "nscloud-ubuntu-22.04-amd64-8x16-with-cache" : "ubuntu-latest",
|
||||
"check-level": 0,
|
||||
"test": true,
|
||||
"check-rebootstrap": level >= 1,
|
||||
"check-stage3": level >= 2,
|
||||
// NOTE: `test-speedcenter` currently seems to be broken on `ubuntu-latest`
|
||||
"test-speedcenter": large && level >= 2,
|
||||
// made explicit until it can be assumed to have propagated to PRs
|
||||
"CMAKE_OPTIONS": "-DUSE_LAKE=ON",
|
||||
},
|
||||
{
|
||||
@@ -221,12 +222,13 @@ jobs:
|
||||
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-x86_64-apple-darwin.tar.zst",
|
||||
"prepare-llvm": "../script/prepare-llvm-macos.sh lean-llvm*",
|
||||
"binary-check": "otool -L",
|
||||
"tar": "gtar" // https://github.com/actions/runner-images/issues/2619
|
||||
"tar": "gtar", // https://github.com/actions/runner-images/issues/2619
|
||||
"CTEST_OPTIONS": "-E 'leanlaketest_hello'", // started failing from unpack
|
||||
},
|
||||
{
|
||||
"name": "macOS aarch64",
|
||||
// standard GH runner only comes with 7GB so use large runner if possible
|
||||
"os": large ? "nscloud-macos-sonoma-arm64-6x14" : "macos-14",
|
||||
// standard GH runner only comes with 7GB so use large runner if possible when running tests
|
||||
"os": large && !isPr ? "nscloud-macos-sonoma-arm64-6x14" : "macos-14",
|
||||
"CMAKE_OPTIONS": "-DLEAN_INSTALL_SUFFIX=-darwin_aarch64",
|
||||
"release": true,
|
||||
"shell": "bash -euxo pipefail {0}",
|
||||
@@ -234,13 +236,13 @@ jobs:
|
||||
"prepare-llvm": "../script/prepare-llvm-macos.sh lean-llvm*",
|
||||
"binary-check": "otool -L",
|
||||
"tar": "gtar", // https://github.com/actions/runner-images/issues/2619
|
||||
// See above for release job levels
|
||||
// See "Linux release" for release job levels; Grove is not a concern here
|
||||
"check-level": isPr ? 0 : 2,
|
||||
"secondary": isPr,
|
||||
},
|
||||
{
|
||||
"name": "Windows",
|
||||
"os": "windows-2022",
|
||||
"os": large && level == 2 ? "namespace-profile-windows-amd64-4x16" : "windows-2022",
|
||||
"release": true,
|
||||
"check-level": 2,
|
||||
"shell": "msys2 {0}",
|
||||
@@ -249,7 +251,7 @@ jobs:
|
||||
"CTEST_OPTIONS": "--repeat until-pass:2",
|
||||
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-x86_64-w64-windows-gnu.tar.zst",
|
||||
"prepare-llvm": "../script/prepare-llvm-mingw.sh lean-llvm*",
|
||||
"binary-check": "ldd"
|
||||
"binary-check": "ldd",
|
||||
},
|
||||
{
|
||||
"name": "Linux aarch64",
|
||||
@@ -259,7 +261,7 @@ jobs:
|
||||
"check-level": 2,
|
||||
"shell": "nix develop .#oldGlibcAArch -c bash -euxo pipefail {0}",
|
||||
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-aarch64-linux-gnu.tar.zst",
|
||||
"prepare-llvm": "../script/prepare-llvm-linux.sh lean-llvm*"
|
||||
"prepare-llvm": "../script/prepare-llvm-linux.sh lean-llvm*",
|
||||
},
|
||||
// Started running out of memory building expensive modules, a 2GB heap is just not that much even before fragmentation
|
||||
//{
|
||||
@@ -288,6 +290,12 @@ jobs:
|
||||
// "CTEST_OPTIONS": "-R \"leantest_1007\\.lean|leantest_Format\\.lean|leanruntest\\_1037.lean|leanruntest_ac_rfl\\.lean|leanruntest_tempfile.lean\\.|leanruntest_libuv\\.lean\""
|
||||
// }
|
||||
];
|
||||
for (const job of matrix) {
|
||||
if (job["prepare-llvm"]) {
|
||||
// `USE_LAKE` is not compatible with `prepare-llvm` currently
|
||||
job["CMAKE_OPTIONS"] = (job["CMAKE_OPTIONS"] ? job["CMAKE_OPTIONS"] + " " : "") + "-DUSE_LAKE=OFF";
|
||||
}
|
||||
}
|
||||
console.log(`matrix:\n${JSON.stringify(matrix, null, 2)}`);
|
||||
matrix = matrix.filter((job) => level >= job["check-level"]);
|
||||
core.setOutput('matrix', matrix.filter((job) => !job["secondary"]));
|
||||
|
||||
12
.github/workflows/grove.yml
vendored
12
.github/workflows/grove.yml
vendored
@@ -30,8 +30,8 @@ jobs:
|
||||
# Check if it's a push to master (no PR number and target branch is master)
|
||||
if [ -z "${{ steps.workflow-info.outputs.pullRequestNumber }}" ]; then
|
||||
if [ "${{ github.event.workflow_run.head_branch }}" = "master" ]; then
|
||||
echo "Push to master detected. Skipping for now, to be enabled later."
|
||||
echo "should-run=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Push to master detected. Running Grove."
|
||||
echo "should-run=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "Push to non-master branch, skipping"
|
||||
echo "should-run=false" >> "$GITHUB_OUTPUT"
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
# Check if it's a PR with grove label
|
||||
PR_LABELS='${{ steps.workflow-info.outputs.pullRequestLabels }}'
|
||||
if echo "$PR_LABELS" | grep -q '"grove"'; then
|
||||
echo "PR with grove label detected"
|
||||
echo "PR with grove label detected. Running Grove."
|
||||
echo "should-run=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "PR without grove label, skipping"
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
- name: Fetch upstream invalidated facts
|
||||
if: ${{ steps.should-run.outputs.should-run == 'true' && steps.workflow-info.outputs.pullRequestNumber != '' }}
|
||||
id: fetch-upstream
|
||||
uses: TwoFx/grove-action/fetch-upstream@v0.3
|
||||
uses: TwoFx/grove-action/fetch-upstream@v0.4
|
||||
with:
|
||||
artifact-name: grove-invalidated-facts
|
||||
base-ref: master
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
commit: ${{ steps.workflow-info.outputs.sourceHeadSha }}
|
||||
workflow: ci.yml
|
||||
path: artifacts
|
||||
name: build-Linux.*
|
||||
name: "build-Linux release"
|
||||
name_is_regexp: true
|
||||
|
||||
- name: Unpack toolchain
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
- name: Build
|
||||
if: ${{ steps.should-run.outputs.should-run == 'true' }}
|
||||
id: build
|
||||
uses: TwoFx/grove-action/build@v0.3
|
||||
uses: TwoFx/grove-action/build@v0.4
|
||||
with:
|
||||
project-path: doc/std/grove
|
||||
script-name: grove-stdlib
|
||||
|
||||
9
.github/workflows/update-stage0.yml
vendored
9
.github/workflows/update-stage0.yml
vendored
@@ -19,6 +19,8 @@ concurrency:
|
||||
jobs:
|
||||
update-stage0:
|
||||
runs-on: nscloud-ubuntu-22.04-amd64-8x16
|
||||
env:
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
steps:
|
||||
# This action should push to an otherwise protected branch, so it
|
||||
# uses a deploy key with write permissions, as suggested at
|
||||
@@ -57,9 +59,14 @@ jobs:
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
# NOTE: must be in sync with `restore-cache` in `build-template.yml`
|
||||
# TODO: actually switch to USE_LAKE once it caches more; for now it just caches more often than any other build type so let's use its cache
|
||||
path: |
|
||||
.ccache
|
||||
build/stage1/**/*.trace
|
||||
build/stage1/**/*.olean*
|
||||
build/stage1/**/*.ilean
|
||||
build/stage1/**/*.ir
|
||||
build/stage1/**/*.c
|
||||
build/stage1/**/*.c.o*
|
||||
key: Linux Lake-build-v3-${{ github.sha }}
|
||||
# fall back to (latest) previous cache
|
||||
restore-keys: |
|
||||
|
||||
@@ -147,6 +147,10 @@ add_custom_target(test
|
||||
COMMAND $(MAKE) -C stage1 test
|
||||
DEPENDS stage1)
|
||||
|
||||
add_custom_target(clean-stdlib
|
||||
COMMAND $(MAKE) -C stage1 clean-stdlib
|
||||
DEPENDS stage1)
|
||||
|
||||
install(CODE "execute_process(COMMAND make -C stage1 install)")
|
||||
|
||||
add_custom_target(check-stage3
|
||||
|
||||
@@ -48,3 +48,7 @@
|
||||
/src/Std/Do @sgraf812
|
||||
/src/Std/Tactic/Do @sgraf812
|
||||
/src/Lean/Elab/Tactic/Do @sgraf812
|
||||
/src/Init/Data/Range/Polymorphic @datokrat
|
||||
/src/Init/Data/Slice @datokrat
|
||||
/src/Init/Data/Iterators @datokrat
|
||||
/src/Std/Data/Iterators @datokrat
|
||||
|
||||
@@ -9,7 +9,7 @@ This is the repository for **Lean 4**.
|
||||
- [Documentation Overview](https://lean-lang.org/documentation/)
|
||||
- [Language Reference](https://lean-lang.org/doc/reference/latest/)
|
||||
- [Release notes](RELEASES.md) starting at v4.0.0-m3
|
||||
- [Examples](https://lean-lang.org/documentation/examples/)
|
||||
- [Examples](https://lean-lang.org/lean4/doc/examples.html)
|
||||
- [External Contribution Guidelines](CONTRIBUTING.md)
|
||||
|
||||
# Installation
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Lean Build Bootstrapping
|
||||
|
||||
Since version 4, Lean is a partially bootstrapped program: most parts of the
|
||||
Lean is a bootstrapped program: the
|
||||
frontend and compiler are written in Lean itself and thus need to be built before
|
||||
building Lean itself - which is needed to again build those parts. This cycle is
|
||||
broken by using pre-built C files checked into the repository (which ultimately
|
||||
@@ -73,6 +73,11 @@ update the archived C source code of the stage 0 compiler in `stage0/src`.
|
||||
The github repository will automatically update stage0 on `master` once
|
||||
`src/stdlib_flags.h` and `stage0/src/stdlib_flags.h` are out of sync.
|
||||
|
||||
NOTE: A full rebuild of stage 1 will only be triggered when the *committed* contents of `stage0/` are changed.
|
||||
Thus if you change files in it manually instead of through `update-stage0-commit` (see below) or fetching updates from git, you either need to commit those changes first or run `make -C build/release clean-stdlib`.
|
||||
The same is true for further stages except that a rebuild of them is retriggered on any committed change, not just to a specific directory.
|
||||
Thus when debugging e.g. stage 2 failures, you can resume the build from these failures on but may want to explicitly call `clean-stdlib` to either observe changes from `.olean` files of modules that built successfully or to check that you did not break modules that built successfully at some prior point.
|
||||
|
||||
If you have write access to the lean4 repository, you can also manually
|
||||
trigger that process, for example to be able to use new features in the compiler itself.
|
||||
You can do that on <https://github.com/leanprover/lean4/actions/workflows/update-stage0.yml>
|
||||
@@ -82,13 +87,13 @@ gh workflow run update-stage0.yml
|
||||
```
|
||||
|
||||
Leaving stage0 updates to the CI automation is preferable, but should you need
|
||||
to do it locally, you can use `make update-stage0-commit` in `build/release` to
|
||||
update `stage0` from `stage1` or `make -C stageN update-stage0-commit` to
|
||||
to do it locally, you can use `make -C build/release update-stage0-commit` to
|
||||
update `stage0` from `stage1` or `make -C build/release/stageN update-stage0-commit` to
|
||||
update from another stage. This command will automatically stage the updated files
|
||||
and introduce a commit,so make sure to commit your work before that.
|
||||
and introduce a commit, so make sure to commit your work before that.
|
||||
|
||||
If you rebased the branch (either onto a newer version of `master`, or fixing
|
||||
up some commits prior to the stage0 update, recreate the stage0 update commits.
|
||||
up some commits prior to the stage0 update), recreate the stage0 update commits.
|
||||
The script `script/rebase-stage0.sh` can be used for that.
|
||||
|
||||
The CI should prevent PRs with changes to stage0 (besides `stdlib_flags.h`)
|
||||
|
||||
@@ -9,7 +9,7 @@ You should not edit the `stage0` directory except using the commands described i
|
||||
## Development Setup
|
||||
|
||||
You can use any of the [supported editors](../setup.md) for editing the Lean source code.
|
||||
If you set up `elan` as below, opening `src/` as a *workspace folder* should ensure that stage 0 (i.e. the stage that first compiles `src/`) will be used for files in that directory.
|
||||
Please see below for specific instructions for VS Code.
|
||||
|
||||
### Dev setup using elan
|
||||
|
||||
@@ -68,6 +68,10 @@ code lean.code-workspace
|
||||
```
|
||||
on the command line.
|
||||
|
||||
You can use the `Refresh File Dependencies` command as in other projects to rebuild modules from inside VS Code but be aware that this does not trigger any non-Lake build targets.
|
||||
In particular, after updating `stage0/` (or fetching an update to it), you will want to invoke `make` directly to rebuild `stage0/bin/lean` as described in [building Lean](../make/index.md).
|
||||
You should then run the `Restart Server` command to update all open files and the server watchdog process as well.
|
||||
|
||||
### `ccache`
|
||||
|
||||
Lean's build process uses [`ccache`](https://ccache.dev/) if it is
|
||||
|
||||
@@ -282,7 +282,7 @@ theorem BinTree.find_insert_of_ne (b : BinTree β) (ne : k ≠ k') (v : β)
|
||||
let ⟨t, h⟩ := b; simp
|
||||
induction t with simp
|
||||
| leaf =>
|
||||
intros le
|
||||
intro le
|
||||
exact Nat.lt_of_le_of_ne le ne
|
||||
| node left key value right ihl ihr =>
|
||||
let .node hl hr bl br := h
|
||||
|
||||
@@ -44,12 +44,12 @@ Useful CMake Configuration Settings
|
||||
Pass these along with the `cmake --preset release` command.
|
||||
There are also two alternative presets that combine some of these options you can use instead of `release`: `debug` and `sandebug` (sanitize + debug).
|
||||
|
||||
* `-D CMAKE_BUILD_TYPE=`\
|
||||
* `-DCMAKE_BUILD_TYPE=`\
|
||||
Select the build type. Valid values are `RELEASE` (default), `DEBUG`,
|
||||
`RELWITHDEBINFO`, and `MINSIZEREL`.
|
||||
|
||||
* `-D CMAKE_C_COMPILER=`\
|
||||
`-D CMAKE_CXX_COMPILER=`\
|
||||
* `-DCMAKE_C_COMPILER=`\
|
||||
`-DCMAKE_CXX_COMPILER=`\
|
||||
Select the C/C++ compilers to use. Official Lean releases currently use Clang;
|
||||
see also `.github/workflows/ci.yml` for the CI config.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Install Packages on OS X 14.5
|
||||
# Install Packages on OS X
|
||||
|
||||
We assume that you are using [homebrew][homebrew] as a package manager.
|
||||
|
||||
@@ -6,23 +6,23 @@ We assume that you are using [homebrew][homebrew] as a package manager.
|
||||
|
||||
## Compilers
|
||||
|
||||
You need a C++11-compatible compiler to build Lean. As of November
|
||||
2014, you have three options:
|
||||
You need a C++14-compatible compiler to build Lean. As of July
|
||||
2025, you have three options:
|
||||
|
||||
- clang++-3.5 (shipped with OSX, Apple LLVM version 6.0)
|
||||
- gcc-4.9.1 (homebrew)
|
||||
- clang++-3.5 (homebrew)
|
||||
- clang++ shipped with OSX (at time of writing v17.0.0)
|
||||
- clang++ via homebrew (at time of writing, v20.1.8)
|
||||
- gcc via homebrew (at time of writing, v15.1.0)
|
||||
|
||||
We recommend to use Apple's clang++ because it is pre-shipped with OS
|
||||
X and requires no further installation.
|
||||
|
||||
To install gcc-4.9.1 via homebrew, please execute:
|
||||
To install gcc via homebrew, please execute:
|
||||
```bash
|
||||
brew install gcc
|
||||
```
|
||||
To install clang++-3.5 via homebrew, please execute:
|
||||
To install clang via homebrew, please execute:
|
||||
```bash
|
||||
brew install llvm
|
||||
brew install llvm lld
|
||||
```
|
||||
To use compilers other than the default one (Apple's clang++), you
|
||||
need to use `-DCMAKE_CXX_COMPILER` option to specify the compiler
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import Grove.Framework
|
||||
import GroveStdlib.Generated.«associative-query-operations»
|
||||
import GroveStdlib.Generated.«associative-creation-operations»
|
||||
import GroveStdlib.Generated.«associative-modification-operations»
|
||||
import GroveStdlib.Generated.«associative-create-then-query»
|
||||
import GroveStdlib.Generated.«associative-all-operations-covered»
|
||||
|
||||
/-
|
||||
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
|
||||
@@ -12,3 +16,7 @@ namespace GroveStdlib.Generated
|
||||
|
||||
def restoreState : RestoreStateM Unit := do
|
||||
«associative-query-operations».restoreState
|
||||
«associative-creation-operations».restoreState
|
||||
«associative-modification-operations».restoreState
|
||||
«associative-create-then-query».restoreState
|
||||
«associative-all-operations-covered».restoreState
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import Grove.Framework
|
||||
|
||||
/-
|
||||
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
|
||||
conflicts, but be careful.
|
||||
-/
|
||||
|
||||
open Grove.Framework Widget
|
||||
|
||||
namespace GroveStdlib.Generated.«associative-all-operations-covered»
|
||||
|
||||
def «all-covered» : Assertion.Fact where
|
||||
widgetId := "associative-all-operations-covered"
|
||||
factId := "all-covered"
|
||||
assertionId := "all-covered"
|
||||
state := {
|
||||
assertionId := "all-covered"
|
||||
description := "All operations should be covered"
|
||||
passed := false
|
||||
message := "There were 19697 operations that were not covered."
|
||||
}
|
||||
metadata := {
|
||||
status := .bad
|
||||
comment := "Still missing some!"
|
||||
}
|
||||
|
||||
def table : Assertion.Data where
|
||||
widgetId := "associative-all-operations-covered"
|
||||
facts := #[
|
||||
«all-covered»,
|
||||
]
|
||||
|
||||
def restoreState : RestoreStateM Unit := do
|
||||
addAssertion table
|
||||
@@ -0,0 +1,357 @@
|
||||
import Grove.Framework
|
||||
|
||||
/-
|
||||
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
|
||||
conflicts, but be careful.
|
||||
-/
|
||||
|
||||
open Grove.Framework Widget
|
||||
|
||||
namespace GroveStdlib.Generated.«associative-create-then-query»
|
||||
|
||||
def «2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap» : Table.Fact .subexpression .subexpression .declaration where
|
||||
widgetId := "associative-create-then-query"
|
||||
factId := "2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap"
|
||||
rowAssociationId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
|
||||
columnAssociationId := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
|
||||
layerStates := #[
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.DHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.DHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.DHashMap α β",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.isEmpty,
|
||||
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap.Raw"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.DHashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.emptyWithCapacity,
|
||||
renderedStatement := "Std.DHashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} (capacity : Nat := 8) :\n Std.DHashMap.Raw α β",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.DHashMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} (m : Std.DHashMap.Raw α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.ExtDHashMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.ExtDHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.ExtDHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtDHashMap α β",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.empty,
|
||||
renderedStatement := "Std.DTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.DTreeMap α β cmp",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap.Raw"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.empty,
|
||||
renderedStatement := "Std.DTreeMap.Raw.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.DTreeMap.Raw α β cmp",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.ExtDTreeMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.ExtDTreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.empty,
|
||||
renderedStatement := "Std.ExtDTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.ExtDTreeMap α β cmp",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
]
|
||||
metadata := {
|
||||
status := .done
|
||||
comment := "Not necessary for `ExtDHashMap` because of simp lemma turning into varno"
|
||||
}
|
||||
|
||||
def «5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap» : Table.Fact .subexpression .subexpression .declaration where
|
||||
widgetId := "associative-create-then-query"
|
||||
factId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap"
|
||||
rowAssociationId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnAssociationId := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
|
||||
layerStates := #[
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.DHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.isEmpty,
|
||||
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
⟨"Std.DHashMap.isEmpty_empty", Grove.Framework.Declaration.thm
|
||||
{ name := `Std.DHashMap.isEmpty_empty,
|
||||
renderedStatement := "Std.DHashMap.isEmpty_empty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} :\n ∅.isEmpty = true",
|
||||
isSimp := true,
|
||||
isDeprecated := false }⟩
|
||||
,
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap.Raw"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.DHashMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} (m : Std.DHashMap.Raw α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
⟨"Std.DHashMap.Raw.isEmpty_emptyc", Grove.Framework.Declaration.thm
|
||||
{ name := `Std.DHashMap.Raw.isEmpty_emptyc,
|
||||
renderedStatement := "Std.DHashMap.Raw.isEmpty_emptyc.{u_1, u_2} {α : Type u_1} {β : α → Type u_2} [BEq α] [Hashable α] :\n ∅.isEmpty = true",
|
||||
isSimp := false,
|
||||
isDeprecated := true }⟩
|
||||
,
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.ExtDHashMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
⟨"Std.DTreeMap.isEmpty_emptyc", Grove.Framework.Declaration.thm
|
||||
{ name := `Std.DTreeMap.isEmpty_emptyc,
|
||||
renderedStatement := "Std.DTreeMap.isEmpty_emptyc.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n ∅.isEmpty = true",
|
||||
isSimp := true,
|
||||
isDeprecated := false }⟩
|
||||
,
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap.Raw"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
⟨"Std.DTreeMap.Raw.isEmpty_emptyc", Grove.Framework.Declaration.thm
|
||||
{ name := `Std.DTreeMap.Raw.isEmpty_emptyc,
|
||||
renderedStatement := "Std.DTreeMap.Raw.isEmpty_emptyc.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n ∅.isEmpty = true",
|
||||
isSimp := true,
|
||||
isDeprecated := false }⟩
|
||||
,
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.ExtDTreeMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
⟨"Std.ExtDTreeMap.isEmpty_empty", Grove.Framework.Declaration.thm
|
||||
{ name := `Std.ExtDTreeMap.isEmpty_empty,
|
||||
renderedStatement := "Std.ExtDTreeMap.isEmpty_empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n ∅.isEmpty = true",
|
||||
isSimp := true,
|
||||
isDeprecated := false }⟩
|
||||
,
|
||||
]
|
||||
},
|
||||
]
|
||||
metadata := {
|
||||
status := .bad
|
||||
comment := "Missing for `ExtDHashMap`"
|
||||
}
|
||||
|
||||
def table : Table.Data .subexpression .subexpression .declaration where
|
||||
widgetId := "associative-create-then-query"
|
||||
selectedRowAssociations := #["2cb3c441-9663-4ce7-9527-0f40fc29925a", "7743a485-024d-43b6-bd5f-ebd3182eb94d", "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d", ]
|
||||
selectedColumnAssociations := #["01f88623-fa5f-4380-9772-b30f2fec5c94", "f084f852-af71-45b6-8ab3-d251a8144f72", ]
|
||||
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
|
||||
selectedCellOptions := #[
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap"
|
||||
rowValue := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DHashMap.isEmpty_emptyWithCapacity", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap.Raw"
|
||||
rowValue := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DHashMap.Raw.isEmpty_emptyWithCapacity", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap"
|
||||
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DHashMap.isEmpty_empty", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap.Raw"
|
||||
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DHashMap.Raw.isEmpty_emptyc", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap"
|
||||
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DTreeMap.isEmpty_emptyc", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap.Raw"
|
||||
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DTreeMap.Raw.isEmpty_emptyc", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.ExtDTreeMap"
|
||||
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.ExtDTreeMap.isEmpty_empty", ]
|
||||
},
|
||||
]
|
||||
facts := #[
|
||||
«2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap»,
|
||||
«5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap»,
|
||||
]
|
||||
|
||||
def restoreState : RestoreStateM Unit := do
|
||||
addTable table
|
||||
@@ -0,0 +1,216 @@
|
||||
import Grove.Framework
|
||||
|
||||
/-
|
||||
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
|
||||
conflicts, but be careful.
|
||||
-/
|
||||
|
||||
open Grove.Framework Widget
|
||||
|
||||
namespace GroveStdlib.Generated.«associative-creation-operations»
|
||||
|
||||
def «2cb3c441-9663-4ce7-9527-0f40fc29925a» : AssociationTable.Fact .subexpression where
|
||||
widgetId := "associative-creation-operations"
|
||||
factId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
|
||||
rowId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.DHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.DHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.emptyWithCapacity,
|
||||
renderedStatement := "Std.DHashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} (capacity : Nat := 8) :\n Std.DHashMap.Raw α β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.ExtDHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtDHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.empty,
|
||||
renderedStatement := "Std.DTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.DTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.empty,
|
||||
renderedStatement := "Std.DTreeMap.Raw.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.DTreeMap.Raw α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.empty,
|
||||
renderedStatement := "Std.ExtDTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.ExtDTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "Std.HashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.HashMap.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.HashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.Raw.emptyWithCapacity,
|
||||
renderedStatement := "Std.HashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} (capacity : Nat := 8) :\n Std.HashMap.Raw α β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.ExtHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.empty,
|
||||
renderedStatement := "Std.TreeMap.empty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} : Std.TreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.empty,
|
||||
renderedStatement := "Std.TreeMap.Raw.empty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} :\n Std.TreeMap.Raw α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.empty,
|
||||
renderedStatement := "Std.ExtTreeMap.empty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} :\n Std.ExtTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.emptyWithCapacity,
|
||||
renderedStatement := "Std.HashSet.emptyWithCapacity.{u} {α : Type u} [BEq α] [Hashable α] (capacity : Nat := 8) :\n Std.HashSet α",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.emptyWithCapacity,
|
||||
renderedStatement := "Std.HashSet.Raw.emptyWithCapacity.{u} {α : Type u} (capacity : Nat := 8) : Std.HashSet.Raw α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashSet.emptyWithCapacity,
|
||||
renderedStatement := "Std.ExtHashSet.emptyWithCapacity.{u} {α : Type u} [BEq α] [Hashable α] (capacity : Nat := 8) :\n Std.ExtHashSet α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.empty,
|
||||
renderedStatement := "Std.TreeSet.empty.{u} {α : Type u} {cmp : α → α → Ordering} : Std.TreeSet α cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.empty,
|
||||
renderedStatement := "Std.TreeSet.Raw.empty.{u} {α : Type u} {cmp : α → α → Ordering} : Std.TreeSet.Raw α cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.empty,
|
||||
renderedStatement := "Std.ExtTreeSet.empty.{u} {α : Type u} {cmp : α → α → Ordering} : Std.ExtTreeSet α cmp",
|
||||
isDeprecated := false })⟩,]
|
||||
metadata := {
|
||||
status := .done
|
||||
comment := ""
|
||||
}
|
||||
def «7743a485-024d-43b6-bd5f-ebd3182eb94d» : AssociationTable.Fact .subexpression where
|
||||
widgetId := "associative-creation-operations"
|
||||
factId := "7743a485-024d-43b6-bd5f-ebd3182eb94d"
|
||||
rowId := "7743a485-024d-43b6-bd5f-ebd3182eb94d"
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.ofList,
|
||||
renderedStatement := "Std.DHashMap.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.DHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.ofList,
|
||||
renderedStatement := "Std.DHashMap.Raw.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.DHashMap.Raw α β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.ofList,
|
||||
renderedStatement := "Std.ExtDHashMap.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.ExtDHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.ofList,
|
||||
renderedStatement := "Std.DTreeMap.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : α → α → Ordering := by exact compare) : Std.DTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.ofList,
|
||||
renderedStatement := "Std.DTreeMap.Raw.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : α → α → Ordering := by exact compare) : Std.DTreeMap.Raw α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.ofList,
|
||||
renderedStatement := "Std.ExtDTreeMap.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : α → α → Ordering := by exact compare) : Std.ExtDTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "Std.HashMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.ofList,
|
||||
renderedStatement := "Std.HashMap.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.HashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.Raw.ofList,
|
||||
renderedStatement := "Std.HashMap.Raw.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.HashMap.Raw α β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashMap.ofList,
|
||||
renderedStatement := "Std.ExtHashMap.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.ExtHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.ofList,
|
||||
renderedStatement := "Std.TreeMap.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : α → α → Ordering := by exact compare) : Std.TreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.ofList,
|
||||
renderedStatement := "Std.TreeMap.Raw.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : α → α → Ordering := by exact compare) : Std.TreeMap.Raw α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.ofList,
|
||||
renderedStatement := "Std.ExtTreeMap.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : α → α → Ordering := by exact compare) : Std.ExtTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.ofList,
|
||||
renderedStatement := "Std.HashSet.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.HashSet α",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.ofList,
|
||||
renderedStatement := "Std.HashSet.Raw.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.HashSet.Raw α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashSet.ofList,
|
||||
renderedStatement := "Std.ExtHashSet.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.ExtHashSet α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.ofList,
|
||||
renderedStatement := "Std.TreeSet.ofList.{u} {α : Type u} (l : List α) (cmp : α → α → Ordering := by exact compare) :\n Std.TreeSet α cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.ofList,
|
||||
renderedStatement := "Std.TreeSet.Raw.ofList.{u} {α : Type u} (l : List α) (cmp : α → α → Ordering := by exact compare) :\n Std.TreeSet.Raw α cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.ofList,
|
||||
renderedStatement := "Std.ExtTreeSet.ofList.{u} {α : Type u} (l : List α) (cmp : α → α → Ordering := by exact compare) :\n Std.ExtTreeSet α cmp",
|
||||
isDeprecated := false })⟩,]
|
||||
metadata := {
|
||||
status := .done
|
||||
comment := ""
|
||||
}
|
||||
def «5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d» : AssociationTable.Fact .subexpression where
|
||||
widgetId := "associative-creation-operations"
|
||||
factId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
rowId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
rowState := #[⟨"Std.DHashMap", "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", displayShort := "∅" }⟩,⟨"Std.DHashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtDHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", displayShort := "∅" }⟩,⟨"Std.DTreeMap", "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", displayShort := "∅" }⟩,⟨"Std.DTreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtDTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", displayShort := "∅" }⟩,⟨"Std.HashMap", "app (EmptyCollection.emptyCollection) (Std.HashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.HashMap*)", displayShort := "∅" }⟩,⟨"Std.HashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)", displayShort := "∅" }⟩,⟨"Std.TreeMap", "app (EmptyCollection.emptyCollection) (Std.TreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeMap*)", displayShort := "∅" }⟩,⟨"Std.TreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)", displayShort := "∅" }⟩,⟨"Std.HashSet", "app (EmptyCollection.emptyCollection) (Std.HashSet*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.HashSet*)", displayShort := "∅" }⟩,⟨"Std.HashSet.Raw", "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtHashSet", "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)", displayShort := "∅" }⟩,⟨"Std.TreeSet", "app (EmptyCollection.emptyCollection) (Std.TreeSet*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeSet*)", displayShort := "∅" }⟩,⟨"Std.TreeSet.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtTreeSet", "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)", displayShort := "∅" }⟩,]
|
||||
metadata := {
|
||||
status := .done
|
||||
comment := ""
|
||||
}
|
||||
|
||||
def table : AssociationTable.Data .subexpression where
|
||||
widgetId := "associative-creation-operations"
|
||||
rows := #[
|
||||
⟨"2cb3c441-9663-4ce7-9527-0f40fc29925a", "empty", #[⟨"Std.DHashMap", "Std.DHashMap.emptyWithCapacity"⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.emptyWithCapacity"⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.emptyWithCapacity"⟩,⟨"Std.DTreeMap", "Std.DTreeMap.empty"⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.empty"⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.empty"⟩,⟨"Std.HashMap", "Std.HashMap.emptyWithCapacity"⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.emptyWithCapacity"⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.emptyWithCapacity"⟩,⟨"Std.TreeMap", "Std.TreeMap.empty"⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.empty"⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.empty"⟩,⟨"Std.HashSet", "Std.HashSet.emptyWithCapacity"⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.emptyWithCapacity"⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.emptyWithCapacity"⟩,⟨"Std.TreeSet", "Std.TreeSet.empty"⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.empty"⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.empty"⟩,]⟩,
|
||||
⟨"7743a485-024d-43b6-bd5f-ebd3182eb94d", "ofList", #[⟨"Std.DHashMap", "Std.DHashMap.ofList"⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.ofList"⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.ofList"⟩,⟨"Std.DTreeMap", "Std.DTreeMap.ofList"⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.ofList"⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.ofList"⟩,⟨"Std.HashMap", "Std.HashMap.ofList"⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.ofList"⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.ofList"⟩,⟨"Std.TreeMap", "Std.TreeMap.ofList"⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.ofList"⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.ofList"⟩,⟨"Std.HashSet", "Std.HashSet.ofList"⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.ofList"⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.ofList"⟩,⟨"Std.TreeSet", "Std.TreeSet.ofList"⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.ofList"⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.ofList"⟩,]⟩,
|
||||
⟨"5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d", "emptyCollection", #[⟨"Std.DHashMap", "app (EmptyCollection.emptyCollection) (Std.DHashMap*)"⟩,⟨"Std.DHashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)"⟩,⟨"Std.ExtDHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)"⟩,⟨"Std.DTreeMap", "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)"⟩,⟨"Std.DTreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)"⟩,⟨"Std.ExtDTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)"⟩,⟨"Std.HashMap", "app (EmptyCollection.emptyCollection) (Std.HashMap*)"⟩,⟨"Std.HashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)"⟩,⟨"Std.ExtHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)"⟩,⟨"Std.TreeMap", "app (EmptyCollection.emptyCollection) (Std.TreeMap*)"⟩,⟨"Std.TreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)"⟩,⟨"Std.ExtTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)"⟩,⟨"Std.HashSet", "app (EmptyCollection.emptyCollection) (Std.HashSet*)"⟩,⟨"Std.HashSet.Raw", "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)"⟩,⟨"Std.ExtHashSet", "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)"⟩,⟨"Std.TreeSet", "app (EmptyCollection.emptyCollection) (Std.TreeSet*)"⟩,⟨"Std.TreeSet.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)"⟩,⟨"Std.ExtTreeSet", "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)"⟩,]⟩,
|
||||
]
|
||||
facts := #[
|
||||
«2cb3c441-9663-4ce7-9527-0f40fc29925a»,
|
||||
«7743a485-024d-43b6-bd5f-ebd3182eb94d»,
|
||||
«5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d»,
|
||||
]
|
||||
|
||||
def restoreState : RestoreStateM Unit := do
|
||||
addAssociationTable table
|
||||
@@ -0,0 +1,21 @@
|
||||
import Grove.Framework
|
||||
|
||||
/-
|
||||
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
|
||||
conflicts, but be careful.
|
||||
-/
|
||||
|
||||
open Grove.Framework Widget
|
||||
|
||||
namespace GroveStdlib.Generated.«associative-modification-operations»
|
||||
|
||||
|
||||
def table : AssociationTable.Data .subexpression where
|
||||
widgetId := "associative-modification-operations"
|
||||
rows := #[
|
||||
]
|
||||
facts := #[
|
||||
]
|
||||
|
||||
def restoreState : RestoreStateM Unit := do
|
||||
addAssociationTable table
|
||||
@@ -16,7 +16,7 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.isEmpty,
|
||||
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.DHashMap α β) : Bool",
|
||||
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.isEmpty,
|
||||
@@ -24,23 +24,23 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
|
||||
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap α β cmp) : Bool",
|
||||
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap.Raw α β cmp) :\n Bool",
|
||||
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.ExtDTreeMap α β cmp) :\n Bool",
|
||||
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "Std.HashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.isEmpty,
|
||||
renderedStatement := "Std.HashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashMap α β) : Bool",
|
||||
renderedStatement := "Std.HashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.Raw.isEmpty,
|
||||
@@ -48,19 +48,19 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashMap.isEmpty,
|
||||
renderedStatement := "Std.ExtHashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashMap α β) : Bool",
|
||||
renderedStatement := "Std.ExtHashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.isEmpty,
|
||||
renderedStatement := "Std.TreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp) : Bool",
|
||||
renderedStatement := "Std.TreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.TreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap.Raw α β cmp) : Bool",
|
||||
renderedStatement := "Std.TreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap.Raw α β cmp) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.isEmpty,
|
||||
renderedStatement := "Std.ExtTreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.ExtTreeMap α β cmp) : Bool",
|
||||
renderedStatement := "Std.ExtTreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.ExtTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.isEmpty,
|
||||
@@ -72,7 +72,7 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashSet.isEmpty,
|
||||
renderedStatement := "Std.ExtHashSet.isEmpty.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) : Bool",
|
||||
renderedStatement := "Std.ExtHashSet.isEmpty.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashSet α) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.isEmpty,
|
||||
@@ -97,7 +97,7 @@ def «f084f852-af71-45b6-8ab3-d251a8144f72» : AssociationTable.Fact .subexpress
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.size,
|
||||
renderedStatement := "Std.DHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.DHashMap α β) : Nat",
|
||||
renderedStatement := "Std.DHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.size,
|
||||
@@ -105,23 +105,23 @@ def «f084f852-af71-45b6-8ab3-d251a8144f72» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.size,
|
||||
renderedStatement := "Std.ExtDHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtDHashMap α β) : Nat",
|
||||
renderedStatement := "Std.ExtDHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.size,
|
||||
renderedStatement := "Std.DTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.DTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.size,
|
||||
renderedStatement := "Std.DTreeMap.Raw.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap.Raw α β cmp) : Nat",
|
||||
renderedStatement := "Std.DTreeMap.Raw.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.size,
|
||||
renderedStatement := "Std.ExtDTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.ExtDTreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.ExtDTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "Std.HashMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.size,
|
||||
renderedStatement := "Std.HashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashMap α β) : Nat",
|
||||
renderedStatement := "Std.HashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.Raw.size,
|
||||
@@ -129,19 +129,19 @@ def «f084f852-af71-45b6-8ab3-d251a8144f72» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashMap.size,
|
||||
renderedStatement := "Std.ExtHashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashMap α β) : Nat",
|
||||
renderedStatement := "Std.ExtHashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.size,
|
||||
renderedStatement := "Std.TreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.TreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.size,
|
||||
renderedStatement := "Std.TreeMap.Raw.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap.Raw α β cmp) : Nat",
|
||||
renderedStatement := "Std.TreeMap.Raw.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap.Raw α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.size,
|
||||
renderedStatement := "Std.ExtTreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.ExtTreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.ExtTreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.ExtTreeMap α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.size,
|
||||
@@ -178,11 +178,11 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
|
||||
rowState := #[⟨"Std.DTreeMap", "Std.DTreeMap.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.any,
|
||||
renderedStatement := "Std.DTreeMap.any.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap α β cmp)\n (p : (a : α) → β a → Bool) : Bool",
|
||||
renderedStatement := "Std.DTreeMap.any.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.any,
|
||||
renderedStatement := "Std.DTreeMap.Raw.any.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap.Raw α β cmp)\n (p : (a : α) → β a → Bool) : Bool",
|
||||
renderedStatement := "Std.DTreeMap.Raw.any.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) (p : (a : α) → β a → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.any,
|
||||
@@ -190,11 +190,11 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.any,
|
||||
renderedStatement := "Std.TreeMap.any.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp) (p : α → β → Bool) :\n Bool",
|
||||
renderedStatement := "Std.TreeMap.any.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp)\n (p : α → β → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.any,
|
||||
renderedStatement := "Std.TreeMap.Raw.any.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap.Raw α β cmp)\n (p : α → β → Bool) : Bool",
|
||||
renderedStatement := "Std.TreeMap.Raw.any.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (p : α → β → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.any,
|
||||
@@ -202,7 +202,7 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.any,
|
||||
renderedStatement := "Std.HashSet.any.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α) (p : α → Bool) : Bool",
|
||||
renderedStatement := "Std.HashSet.any.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α)\n (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.any,
|
||||
@@ -210,15 +210,15 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.any,
|
||||
renderedStatement := "Std.TreeSet.any.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) : Bool",
|
||||
renderedStatement := "Std.TreeSet.any.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) :\n Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.any,
|
||||
renderedStatement := "Std.TreeSet.Raw.any.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp) (p : α → Bool) : Bool",
|
||||
renderedStatement := "Std.TreeSet.Raw.any.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp)\n (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.any,
|
||||
renderedStatement := "Std.ExtTreeSet.any.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp)\n (p : α → Bool) : Bool",
|
||||
renderedStatement := "Std.ExtTreeSet.any.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,]
|
||||
metadata := {
|
||||
status := .bad
|
||||
@@ -228,62 +228,51 @@ def «c1d181f6-3204-4956-946f-e81619f9feb4» : AssociationTable.Fact .subexpress
|
||||
widgetId := "associative-query-operations"
|
||||
factId := "c1d181f6-3204-4956-946f-e81619f9feb4"
|
||||
rowId := "c1d181f6-3204-4956-946f-e81619f9feb4"
|
||||
rowState := #[⟨"Std.DTreeMap", "Std.DTreeMap.all", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.all
|
||||
renderedStatement := "Std.DTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap α β cmp)\n (p : (a : α) → β a → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.all", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.Raw.all
|
||||
renderedStatement := "Std.DTreeMap.Raw.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap.Raw α β cmp)\n (p : (a : α) → β a → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.all", .declaration (Declaration.def {
|
||||
name := `Std.ExtDTreeMap.all
|
||||
renderedStatement := "Std.ExtDTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtDTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeMap", "Std.TreeMap.all", .declaration (Declaration.def {
|
||||
name := `Std.TreeMap.all
|
||||
renderedStatement := "Std.TreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp) (p : α → β → Bool) :\n Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.all", .declaration (Declaration.def {
|
||||
name := `Std.TreeMap.Raw.all
|
||||
renderedStatement := "Std.TreeMap.Raw.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap.Raw α β cmp)\n (p : α → β → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.all", .declaration (Declaration.def {
|
||||
name := `Std.ExtTreeMap.all
|
||||
renderedStatement := "Std.ExtTreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (p : α → β → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashSet", "Std.HashSet.all", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.all
|
||||
renderedStatement := "Std.HashSet.all.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α) (p : α → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.all", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.Raw.all
|
||||
renderedStatement := "Std.HashSet.Raw.all.{u} {α : Type u} (m : Std.HashSet.Raw α) (p : α → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet", "Std.TreeSet.all", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.all
|
||||
renderedStatement := "Std.TreeSet.all.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.all", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.Raw.all
|
||||
renderedStatement := "Std.TreeSet.Raw.all.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp) (p : α → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.all", .declaration (Declaration.def {
|
||||
name := `Std.ExtTreeSet.all
|
||||
renderedStatement := "Std.ExtTreeSet.all.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp)\n (p : α → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,]
|
||||
rowState := #[⟨"Std.DTreeMap", "Std.DTreeMap.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.all,
|
||||
renderedStatement := "Std.DTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.all,
|
||||
renderedStatement := "Std.DTreeMap.Raw.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) (p : (a : α) → β a → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.all,
|
||||
renderedStatement := "Std.ExtDTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtDTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.all,
|
||||
renderedStatement := "Std.TreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp)\n (p : α → β → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.all,
|
||||
renderedStatement := "Std.TreeMap.Raw.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (p : α → β → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.all,
|
||||
renderedStatement := "Std.ExtTreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (p : α → β → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.all,
|
||||
renderedStatement := "Std.HashSet.all.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α)\n (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.all,
|
||||
renderedStatement := "Std.HashSet.Raw.all.{u} {α : Type u} (m : Std.HashSet.Raw α) (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.all,
|
||||
renderedStatement := "Std.TreeSet.all.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) :\n Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.all,
|
||||
renderedStatement := "Std.TreeSet.Raw.all.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp)\n (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.all,
|
||||
renderedStatement := "Std.ExtTreeSet.all.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,]
|
||||
metadata := {
|
||||
status := .bad
|
||||
comment := "Missing for some containers"
|
||||
@@ -292,97 +281,79 @@ def «efe57f41-7db7-4303-b3a6-5216a70c43ce» : AssociationTable.Fact .subexpress
|
||||
widgetId := "associative-query-operations"
|
||||
factId := "efe57f41-7db7-4303-b3a6-5216a70c43ce"
|
||||
rowId := "efe57f41-7db7-4303-b3a6-5216a70c43ce"
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.DHashMap.getD
|
||||
renderedStatement := "Std.DHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.DHashMap.Raw.getD
|
||||
renderedStatement := "Std.DHashMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α] [LawfulBEq α] (m : Std.DHashMap.Raw α β)\n (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtDHashMap.getD
|
||||
renderedStatement := "Std.ExtDHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.ExtDHashMap α β) (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DTreeMap", "Std.DTreeMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.getD
|
||||
renderedStatement := "Std.DTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap α β cmp) (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.Raw.getD
|
||||
renderedStatement := "Std.DTreeMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap.Raw α β cmp) (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtDTreeMap.getD
|
||||
renderedStatement := "Std.ExtDTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashMap", "Std.HashMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.HashMap.getD
|
||||
renderedStatement := "Std.HashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashMap α β) (a : α)\n (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.HashMap.Raw.getD
|
||||
renderedStatement := "Std.HashMap.Raw.getD.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (m : Std.HashMap.Raw α β) (a : α)\n (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtHashMap.getD
|
||||
renderedStatement := "Std.ExtHashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashMap α β) (a : α) (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeMap", "Std.TreeMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.TreeMap.getD
|
||||
renderedStatement := "Std.TreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp) (a : α)\n (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.TreeMap.Raw.getD
|
||||
renderedStatement := "Std.TreeMap.Raw.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap.Raw α β cmp) (a : α)\n (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtTreeMap.getD
|
||||
renderedStatement := "Std.ExtTreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (a : α) (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashSet", "Std.HashSet.getD", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.getD
|
||||
renderedStatement := "Std.HashSet.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.Raw.getD
|
||||
renderedStatement := "Std.HashSet.Raw.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α) (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtHashSet.getD
|
||||
renderedStatement := "Std.ExtHashSet.getD.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet", "Std.TreeSet.getD", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.getD
|
||||
renderedStatement := "Std.TreeSet.getD.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.Raw.getD
|
||||
renderedStatement := "Std.TreeSet.Raw.getD.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp) (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtTreeSet.getD
|
||||
renderedStatement := "Std.ExtTreeSet.getD.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp)\n (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,]
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.getD,
|
||||
renderedStatement := "Std.DHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (fallback : β a) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.getD,
|
||||
renderedStatement := "Std.DHashMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α] [LawfulBEq α]\n (m : Std.DHashMap.Raw α β) (a : α) (fallback : β a) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.getD,
|
||||
renderedStatement := "Std.ExtDHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [LawfulBEq α] (m : Std.ExtDHashMap α β) (a : α) (fallback : β a) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.getD,
|
||||
renderedStatement := "Std.DTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap α β cmp) (a : α) (fallback : β a) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.getD,
|
||||
renderedStatement := "Std.DTreeMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap.Raw α β cmp) (a : α) (fallback : β a) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.getD,
|
||||
renderedStatement := "Std.ExtDTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n [Std.TransCmp cmp] [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (fallback : β a) :\n β a",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "Std.HashMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.getD,
|
||||
renderedStatement := "Std.HashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.Raw.getD,
|
||||
renderedStatement := "Std.HashMap.Raw.getD.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (m : Std.HashMap.Raw α β)\n (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashMap.getD,
|
||||
renderedStatement := "Std.ExtHashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.getD,
|
||||
renderedStatement := "Std.TreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp)\n (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.getD,
|
||||
renderedStatement := "Std.TreeMap.Raw.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.getD,
|
||||
renderedStatement := "Std.ExtTreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.getD,
|
||||
renderedStatement := "Std.HashSet.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.getD,
|
||||
renderedStatement := "Std.HashSet.Raw.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α)\n (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashSet.getD,
|
||||
renderedStatement := "Std.ExtHashSet.getD.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.getD,
|
||||
renderedStatement := "Std.TreeSet.getD.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp)\n (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.getD,
|
||||
renderedStatement := "Std.TreeSet.Raw.getD.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp)\n (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.getD,
|
||||
renderedStatement := "Std.ExtTreeSet.getD.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,]
|
||||
metadata := {
|
||||
status := .done
|
||||
comment := ""
|
||||
@@ -391,73 +362,61 @@ def «e23b1119-3b57-433e-a68d-68fd70b9943d» : AssociationTable.Fact .subexpress
|
||||
widgetId := "associative-query-operations"
|
||||
factId := "e23b1119-3b57-433e-a68d-68fd70b9943d"
|
||||
rowId := "e23b1119-3b57-433e-a68d-68fd70b9943d"
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.get", .declaration (Declaration.def {
|
||||
name := `Std.DHashMap.get
|
||||
renderedStatement := "Std.DHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (h : a ∈ m) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.Const.get", .declaration (Declaration.def {
|
||||
name := `Std.DHashMap.Raw.Const.get
|
||||
renderedStatement := "Std.DHashMap.Raw.Const.get.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (m : Std.DHashMap.Raw α fun x => β)\n (a : α) (h : a ∈ m) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.get", .declaration (Declaration.def {
|
||||
name := `Std.ExtDHashMap.get
|
||||
renderedStatement := "Std.ExtDHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.ExtDHashMap α β) (a : α) (h : a ∈ m) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DTreeMap", "Std.DTreeMap.get", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.get
|
||||
renderedStatement := "Std.DTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap α β cmp) (a : α) (h : a ∈ t) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.get", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.Raw.get
|
||||
renderedStatement := "Std.DTreeMap.Raw.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap.Raw α β cmp) (a : α) (h : a ∈ t) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.get", .declaration (Declaration.def {
|
||||
name := `Std.ExtDTreeMap.get
|
||||
renderedStatement := "Std.ExtDTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (h : a ∈ t) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashMap", "app (GetElem.getElem) (Std.HashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.get,
|
||||
renderedStatement := "Std.DHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (h : a ∈ m) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.Const.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.Const.get,
|
||||
renderedStatement := "Std.DHashMap.Raw.Const.get.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (m : Std.DHashMap.Raw α fun x => β) (a : α) (h : a ∈ m) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.get,
|
||||
renderedStatement := "Std.ExtDHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [LawfulBEq α] (m : Std.ExtDHashMap α β) (a : α) (h : a ∈ m) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.get,
|
||||
renderedStatement := "Std.DTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap α β cmp) (a : α) (h : a ∈ t) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.get,
|
||||
renderedStatement := "Std.DTreeMap.Raw.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap.Raw α β cmp) (a : α) (h : a ∈ t) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.get,
|
||||
renderedStatement := "Std.ExtDTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (h : a ∈ t) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "app (GetElem.getElem) (Std.HashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.HashMap*)", displayShort := "Std.HashMap[·]" }⟩,⟨"Std.HashMap.Raw", "app (GetElem.getElem) (Std.HashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.HashMap.Raw*)", displayShort := "Std.HashMap.Raw[·]" }⟩,⟨"Std.ExtHashMap", "app (GetElem.getElem) (Std.ExtHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.ExtHashMap*)", displayShort := "Std.ExtHashMap[·]" }⟩,⟨"Std.TreeMap", "app (GetElem.getElem) (Std.TreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.TreeMap*)", displayShort := "Std.TreeMap[·]" }⟩,⟨"Std.TreeMap.Raw", "app (GetElem.getElem) (Std.TreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.TreeMap.Raw*)", displayShort := "Std.TreeMap.Raw[·]" }⟩,⟨"Std.ExtTreeMap", "app (GetElem.getElem) (Std.ExtTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.ExtTreeMap*)", displayShort := "Std.ExtTreeMap[·]" }⟩,⟨"Std.HashSet", "Std.HashSet.get", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.get
|
||||
renderedStatement := "Std.HashSet.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a : α) (h : a ∈ m) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.get", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.Raw.get
|
||||
renderedStatement := "Std.HashSet.Raw.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α) (a : α) (h : a ∈ m) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.get", .declaration (Declaration.def {
|
||||
name := `Std.ExtHashSet.get
|
||||
renderedStatement := "Std.ExtHashSet.get.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a : α) (h : a ∈ m) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet", "Std.TreeSet.get", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.get
|
||||
renderedStatement := "Std.TreeSet.get.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (a : α) (h : a ∈ t) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.get", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.Raw.get
|
||||
renderedStatement := "Std.TreeSet.Raw.get.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp) (a : α) (h : a ∈ t) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.get", .declaration (Declaration.def {
|
||||
name := `Std.ExtTreeSet.get
|
||||
renderedStatement := "Std.ExtTreeSet.get.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp) (a : α)\n (h : a ∈ t) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,]
|
||||
{ key := "app (GetElem.getElem) (Std.ExtTreeMap*)", displayShort := "Std.ExtTreeMap[·]" }⟩,⟨"Std.HashSet", "Std.HashSet.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.get,
|
||||
renderedStatement := "Std.HashSet.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a : α) (h : a ∈ m) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.get,
|
||||
renderedStatement := "Std.HashSet.Raw.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α) (a : α)\n (h : a ∈ m) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashSet.get,
|
||||
renderedStatement := "Std.ExtHashSet.get.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a : α) (h : a ∈ m) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.get,
|
||||
renderedStatement := "Std.TreeSet.get.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (a : α)\n (h : a ∈ t) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.get,
|
||||
renderedStatement := "Std.TreeSet.Raw.get.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp) (a : α)\n (h : a ∈ t) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.get,
|
||||
renderedStatement := "Std.ExtTreeSet.get.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (a : α) (h : a ∈ t) : α",
|
||||
isDeprecated := false })⟩,]
|
||||
metadata := {
|
||||
status := .bad
|
||||
comment := "Should *Set have GetElem?"
|
||||
|
||||
@@ -20,23 +20,75 @@ def sequentialContainers : Node :=
|
||||
|
||||
namespace AssociativeContainers
|
||||
|
||||
def associativeQueryOperations : AssociationTable .subexpression
|
||||
[`Std.DHashMap, `Std.DHashMap.Raw, `Std.ExtDHashMap, `Std.DTreeMap, `Std.DTreeMap.Raw, `Std.ExtDTreeMap, `Std.HashMap,
|
||||
`Std.HashMap.Raw, `Std.ExtHashMap, `Std.TreeMap, `Std.TreeMap.Raw, `Std.ExtTreeMap, `Std.HashSet, `Std.HashSet.Raw, `Std.ExtHashSet,
|
||||
`Std.TreeSet, `Std.TreeSet.Raw, `Std.ExtTreeSet] where
|
||||
def associativeContainers : List Lean.Name :=
|
||||
[`Std.DHashMap, `Std.DHashMap.Raw, `Std.ExtDHashMap, `Std.DTreeMap, `Std.DTreeMap.Raw, `Std.ExtDTreeMap, `Std.HashMap,
|
||||
`Std.HashMap.Raw, `Std.ExtHashMap, `Std.TreeMap, `Std.TreeMap.Raw, `Std.ExtTreeMap, `Std.HashSet, `Std.HashSet.Raw, `Std.ExtHashSet,
|
||||
`Std.TreeSet, `Std.TreeSet.Raw, `Std.ExtTreeSet]
|
||||
|
||||
def associativeQueryOperations : AssociationTable .subexpression associativeContainers where
|
||||
id := "associative-query-operations"
|
||||
title := "Associative query operations"
|
||||
description := "Operations that take as input an associative container and return a 'single' piece of information (e.g., `GetElem` or `isEmpty`, but not `toList`)."
|
||||
dataSources n :=
|
||||
(DataSource.declarationsInNamespace n .definitionsOnly)
|
||||
(DataSource.definitionsInNamespace n)
|
||||
|>.map Subexpression.declaration
|
||||
|>.or (DataSource.getElem n)
|
||||
|
||||
def associativeCreationOperations : AssociationTable .subexpression associativeContainers where
|
||||
id := "associative-creation-operations"
|
||||
title := "Associative creation operations"
|
||||
description := "Operations that create a new associative container"
|
||||
dataSources n :=
|
||||
(DataSource.definitionsInNamespace n)
|
||||
|>.map Subexpression.declaration
|
||||
|>.or (DataSource.emptyCollection n)
|
||||
|
||||
def associativeModificationOperations : AssociationTable .subexpression associativeContainers where
|
||||
id := "associative-modification-operations"
|
||||
title := "Associative modification operations"
|
||||
description := "Operations that both accept and return an associative container"
|
||||
dataSources n :=
|
||||
(DataSource.definitionsInNamespace n)
|
||||
|>.map Subexpression.declaration
|
||||
|
||||
def associativeCreateThenQuery : Table .subexpression .subexpression .declaration associativeContainers where
|
||||
id := "associative-create-then-query"
|
||||
title := "Associative create then query"
|
||||
description := "Lemmas that say what happens when creating a new associative container and then immediately querying from it"
|
||||
rowsFrom := .table associativeCreationOperations
|
||||
columnsFrom := .table associativeQueryOperations
|
||||
cellData := .classic _ { relevantNamespaces := associativeContainers }
|
||||
|
||||
def allOperationsCovered : Assertion where
|
||||
widgetId := "associative-all-operations-covered"
|
||||
title := "All operations on associative containers covered"
|
||||
description := "All operations on an associative container should appear in at least one of the tables"
|
||||
check := do
|
||||
let allValuesArray : Array String ← #[associativeQueryOperations, associativeCreationOperations, associativeModificationOperations].flatMapM valuesInAssociationTable
|
||||
let allValues : Std.HashSet String := Std.HashSet.ofArray allValuesArray
|
||||
let env ← Lean.getEnv
|
||||
let mut numBad := 0
|
||||
for (n, _) in env.constants do
|
||||
if associativeContainers.any (fun namesp => namesp.isPrefixOf n) then
|
||||
if !n.toString ∈ allValues then
|
||||
numBad := numBad + 1
|
||||
return #[{
|
||||
assertionId := "all-covered"
|
||||
description := "All operations should be covered"
|
||||
passed := numBad == 0
|
||||
message := if numBad = 0 then "All operations were covered" else s!"There were {numBad} operations that were not covered."
|
||||
}]
|
||||
|
||||
end AssociativeContainers
|
||||
|
||||
open AssociativeContainers in
|
||||
def associativeContainers : Node :=
|
||||
.section "associative-containers" "Associative containers" #[
|
||||
.associationTable AssociativeContainers.associativeQueryOperations
|
||||
.associationTable associativeQueryOperations,
|
||||
.associationTable associativeCreationOperations,
|
||||
.associationTable associativeModificationOperations,
|
||||
.table associativeCreateThenQuery,
|
||||
.assertion allOperationsCovered
|
||||
]
|
||||
|
||||
namespace PersistentDataStructures
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
lake exe grove-stdlib --full metadata.json
|
||||
cd .lake/packages/grove/frontend
|
||||
npm install
|
||||
cp ../../../../metadata.json public/metadata.json
|
||||
if [ -f "../../../../invalidated.json" ]; then
|
||||
GROVE_DATA_LOCATION=../../../../metadata.json GROVE_UPSTREAM_INVALIDATED_FACTS_LOCATION=../../../../invalidated.json npm run dev
|
||||
cp ../../../../invalidated.json public/invalidated.json
|
||||
GROVE_DATA_LOCATION=public/metadata.json GROVE_UPSTREAM_INVALIDATED_FACTS_LOCATION=public/invalidated.json npm run dev
|
||||
else
|
||||
GROVE_DATA_LOCATION=../../../../metadata.json npm run dev
|
||||
fi
|
||||
GROVE_DATA_LOCATION=public/metadata.json npm run dev
|
||||
fi
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"type": "git",
|
||||
"subDir": "backend",
|
||||
"scope": "",
|
||||
"rev": "e8127fc6554b99fb988ecdceb770a5e112afbe24",
|
||||
"rev": "3e8aabdea58c11813c5d3b7eeb187ded44ee9a34",
|
||||
"name": "grove",
|
||||
"manifestFile": "lake-manifest.json",
|
||||
"inputRev": "master",
|
||||
|
||||
12
flake.nix
12
flake.nix
@@ -18,14 +18,14 @@
|
||||
# An old nixpkgs for creating releases with an old glibc
|
||||
pkgsDist-old-aarch = import inputs.nixpkgs-old { localSystem.config = "aarch64-unknown-linux-gnu"; };
|
||||
|
||||
lean-packages = pkgs.callPackage (./nix/packages.nix) { src = ./.; };
|
||||
llvmPackages = pkgs.llvmPackages_15;
|
||||
|
||||
devShellWithDist = pkgsDist: pkgs.mkShell.override {
|
||||
stdenv = pkgs.overrideCC pkgs.stdenv lean-packages.llvmPackages.clang;
|
||||
stdenv = pkgs.overrideCC pkgs.stdenv llvmPackages.clang;
|
||||
} ({
|
||||
buildInputs = with pkgs; [
|
||||
cmake gmp libuv ccache pkg-config
|
||||
lean-packages.llvmPackages.llvm # llvm-symbolizer for asan/lsan
|
||||
llvmPackages.llvm # llvm-symbolizer for asan/lsan
|
||||
gdb
|
||||
tree # for CI
|
||||
];
|
||||
@@ -60,12 +60,6 @@
|
||||
GDB = pkgsDist.gdb;
|
||||
});
|
||||
in {
|
||||
packages.${system} = {
|
||||
# to be removed when Nix CI is not needed anymore
|
||||
inherit (lean-packages) cacheRoots test update-stage0-commit ciShell;
|
||||
deprecated = lean-packages;
|
||||
};
|
||||
|
||||
devShells.${system} = {
|
||||
# The default development shell for working on lean itself
|
||||
default = devShellWithDist pkgs;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
set -eo pipefail
|
||||
|
||||
for pkg in $buildInputs; do
|
||||
export PATH=$PATH:$pkg/bin
|
||||
done
|
||||
|
||||
: ${outputs:=out}
|
||||
@@ -1,208 +0,0 @@
|
||||
{ src, debug ? false, stage0debug ? false, extraCMakeFlags ? [],
|
||||
stdenv, lib, cmake, pkg-config, gmp, libuv, cadical, git, gnumake, bash, buildLeanPackage, writeShellScriptBin, runCommand, symlinkJoin, lndir, perl, gnused, darwin, llvmPackages, linkFarmFromDrvs,
|
||||
... } @ args:
|
||||
with builtins;
|
||||
lib.warn "The Nix-based build is deprecated" rec {
|
||||
inherit stdenv;
|
||||
sourceByRegex = p: rs: lib.sourceByRegex p (map (r: "(/src/)?${r}") rs);
|
||||
buildCMake = args: stdenv.mkDerivation ({
|
||||
nativeBuildInputs = [ cmake pkg-config ];
|
||||
buildInputs = [ gmp libuv llvmPackages.llvm ];
|
||||
# https://github.com/NixOS/nixpkgs/issues/60919
|
||||
hardeningDisable = [ "all" ];
|
||||
dontStrip = (args.debug or debug);
|
||||
|
||||
postConfigure = ''
|
||||
patchShebangs .
|
||||
'';
|
||||
} // args // {
|
||||
src = args.realSrc or (sourceByRegex args.src [ "[a-z].*" "CMakeLists\.txt" ]);
|
||||
cmakeFlags = ["-DSMALL_ALLOCATOR=ON" "-DUSE_MIMALLOC=OFF"] ++ (args.cmakeFlags or [ "-DSTAGE=1" "-DPREV_STAGE=./faux-prev-stage" "-DUSE_GITHASH=OFF" "-DCADICAL=${cadical}/bin/cadical" ]) ++ (args.extraCMakeFlags or extraCMakeFlags) ++ lib.optional (args.debug or debug) [ "-DCMAKE_BUILD_TYPE=Debug" ];
|
||||
preConfigure = args.preConfigure or "" + ''
|
||||
# ignore absence of submodule
|
||||
sed -i 's!lake/Lake.lean!!' CMakeLists.txt
|
||||
'';
|
||||
});
|
||||
lean-bin-tools-unwrapped = buildCMake {
|
||||
name = "lean-bin-tools";
|
||||
outputs = [ "out" "leanc_src" ];
|
||||
realSrc = sourceByRegex (src + "/src") [ "CMakeLists\.txt" "[a-z].*" ".*\.in" "Leanc\.lean" ];
|
||||
dontBuild = true;
|
||||
installPhase = ''
|
||||
mkdir $out $leanc_src
|
||||
mv bin/ include/ share/ $out/
|
||||
mv leanc.sh $out/bin/leanc
|
||||
mv leanc/Leanc.lean $leanc_src/
|
||||
substituteInPlace $out/bin/leanc --replace '$root' "$out" --replace " sed " " ${gnused}/bin/sed "
|
||||
substituteInPlace $out/bin/leanmake --replace "make" "${gnumake}/bin/make"
|
||||
substituteInPlace $out/share/lean/lean.mk --replace "/usr/bin/env bash" "${bash}/bin/bash"
|
||||
'';
|
||||
};
|
||||
leancpp = buildCMake {
|
||||
name = "leancpp";
|
||||
src = src + "/src";
|
||||
buildFlags = [ "leancpp" "leanrt" "leanrt_initial-exec" "leanshell" "leanmain" ];
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
mv lib/ $out/
|
||||
mv runtime/libleanrt_initial-exec.a $out/lib
|
||||
'';
|
||||
};
|
||||
stage0 = args.stage0 or (buildCMake {
|
||||
name = "lean-stage0";
|
||||
realSrc = src + "/stage0/src";
|
||||
debug = stage0debug;
|
||||
cmakeFlags = [ "-DSTAGE=0" ];
|
||||
extraCMakeFlags = [];
|
||||
preConfigure = ''
|
||||
ln -s ${src + "/stage0/stdlib"} ../stdlib
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin $out/lib/lean
|
||||
mv bin/lean $out/bin/
|
||||
mv lib/lean/*.{so,dylib} $out/lib/lean
|
||||
'';
|
||||
meta.mainProgram = "lean";
|
||||
});
|
||||
stage = { stage, prevStage, self }:
|
||||
let
|
||||
desc = "stage${toString stage}";
|
||||
build = args: buildLeanPackage.override {
|
||||
lean = prevStage;
|
||||
leanc = lean-bin-tools-unwrapped;
|
||||
# use same stage for retrieving dependencies
|
||||
lean-leanDeps = stage0;
|
||||
lean-final = self;
|
||||
} ({
|
||||
src = src + "/src";
|
||||
roots = [ { mod = args.name; glob = "andSubmodules"; } ];
|
||||
fullSrc = src;
|
||||
srcPath = "$PWD/src:$PWD/src/lake";
|
||||
inherit debug;
|
||||
leanFlags = [ "-DwarningAsError=true" ];
|
||||
} // args);
|
||||
Init' = build { name = "Init"; deps = []; };
|
||||
Std' = build { name = "Std"; deps = [ Init' ]; };
|
||||
Lean' = build { name = "Lean"; deps = [ Std' ]; };
|
||||
attachSharedLib = sharedLib: pkg: pkg // {
|
||||
inherit sharedLib;
|
||||
mods = mapAttrs (_: m: m // { inherit sharedLib; propagatedLoadDynlibs = []; }) pkg.mods;
|
||||
};
|
||||
in (all: all // all.lean) rec {
|
||||
inherit (Lean) emacs-dev emacs-package vscode-dev vscode-package;
|
||||
Init = attachSharedLib leanshared Init';
|
||||
Std = attachSharedLib leanshared Std' // { allExternalDeps = [ Init ]; };
|
||||
Lean = attachSharedLib leanshared Lean' // { allExternalDeps = [ Std ]; };
|
||||
Lake = build {
|
||||
name = "Lake";
|
||||
sharedLibName = "Lake_shared";
|
||||
src = src + "/src/lake";
|
||||
deps = [ Init Lean ];
|
||||
};
|
||||
Lake-Main = build {
|
||||
name = "LakeMain";
|
||||
roots = [{ glob = "one"; mod = "LakeMain"; }];
|
||||
executableName = "lake";
|
||||
deps = [ Lake ];
|
||||
linkFlags = lib.optional stdenv.isLinux "-rdynamic";
|
||||
src = src + "/src/lake";
|
||||
};
|
||||
stdlib = [ Init Std Lean Lake ];
|
||||
modDepsFiles = symlinkJoin { name = "modDepsFiles"; paths = map (l: l.modDepsFile) (stdlib ++ [ Leanc ]); };
|
||||
depRoots = symlinkJoin { name = "depRoots"; paths = map (l: l.depRoots) stdlib; };
|
||||
iTree = symlinkJoin { name = "ileans"; paths = map (l: l.iTree) stdlib; };
|
||||
Leanc = build { name = "Leanc"; src = lean-bin-tools-unwrapped.leanc_src; deps = stdlib; roots = [ "Leanc" ]; };
|
||||
stdlibLinkFlags = "${lib.concatMapStringsSep " " (l: "-L${l.staticLib}") stdlib} -L${leancpp}/lib/lean";
|
||||
libInit_shared = runCommand "libInit_shared" { buildInputs = [ stdenv.cc ]; libName = "libInit_shared${stdenv.hostPlatform.extensions.sharedLibrary}"; } ''
|
||||
mkdir $out
|
||||
touch empty.c
|
||||
${stdenv.cc}/bin/cc -shared -o $out/$libName empty.c
|
||||
'';
|
||||
leanshared_1 = runCommand "leanshared_1" { buildInputs = [ stdenv.cc ]; libName = "leanshared_1${stdenv.hostPlatform.extensions.sharedLibrary}"; } ''
|
||||
mkdir $out
|
||||
touch empty.c
|
||||
${stdenv.cc}/bin/cc -shared -o $out/$libName empty.c
|
||||
'';
|
||||
leanshared = runCommand "leanshared" { buildInputs = [ stdenv.cc ]; libName = "libleanshared${stdenv.hostPlatform.extensions.sharedLibrary}"; } ''
|
||||
mkdir $out
|
||||
LEAN_CC=${stdenv.cc}/bin/cc ${lean-bin-tools-unwrapped}/bin/leanc -shared ${lib.optionalString stdenv.isLinux "-Wl,-Bsymbolic"} \
|
||||
-Wl,--whole-archive ${leancpp}/lib/temp/libleanshell.a -lInit -lStd -lLean -lleancpp ${leancpp}/lib/libleanrt_initial-exec.a -Wl,--no-whole-archive -lstdc++ \
|
||||
-lm ${stdlibLinkFlags} \
|
||||
$(${llvmPackages.libllvm.dev}/bin/llvm-config --ldflags --libs) \
|
||||
-o $out/$libName
|
||||
'';
|
||||
mods = foldl' (mods: pkg: mods // pkg.mods) {} stdlib;
|
||||
print-paths = Lean.makePrintPathsFor [] mods;
|
||||
leanc = writeShellScriptBin "leanc" ''
|
||||
LEAN_CC=${stdenv.cc}/bin/cc ${Leanc.executable}/bin/leanc -I${lean-bin-tools-unwrapped}/include ${stdlibLinkFlags} -L${libInit_shared} -L${leanshared_1} -L${leanshared} -L${Lake.sharedLib} "$@"
|
||||
'';
|
||||
lean = runCommand "lean" { buildInputs = lib.optional stdenv.isDarwin darwin.cctools; } ''
|
||||
mkdir -p $out/bin
|
||||
${leanc}/bin/leanc ${leancpp}/lib/temp/libleanmain.a ${libInit_shared}/* ${leanshared_1}/* ${leanshared}/* -o $out/bin/lean
|
||||
'';
|
||||
# derivation following the directory layout of the "basic" setup, mostly useful for running tests
|
||||
lean-all = stdenv.mkDerivation {
|
||||
name = "lean-${desc}";
|
||||
buildCommand = ''
|
||||
mkdir -p $out/bin $out/lib/lean
|
||||
ln -sf ${leancpp}/lib/lean/* ${lib.concatMapStringsSep " " (l: "${l.modRoot}/* ${l.staticLib}/*") (lib.reverseList stdlib)} ${libInit_shared}/* ${leanshared_1}/* ${leanshared}/* ${Lake.sharedLib}/* $out/lib/lean/
|
||||
# put everything in a single final derivation so `IO.appDir` references work
|
||||
cp ${lean}/bin/lean ${leanc}/bin/leanc ${Lake-Main.executable}/bin/lake $out/bin
|
||||
# NOTE: `lndir` will not override existing `bin/leanc`
|
||||
${lndir}/bin/lndir -silent ${lean-bin-tools-unwrapped} $out
|
||||
'';
|
||||
meta.mainProgram = "lean";
|
||||
};
|
||||
cacheRoots = linkFarmFromDrvs "cacheRoots" ([
|
||||
stage0 lean leanc lean-all iTree modDepsFiles depRoots Leanc.src
|
||||
] ++ map (lib: lib.oTree) stdlib);
|
||||
test = buildCMake {
|
||||
name = "lean-test-${desc}";
|
||||
realSrc = lib.sourceByRegex src [ "src.*" "tests.*" ];
|
||||
buildInputs = [ gmp libuv perl git cadical ];
|
||||
preConfigure = ''
|
||||
cd src
|
||||
'';
|
||||
extraCMakeFlags = [ "-DLLVM=OFF" ];
|
||||
postConfigure = ''
|
||||
patchShebangs ../../tests ../lake
|
||||
rm -r bin lib include share
|
||||
ln -sf ${lean-all}/* .
|
||||
'';
|
||||
buildPhase = ''
|
||||
ctest --output-junit test-results.xml --output-on-failure -E 'leancomptest_(doc_example|foreign)|leanlaketest_reverse-ffi|leanruntest_timeIO' -j$NIX_BUILD_CORES
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
mv test-results.xml $out
|
||||
'';
|
||||
};
|
||||
update-stage0 =
|
||||
let cTree = symlinkJoin { name = "cs"; paths = map (lib: lib.cTree) (stdlib ++ [Lake-Main]); }; in
|
||||
writeShellScriptBin "update-stage0" ''
|
||||
CSRCS=${cTree} CP_C_PARAMS="--dereference --no-preserve=all" ${src + "/script/lib/update-stage0"}
|
||||
'';
|
||||
update-stage0-commit = writeShellScriptBin "update-stage0-commit" ''
|
||||
set -euo pipefail
|
||||
${update-stage0}/bin/update-stage0
|
||||
git commit -m "chore: update stage0"
|
||||
'';
|
||||
link-ilean = writeShellScriptBin "link-ilean" ''
|
||||
dest=''${1:-src}
|
||||
rm -rf $dest/build/lib || true
|
||||
mkdir -p $dest/build/lib
|
||||
ln -s ${iTree}/* $dest/build/lib
|
||||
'';
|
||||
benchmarks =
|
||||
let
|
||||
entries = attrNames (readDir (src + "/tests/bench"));
|
||||
leanFiles = map (n: elemAt n 0) (filter (n: n != null) (map (match "(.*)\.lean") entries));
|
||||
in lib.genAttrs leanFiles (n: (buildLeanPackage {
|
||||
name = n;
|
||||
src = filterSource (e: _: baseNameOf e == "${n}.lean") (src + "/tests/bench");
|
||||
}).executable);
|
||||
};
|
||||
stage1 = stage { stage = 1; prevStage = stage0; self = stage1; };
|
||||
stage2 = stage { stage = 2; prevStage = stage1; self = stage2; };
|
||||
stage3 = stage { stage = 3; prevStage = stage2; self = stage3; };
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
{ lean, lean-leanDeps ? lean, lean-final ? lean, leanc,
|
||||
stdenv, lib, coreutils, gnused, writeShellScriptBin, bash, substituteAll, symlinkJoin, linkFarmFromDrvs,
|
||||
runCommand, darwin, mkShell, ... }:
|
||||
let lean-final' = lean-final; in
|
||||
lib.makeOverridable (
|
||||
{ name, src, fullSrc ? src, srcPrefix ? "", srcPath ? "$PWD/${srcPrefix}",
|
||||
# Lean dependencies. Each entry should be an output of buildLeanPackage.
|
||||
deps ? [ lean.Init lean.Std lean.Lean ],
|
||||
# Static library dependencies. Each derivation `static` should contain a static library in the directory `${static}`.
|
||||
staticLibDeps ? [],
|
||||
# Whether to wrap static library inputs in a -Wl,--start-group [...] -Wl,--end-group to ensure dependencies are resolved.
|
||||
groupStaticLibs ? false,
|
||||
# Shared library dependencies included at interpretation with --load-dynlib and linked to. Each derivation `shared` should contain a
|
||||
# shared library at the path `${shared}/${shared.libName or shared.name}` and a name to link to like `-l${shared.linkName or shared.name}`.
|
||||
# These libs are also linked to in packages that depend on this one.
|
||||
nativeSharedLibs ? [],
|
||||
# Lean modules to include.
|
||||
# A set of Lean modules names as strings (`"Foo.Bar"`) or attrsets (`{ name = "Foo.Bar"; glob = "one" | "submodules" | "andSubmodules"; }`);
|
||||
# see Lake README for glob meanings. Dependencies of selected modules are always included.
|
||||
roots ? [ name ],
|
||||
# Output from `lean --deps-json` on package source files. Persist the corresponding output attribute to a file and pass it back in here to avoid IFD.
|
||||
# Must be refreshed on any change in `import`s or set of source file names.
|
||||
modDepsFile ? null,
|
||||
# Whether to compile each module into a native shared library that is loaded whenever the module is imported in order to accelerate evaluation
|
||||
precompileModules ? false,
|
||||
# Whether to compile the package into a native shared library that is loaded whenever *any* of the package's modules is imported into another package.
|
||||
# If `precompileModules` is also `true`, the latter only affects imports within the current package.
|
||||
precompilePackage ? precompileModules,
|
||||
# Lean plugin dependencies. Each derivation `plugin` should contain a plugin library at path `${plugin}/${plugin.name}`.
|
||||
pluginDeps ? [],
|
||||
# `overrideAttrs` for `buildMod`
|
||||
overrideBuildModAttrs ? null,
|
||||
debug ? false, leanFlags ? [], leancFlags ? [], linkFlags ? [], executableName ? lib.toLower name, libName ? name, sharedLibName ? libName,
|
||||
srcTarget ? "..#stage0", srcArgs ? "(\${args[*]})", lean-final ? lean-final' }@args:
|
||||
with builtins; let
|
||||
# "Init.Core" ~> "Init/Core"
|
||||
modToPath = mod: replaceStrings ["."] ["/"] mod;
|
||||
modToAbsPath = mod: "${src}/${modToPath mod}";
|
||||
# sanitize file name before copying to store, except when already in store
|
||||
copyToStoreSafe = base: suffix: if lib.isDerivation base then base + suffix else
|
||||
builtins.path { name = lib.strings.sanitizeDerivationName (baseNameOf suffix); path = base + suffix; };
|
||||
modToLean = mod: copyToStoreSafe src "/${modToPath mod}.lean";
|
||||
bareStdenv = ./bareStdenv;
|
||||
mkBareDerivation = args: derivation (args // {
|
||||
name = lib.strings.sanitizeDerivationName args.name;
|
||||
stdenv = bareStdenv;
|
||||
inherit (stdenv) system;
|
||||
buildInputs = (args.buildInputs or []) ++ [ coreutils ];
|
||||
builder = stdenv.shell;
|
||||
args = [ "-c" ''
|
||||
source $stdenv/setup
|
||||
set -u
|
||||
${args.buildCommand}
|
||||
'' ];
|
||||
}) // { overrideAttrs = f: mkBareDerivation (lib.fix (lib.extends f (_: args))); };
|
||||
runBareCommand = name: args: buildCommand: mkBareDerivation (args // { inherit name buildCommand; });
|
||||
runBareCommandLocal = name: args: buildCommand: runBareCommand name (args // {
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
}) buildCommand;
|
||||
mkSharedLib = name: args: runBareCommand "${name}-dynlib" {
|
||||
buildInputs = [ stdenv.cc ] ++ lib.optional stdenv.isDarwin darwin.cctools;
|
||||
libName = "${name}${stdenv.hostPlatform.extensions.sharedLibrary}";
|
||||
} ''
|
||||
mkdir -p $out
|
||||
${leanc}/bin/leanc -shared ${args} -o $out/$libName
|
||||
'';
|
||||
depRoot = name: deps: mkBareDerivation {
|
||||
name = "${name}-depRoot";
|
||||
inherit deps;
|
||||
depRoots = map (drv: drv.LEAN_PATH) deps;
|
||||
|
||||
passAsFile = [ "deps" "depRoots" ];
|
||||
buildCommand = ''
|
||||
mkdir -p $out
|
||||
for i in $(cat $depRootsPath); do
|
||||
cp -dru --no-preserve=mode $i/. $out
|
||||
done
|
||||
for i in $(cat $depsPath); do
|
||||
cp -drsu --no-preserve=mode $i/. $out
|
||||
done
|
||||
'';
|
||||
};
|
||||
srcRoot = src;
|
||||
|
||||
# A flattened list of Lean-module dependencies (`deps`)
|
||||
allExternalDeps = lib.unique (lib.foldr (dep: allExternalDeps: allExternalDeps ++ [ dep ] ++ dep.allExternalDeps) [] deps);
|
||||
allNativeSharedLibs =
|
||||
lib.unique (lib.flatten (nativeSharedLibs ++ (map (dep: dep.allNativeSharedLibs or []) allExternalDeps)));
|
||||
|
||||
# A flattened list of all static library dependencies: this and every dep module's explicitly provided `staticLibDeps`,
|
||||
# plus every dep module itself: `dep.staticLib`
|
||||
allStaticLibDeps =
|
||||
lib.unique (lib.flatten (staticLibDeps ++ (map (dep: [dep.staticLib] ++ dep.staticLibDeps or []) allExternalDeps)));
|
||||
|
||||
pathOfSharedLib = dep: dep.libPath or "${dep}/${dep.libName or dep.name}";
|
||||
|
||||
leanPluginFlags = lib.concatStringsSep " " (map (dep: "--plugin=${pathOfSharedLib dep}") pluginDeps);
|
||||
loadDynlibsOfDeps = deps: lib.unique (concatMap (d: d.propagatedLoadDynlibs) deps);
|
||||
|
||||
# submodules "Init" = ["Init.List.Basic", "Init.Core", ...]
|
||||
submodules = mod: let
|
||||
dir = readDir (modToAbsPath mod);
|
||||
f = p: t:
|
||||
if t == "directory" then
|
||||
submodules "${mod}.${p}"
|
||||
else
|
||||
let m = builtins.match "(.*)\.lean" p;
|
||||
in lib.optional (m != null) "${mod}.${head m}";
|
||||
in concatLists (lib.mapAttrsToList f dir);
|
||||
|
||||
# conservatively approximate list of source files matched by glob
|
||||
expandGlobAllApprox = g:
|
||||
if typeOf g == "string" then
|
||||
# we can't know the required files without parsing dependencies (which is what we want this
|
||||
# function for), so we approximate to the entire package.
|
||||
let root = (head (split "\\." g));
|
||||
in lib.optional (pathExists (src + "/${modToPath root}.lean")) root ++ lib.optionals (pathExists (modToAbsPath root)) (submodules root)
|
||||
else if g.glob == "one" then expandGlobAllApprox g.mod
|
||||
else if g.glob == "submodules" then submodules g.mod
|
||||
else if g.glob == "andSubmodules" then [g.mod] ++ submodules g.mod
|
||||
else throw "unknown glob kind '${g}'";
|
||||
# list of modules that could potentially be involved in the build
|
||||
candidateMods = lib.unique (concatMap expandGlobAllApprox roots);
|
||||
candidateFiles = map modToLean candidateMods;
|
||||
modDepsFile = args.modDepsFile or mkBareDerivation {
|
||||
name = "${name}-deps.json";
|
||||
candidateFiles = lib.concatStringsSep " " candidateFiles;
|
||||
passAsFile = [ "candidateFiles" ];
|
||||
buildCommand = ''
|
||||
mkdir $out
|
||||
${lean-leanDeps}/bin/lean --deps-json --stdin < $candidateFilesPath > $out/$name
|
||||
'';
|
||||
};
|
||||
modDeps = fromJSON (
|
||||
# the only possible references to store paths in the JSON should be inside errors, so no chance of missed dependencies from this
|
||||
unsafeDiscardStringContext (readFile "${modDepsFile}/${modDepsFile.name}"));
|
||||
# map from module name to list of imports
|
||||
modDepsMap = listToAttrs (lib.zipListsWith lib.nameValuePair candidateMods modDeps.imports);
|
||||
maybeOverrideAttrs = f: x: if f != null then x.overrideAttrs f else x;
|
||||
# build module (.olean and .c) given derivations of all (immediate) dependencies
|
||||
# TODO: make `rec` parts override-compatible?
|
||||
buildMod = mod: deps: maybeOverrideAttrs overrideBuildModAttrs (mkBareDerivation rec {
|
||||
name = "${mod}";
|
||||
LEAN_PATH = depRoot mod deps;
|
||||
LEAN_ABORT_ON_PANIC = "1";
|
||||
relpath = modToPath mod;
|
||||
buildInputs = [ lean ];
|
||||
leanPath = relpath + ".lean";
|
||||
# should be either single .lean file or directory directly containing .lean file plus dependencies
|
||||
src = copyToStoreSafe srcRoot ("/" + leanPath);
|
||||
outputs = [ "out" "ilean" "c" ];
|
||||
oleanPath = relpath + ".olean";
|
||||
ileanPath = relpath + ".ilean";
|
||||
cPath = relpath + ".c";
|
||||
inherit leanFlags leanPluginFlags;
|
||||
leanLoadDynlibFlags = map (p: "--load-dynlib=${pathOfSharedLib p}") (loadDynlibsOfDeps deps);
|
||||
buildCommand = ''
|
||||
dir=$(dirname $relpath)
|
||||
mkdir -p $dir $out/$dir $ilean/$dir $c/$dir
|
||||
if [ -d $src ]; then cp -r $src/. .; else cp $src $leanPath; fi
|
||||
lean -o $out/$oleanPath -i $out/$ileanPath -c $c/$cPath $leanPath $leanFlags $leanPluginFlags $leanLoadDynlibFlags
|
||||
'';
|
||||
}) // {
|
||||
inherit deps;
|
||||
propagatedLoadDynlibs = loadDynlibsOfDeps deps;
|
||||
};
|
||||
compileMod = mod: drv: mkBareDerivation {
|
||||
name = "${mod}-cc";
|
||||
buildInputs = [ leanc stdenv.cc ];
|
||||
hardeningDisable = [ "all" ];
|
||||
oPath = drv.relpath + ".o";
|
||||
inherit leancFlags;
|
||||
buildCommand = ''
|
||||
mkdir -p $out/$(dirname ${drv.relpath})
|
||||
# make local "copy" so `drv`'s Nix store path doesn't end up in ccache's hash
|
||||
ln -s ${drv.c}/${drv.cPath} src.c
|
||||
# on the other hand, a debug build is pretty fast anyway, so preserve the path for gdb
|
||||
leanc -c -o $out/$oPath $leancFlags -fPIC ${if debug then "${drv.c}/${drv.cPath} -g" else "src.c -O3 -DNDEBUG -DLEAN_EXPORTING"}
|
||||
'';
|
||||
};
|
||||
mkMod = mod: deps:
|
||||
let drv = buildMod mod deps;
|
||||
obj = compileMod mod drv;
|
||||
# this attribute will only be used if any dependent module is precompiled
|
||||
sharedLib = mkSharedLib mod "${obj}/${obj.oPath} ${lib.concatStringsSep " " (map (d: pathOfSharedLib d.sharedLib) deps)}";
|
||||
in drv // {
|
||||
inherit obj sharedLib;
|
||||
} // lib.optionalAttrs precompileModules {
|
||||
propagatedLoadDynlibs = [sharedLib];
|
||||
};
|
||||
externalModMap = lib.foldr (dep: depMap: depMap // dep.mods) {} allExternalDeps;
|
||||
# map from module name to derivation
|
||||
modCandidates = mapAttrs (mod: header:
|
||||
let
|
||||
deps = if header.errors == []
|
||||
then map (m: m.module) header.result.imports
|
||||
else abort "errors while parsing imports of ${mod}:\n${lib.concatStringsSep "\n" header.errors}";
|
||||
in mkMod mod (map (dep: if modDepsMap ? ${dep} then modCandidates.${dep} else externalModMap.${dep}) deps)) modDepsMap;
|
||||
expandGlob = g:
|
||||
if typeOf g == "string" then [g]
|
||||
else if g.glob == "one" then [g.mod]
|
||||
else if g.glob == "submodules" then submodules g.mod
|
||||
else if g.glob == "andSubmodules" then [g.mod] ++ submodules g.mod
|
||||
else throw "unknown glob kind '${g}'";
|
||||
# subset of `modCandidates` that is transitively reachable from `roots`
|
||||
mods' = listToAttrs (map (e: { name = e.key; value = modCandidates.${e.key}; }) (genericClosure {
|
||||
startSet = map (m: { key = m; }) (concatMap expandGlob roots);
|
||||
operator = e: if modDepsMap ? ${e.key} then map (m: { key = m.module; }) (filter (m: modCandidates ? ${m.module}) modDepsMap.${e.key}.result.imports) else [];
|
||||
}));
|
||||
allLinkFlags = lib.foldr (shared: acc: acc ++ [ "-L${shared}" "-l${shared.linkName or shared.name}" ]) linkFlags allNativeSharedLibs;
|
||||
|
||||
objects = mapAttrs (_: m: m.obj) mods';
|
||||
bintools = if stdenv.isDarwin then darwin.cctools else stdenv.cc.bintools.bintools;
|
||||
staticLib = runCommand "${name}-lib" { buildInputs = [ bintools ]; } ''
|
||||
mkdir -p $out
|
||||
ar Trcs $out/lib${libName}.a ${lib.concatStringsSep " " (map (drv: "${drv}/${drv.oPath}") (attrValues objects))};
|
||||
'';
|
||||
|
||||
staticLibLinkWrapper = libs: if groupStaticLibs && !stdenv.isDarwin
|
||||
then "-Wl,--start-group ${libs} -Wl,--end-group"
|
||||
else "${libs}";
|
||||
in rec {
|
||||
inherit name lean deps staticLibDeps allNativeSharedLibs allLinkFlags allExternalDeps src objects staticLib modDepsFile;
|
||||
mods = mapAttrs (_: m:
|
||||
m //
|
||||
# if neither precompilation option was set but a dependent module wants to be precompiled, default to precompiling this package whole
|
||||
lib.optionalAttrs (precompilePackage || !precompileModules) { inherit sharedLib; } //
|
||||
lib.optionalAttrs precompilePackage { propagatedLoadDynlibs = [sharedLib]; })
|
||||
mods';
|
||||
modRoot = depRoot name (attrValues mods);
|
||||
depRoots = linkFarmFromDrvs "depRoots" (map (m: m.LEAN_PATH) (attrValues mods));
|
||||
cTree = symlinkJoin { name = "${name}-cTree"; paths = map (mod: mod.c) (attrValues mods); };
|
||||
oTree = symlinkJoin { name = "${name}-oTree"; paths = (attrValues objects); };
|
||||
iTree = symlinkJoin { name = "${name}-iTree"; paths = map (mod: mod.ilean) (attrValues mods); };
|
||||
sharedLib = mkSharedLib "lib${sharedLibName}" ''
|
||||
${if stdenv.isDarwin then "-Wl,-force_load,${staticLib}/lib${libName}.a" else "-Wl,--whole-archive ${staticLib}/lib${libName}.a -Wl,--no-whole-archive"} \
|
||||
${lib.concatStringsSep " " (map (d: "${d.sharedLib}/*") deps)}'';
|
||||
executable = lib.makeOverridable ({ withSharedStdlib ? true }: let
|
||||
objPaths = map (drv: "${drv}/${drv.oPath}") (attrValues objects) ++ lib.optional withSharedStdlib "${lean-final.leanshared}/*";
|
||||
in runCommand executableName { buildInputs = [ stdenv.cc leanc ]; } ''
|
||||
mkdir -p $out/bin
|
||||
leanc ${staticLibLinkWrapper (lib.concatStringsSep " " (objPaths ++ map (d: "${d}/*.a") allStaticLibDeps))} \
|
||||
-o $out/bin/${executableName} \
|
||||
${lib.concatStringsSep " " allLinkFlags}
|
||||
'') {};
|
||||
})
|
||||
@@ -1,42 +0,0 @@
|
||||
#!@bash@/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
function pebkac() {
|
||||
echo 'This is just a simple Nix adapter for `lake print-paths|serve`.'
|
||||
exit 1
|
||||
}
|
||||
|
||||
[[ $# -gt 0 ]] || pebkac
|
||||
case $1 in
|
||||
--version)
|
||||
# minimum version for `lake serve` with fallback
|
||||
echo 3.1.0
|
||||
;;
|
||||
print-paths)
|
||||
shift
|
||||
deps="$@"
|
||||
root=.
|
||||
# fall back to initial package if not in package
|
||||
[[ ! -f "$root/flake.nix" ]] && root="@srcRoot@"
|
||||
target="$root#print-paths"
|
||||
args=()
|
||||
# HACK: use stage 0 instead of 1 inside Lean's own `src/`
|
||||
[[ -d Lean && -f ../flake.nix ]] && target="@srcTarget@print-paths" && args=@srcArgs@
|
||||
for dep in $deps; do
|
||||
target="$target.\"$dep\""
|
||||
done
|
||||
echo "Building dependencies..." >&2
|
||||
# -v only has "built ...", but "-vv" is a bit too verbose
|
||||
exec @nix@/bin/nix run "$target" ${args[*]} -v
|
||||
;;
|
||||
serve)
|
||||
shift
|
||||
[[ ${1:-} == "--" ]] && shift
|
||||
# `link-ilean` puts them there
|
||||
LEAN_PATH=${LEAN_PATH:+$LEAN_PATH:}$PWD/build/lib exec $(dirname $0)/lean --server "$@"
|
||||
;;
|
||||
*)
|
||||
pebkac
|
||||
;;
|
||||
esac
|
||||
@@ -1,28 +0,0 @@
|
||||
#!@bash@/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
root="."
|
||||
# find package root
|
||||
while [[ "$root" != / ]]; do
|
||||
[ -f "$root/flake.nix" ] && break
|
||||
root="$(realpath "$root/..")"
|
||||
done
|
||||
# fall back to initial package if not in package
|
||||
[[ ! -f "$root/flake.nix" ]] && root="@srcRoot@"
|
||||
|
||||
# use Lean w/ package unless in server mode (which has its own LEAN_PATH logic)
|
||||
target="$root#lean-package"
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--server | --worker | -v | --version)
|
||||
target="$root#lean"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
args=(-- "$@")
|
||||
# HACK: use stage 0 instead of 1 inside Lean's own `src/`
|
||||
[[ -d Lean && -f ../flake.nix ]] && target="@srcTarget@" && args=@srcArgs@
|
||||
|
||||
LEAN_SYSROOT="$(dirname "$0")/.." exec @nix@/bin/nix ${LEAN_NIX_ARGS:-} run "$target" ${args[*]}
|
||||
@@ -1,52 +0,0 @@
|
||||
{ src, pkgs, ... } @ args:
|
||||
with pkgs;
|
||||
let
|
||||
# https://github.com/NixOS/nixpkgs/issues/130963
|
||||
llvmPackages = if stdenv.isDarwin then llvmPackages_11 else llvmPackages_15;
|
||||
cc = (ccacheWrapper.override rec {
|
||||
cc = llvmPackages.clang;
|
||||
extraConfig = ''
|
||||
export CCACHE_DIR=/nix/var/cache/ccache
|
||||
export CCACHE_UMASK=007
|
||||
export CCACHE_BASE_DIR=$NIX_BUILD_TOP
|
||||
# https://github.com/NixOS/nixpkgs/issues/109033
|
||||
args=("$@")
|
||||
for ((i=0; i<"''${#args[@]}"; i++)); do
|
||||
case ''${args[i]} in
|
||||
-frandom-seed=*) unset args[i]; break;;
|
||||
esac
|
||||
done
|
||||
set -- "''${args[@]}"
|
||||
[ -d $CCACHE_DIR ] || exec ${cc}/bin/$(basename "$0") "$@"
|
||||
'';
|
||||
}).overrideAttrs (old: {
|
||||
# https://github.com/NixOS/nixpkgs/issues/119779
|
||||
installPhase = builtins.replaceStrings ["use_response_file_by_default=1"] ["use_response_file_by_default=0"] old.installPhase;
|
||||
});
|
||||
stdenv' = if stdenv.isLinux then useGoldLinker stdenv else stdenv;
|
||||
lean = callPackage (import ./bootstrap.nix) (args // {
|
||||
stdenv = overrideCC stdenv' cc;
|
||||
inherit src buildLeanPackage llvmPackages;
|
||||
});
|
||||
makeOverridableLeanPackage = f:
|
||||
let newF = origArgs: f origArgs // {
|
||||
overrideArgs = newArgs: makeOverridableLeanPackage f (origArgs // newArgs);
|
||||
};
|
||||
in lib.setFunctionArgs newF (lib.getFunctionArgs f) // {
|
||||
override = args: makeOverridableLeanPackage (f.override args);
|
||||
};
|
||||
buildLeanPackage = makeOverridableLeanPackage (callPackage (import ./buildLeanPackage.nix) (args // {
|
||||
inherit (lean) stdenv;
|
||||
lean = lean.stage1;
|
||||
inherit (lean.stage1) leanc;
|
||||
}));
|
||||
in {
|
||||
inherit cc buildLeanPackage llvmPackages;
|
||||
nixpkgs = pkgs;
|
||||
ciShell = writeShellScriptBin "ciShell" ''
|
||||
set -o pipefail
|
||||
export PATH=${moreutils}/bin:$PATH
|
||||
# prefix lines with cumulative and individual execution time
|
||||
"$@" |& ts -i "(%.S)]" | ts -s "[%M:%S"
|
||||
'';
|
||||
} // lean.stage1
|
||||
@@ -1 +0,0 @@
|
||||
#eval "Hello, world!"
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
description = "My Lean package";
|
||||
|
||||
inputs.lean.url = "github:leanprover/lean4";
|
||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
outputs = { self, lean, flake-utils }: flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
leanPkgs = lean.packages.${system};
|
||||
pkg = leanPkgs.buildLeanPackage {
|
||||
name = "MyPackage"; # must match the name of the top-level .lean file
|
||||
src = ./.;
|
||||
};
|
||||
in {
|
||||
packages = pkg // {
|
||||
inherit (leanPkgs) lean;
|
||||
};
|
||||
|
||||
defaultPackage = pkg.modRoot;
|
||||
});
|
||||
}
|
||||
132
script/AnalyzeGrindAnnotations.lean
Normal file
132
script/AnalyzeGrindAnnotations.lean
Normal file
@@ -0,0 +1,132 @@
|
||||
/-
|
||||
Copyright (c) 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
import Lean
|
||||
|
||||
namespace Lean.Meta.Grind.Analyzer
|
||||
|
||||
|
||||
/-!
|
||||
A simple E-matching annotation analyzer.
|
||||
For each theorem annotated as an E-matching candidate, it creates an artificial goal, executes `grind` and shows the
|
||||
number of instances created.
|
||||
For a theorem of the form `params -> type`, the artificial goal is of the form `params -> type -> False`.
|
||||
-/
|
||||
|
||||
/--
|
||||
`grind` configuration for the analyzer. We disable case-splits and lookahead,
|
||||
increase the number of generations, and limit the number of instances generated.
|
||||
-/
|
||||
def config : Grind.Config := {
|
||||
splits := 0
|
||||
lookahead := false
|
||||
mbtc := false
|
||||
ematch := 20
|
||||
instances := 100
|
||||
gen := 10
|
||||
}
|
||||
|
||||
structure Config where
|
||||
/-- Minimum number of instantiations to trigger summary report -/
|
||||
min : Nat := 10
|
||||
/-- Minimum number of instantiations to trigger detailed report -/
|
||||
detailed : Nat := 50
|
||||
|
||||
def mkParams : MetaM Params := do
|
||||
let params ← Grind.mkParams config
|
||||
let ematch ← getEMatchTheorems
|
||||
let casesTypes ← Grind.getCasesTypes
|
||||
return { params with ematch, casesTypes }
|
||||
|
||||
/-- Returns the total number of generated instances. -/
|
||||
private def sum (cs : PHashMap Origin Nat) : Nat := Id.run do
|
||||
let mut r := 0
|
||||
for (_, c) in cs do
|
||||
r := r + c
|
||||
return r
|
||||
|
||||
private def thmsToMessageData (thms : PHashMap Origin Nat) : MetaM MessageData := do
|
||||
let data := thms.toArray.filterMap fun (origin, c) =>
|
||||
match origin with
|
||||
| .decl declName => some (declName, c)
|
||||
| _ => none
|
||||
let data := data.qsort fun (d₁, c₁) (d₂, c₂) => if c₁ == c₂ then Name.lt d₁ d₂ else c₁ > c₂
|
||||
let data ← data.mapM fun (declName, counter) =>
|
||||
return .trace { cls := `thm } m!"{.ofConst (← mkConstWithLevelParams declName)} ↦ {counter}" #[]
|
||||
return .trace { cls := `thm } "instances" data
|
||||
|
||||
/--
|
||||
Analyzes theorem `declName`. That is, creates the artificial goal based on `declName` type,
|
||||
and invokes `grind` on it.
|
||||
-/
|
||||
def analyzeEMatchTheorem (declName : Name) (c : Config) : MetaM Unit := do
|
||||
let info ← getConstInfo declName
|
||||
let mvarId ← forallTelescope info.type fun _ type => do
|
||||
withLocalDeclD `h type fun _ => do
|
||||
return (← mkFreshExprMVar (mkConst ``False)).mvarId!
|
||||
let result ← Grind.main mvarId (← mkParams) (pure ())
|
||||
let thms := result.counters.thm
|
||||
let s := sum thms
|
||||
if s > c.min then
|
||||
IO.println s!"{declName} : {s}"
|
||||
if s > c.detailed then
|
||||
logInfo m!"{declName}\n{← thmsToMessageData thms}"
|
||||
|
||||
-- Not sure why this is failing: `down_pure` perhaps has an unnecessary universe parameter?
|
||||
run_meta analyzeEMatchTheorem ``Std.Do.SPred.down_pure {}
|
||||
|
||||
/-- Analyzes all theorems in the standard library marked as E-matching theorems. -/
|
||||
def analyzeEMatchTheorems (c : Config := {}) : MetaM Unit := do
|
||||
let origins := (← getEMatchTheorems).getOrigins
|
||||
let decls := origins.filterMap fun | .decl declName => some declName | _ => none
|
||||
for declName in decls.mergeSort Name.lt do
|
||||
try
|
||||
analyzeEMatchTheorem declName c
|
||||
catch e =>
|
||||
logError m!"{declName} failed with {e.toMessageData}"
|
||||
logInfo m!"Finished analyzing {decls.length} theorems"
|
||||
|
||||
/-- Macro for analyzing E-match theorems with unlimited heartbeats -/
|
||||
macro "#analyzeEMatchTheorems" : command => `(
|
||||
set_option maxHeartbeats 0 in
|
||||
run_meta analyzeEMatchTheorems
|
||||
)
|
||||
|
||||
#analyzeEMatchTheorems
|
||||
|
||||
-- -- We can analyze specific theorems using commands such as
|
||||
set_option trace.grind.ematch.instance true
|
||||
|
||||
-- 1. grind immediately sees `(#[] : Array α) = ([] : List α).toArray` but probably this should be hidden.
|
||||
-- 2. `Vector.toArray_empty` keys on `Array.mk []` rather than `#v[].toArray`
|
||||
-- I guess we could add `(#[].extract _ _).extract _ _` as a stop pattern.
|
||||
run_meta analyzeEMatchTheorem ``Array.extract_empty {}
|
||||
|
||||
-- Neither `Option.bind_some` nor `Option.bind_fun_some` fire, because the terms appear inside
|
||||
-- lambdas. So we get crazy things like:
|
||||
-- `fun x => ((some x).bind some).bind fun x => (some x).bind fun x => (some x).bind some`
|
||||
-- We could consider replacing `filterMap_some` with
|
||||
-- `filterMap g (filterMap f xs) = filterMap (f >=> g) xs`
|
||||
-- to avoid the lambda that `grind` struggles with, but this would require more API around the fish.
|
||||
run_meta analyzeEMatchTheorem ``Array.filterMap_some {}
|
||||
|
||||
-- Not entirely certain what is wrong here, but certainly
|
||||
-- `eq_empty_of_append_eq_empty` is firing too often.
|
||||
-- Ideally we could instantiate this is we fine `xs ++ ys` in the same equivalence class,
|
||||
-- note just as soon as we see `xs ++ ys`.
|
||||
-- I've tried removing this in https://github.com/leanprover/lean4/pull/10162
|
||||
run_meta analyzeEMatchTheorem ``Array.range'_succ {}
|
||||
|
||||
-- Perhaps the same story here.
|
||||
run_meta analyzeEMatchTheorem ``Array.range_succ {}
|
||||
|
||||
-- `zip_map_left` and `zip_map_right` are bad grind lemmas,
|
||||
-- checking if they can be removed in https://github.com/leanprover/lean4/pull/10163
|
||||
run_meta analyzeEMatchTheorem ``Array.zip_map {}
|
||||
|
||||
-- It seems crazy to me that as soon as we have `0 >>> n = 0`, we instantiate based on the
|
||||
-- pattern `0 >>> n >>> m` by substituting `0` into `0 >>> n` to produce the `0 >>> n >>> n`.
|
||||
-- I don't think any forbidden subterms can help us here. I don't know what to do. :-(
|
||||
run_meta analyzeEMatchTheorem ``Int.zero_shiftRight {}
|
||||
@@ -1,9 +1,96 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
set -euxo pipefail
|
||||
|
||||
# We benchmark against stage 2 to test new optimizations.
|
||||
timeout -s KILL 1h time bash -c 'mkdir -p build/release; cd build/release; cmake ../.. && make -j$(nproc) stage2' 1>&2
|
||||
cmake --preset release 1>&2
|
||||
|
||||
# We benchmark against stage2/bin to test new optimizations.
|
||||
timeout -s KILL 1h time make -C build/release -j$(nproc) stage3 1>&2
|
||||
export PATH=$PWD/build/release/stage2/bin:$PATH
|
||||
|
||||
# The extra opts used to be passed to the Makefile during benchmarking only but with Lake it is
|
||||
# easier to configure them statically.
|
||||
cmake -B build/release/stage3 -S src -DLEAN_EXTRA_LAKEFILE_TOML='weakLeanArgs=["-Dprofiler=true", "-Dprofiler.threshold=9999999", "--stats"]' 1>&2
|
||||
|
||||
(
|
||||
cd tests/bench
|
||||
timeout -s KILL 1h time temci exec --config speedcenter.yaml --in speedcenter.exec.velcom.yaml 1>&2
|
||||
temci report run_output.yaml --reporter codespeed2
|
||||
)
|
||||
|
||||
if [ -d .git ]; then
|
||||
DIR="$(git rev-parse @)"
|
||||
BASE_URL="https://speed.lean-lang.org/lean4-out/$DIR"
|
||||
{
|
||||
cat <<'EOF'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Lakeprof Report</title>
|
||||
</head>
|
||||
<h1>Lakeprof Report</h1>
|
||||
<button type="button" id="btn_fetch">View build trace in Perfetto</button>
|
||||
<script type="text/javascript">
|
||||
const ORIGIN = 'https://ui.perfetto.dev';
|
||||
|
||||
const btnFetch = document.getElementById('btn_fetch');
|
||||
|
||||
async function fetchAndOpen(traceUrl) {
|
||||
const resp = await fetch(traceUrl);
|
||||
// Error checking is left as an exercise to the reader.
|
||||
const blob = await resp.blob();
|
||||
const arrayBuffer = await blob.arrayBuffer();
|
||||
openTrace(arrayBuffer, traceUrl);
|
||||
}
|
||||
|
||||
function openTrace(arrayBuffer, traceUrl) {
|
||||
const win = window.open(ORIGIN);
|
||||
if (!win) {
|
||||
btnFetch.style.background = '#f3ca63';
|
||||
btnFetch.onclick = () => openTrace(arrayBuffer);
|
||||
btnFetch.innerText = 'Popups blocked, click here to open the trace file';
|
||||
return;
|
||||
}
|
||||
|
||||
const timer = setInterval(() => win.postMessage('PING', ORIGIN), 50);
|
||||
|
||||
const onMessageHandler = (evt) => {
|
||||
if (evt.data !== 'PONG') return;
|
||||
|
||||
// We got a PONG, the UI is ready.
|
||||
window.clearInterval(timer);
|
||||
window.removeEventListener('message', onMessageHandler);
|
||||
|
||||
const reopenUrl = new URL(location.href);
|
||||
reopenUrl.hash = `#reopen=${traceUrl}`;
|
||||
win.postMessage({
|
||||
perfetto: {
|
||||
buffer: arrayBuffer,
|
||||
title: 'Lake Build Trace',
|
||||
url: reopenUrl.toString(),
|
||||
}}, ORIGIN);
|
||||
};
|
||||
|
||||
window.addEventListener('message', onMessageHandler);
|
||||
}
|
||||
|
||||
// This is triggered when following the link from the Perfetto UI's sidebar.
|
||||
if (location.hash.startsWith('#reopen=')) {
|
||||
const traceUrl = location.hash.substr(8);
|
||||
fetchAndOpen(traceUrl);
|
||||
}
|
||||
EOF
|
||||
cat <<EOF
|
||||
btnFetch.onclick = () => fetchAndOpen("$BASE_URL/lakeprof.trace_event");
|
||||
</script>
|
||||
EOF
|
||||
echo "<pre><code>"
|
||||
(cd src; lakeprof report -prc)
|
||||
echo "</code></pre>"
|
||||
echo "</body></html>"
|
||||
} | tee index.html
|
||||
|
||||
curl -T index.html $BASE_URL/index.html
|
||||
curl -T src/lakeprof.log $BASE_URL/lakeprof.log
|
||||
curl -T src/lakeprof.trace_event $BASE_URL/lakeprof.trace_event
|
||||
fi
|
||||
|
||||
@@ -28,13 +28,6 @@ repositories:
|
||||
branch: main
|
||||
dependencies: []
|
||||
|
||||
- name: doc-gen4
|
||||
url: https://github.com/leanprover/doc-gen4
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: [lean4-cli]
|
||||
|
||||
- name: verso
|
||||
url: https://github.com/leanprover/verso
|
||||
toolchain-tag: true
|
||||
@@ -42,6 +35,28 @@ repositories:
|
||||
branch: main
|
||||
dependencies: []
|
||||
|
||||
- name: plausible
|
||||
url: https://github.com/leanprover-community/plausible
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: []
|
||||
|
||||
- name: import-graph
|
||||
url: https://github.com/leanprover-community/import-graph
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies:
|
||||
- lean4-cli
|
||||
|
||||
- name: doc-gen4
|
||||
url: https://github.com/leanprover/doc-gen4
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: [lean4-cli]
|
||||
|
||||
- name: reference-manual
|
||||
url: https://github.com/leanprover/reference-manual
|
||||
toolchain-tag: true
|
||||
@@ -65,22 +80,6 @@ repositories:
|
||||
dependencies:
|
||||
- batteries
|
||||
|
||||
- name: import-graph
|
||||
url: https://github.com/leanprover-community/import-graph
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies:
|
||||
- lean4-cli
|
||||
- batteries
|
||||
|
||||
- name: plausible
|
||||
url: https://github.com/leanprover-community/plausible
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: []
|
||||
|
||||
- name: mathlib4
|
||||
url: https://github.com/leanprover-community/mathlib4
|
||||
toolchain-tag: true
|
||||
|
||||
@@ -195,7 +195,7 @@ def execute_release_steps(repo, version, config):
|
||||
run_command(f"git checkout {default_branch} && git pull", cwd=repo_path)
|
||||
|
||||
# Special rc1 safety check for batteries and mathlib4 (before creating any branches)
|
||||
if re.search(r'rc\d+$', version) and repo_name in ["batteries", "mathlib4"] and version.endswith('-rc1'):
|
||||
if repo_name in ["batteries", "mathlib4"] and version.endswith('-rc1'):
|
||||
print(blue("This repo has nightly-testing infrastructure"))
|
||||
print(blue(f"Checking if nightly-testing can be safely merged into bump/{version.split('-rc')[0]}..."))
|
||||
|
||||
@@ -403,7 +403,7 @@ def execute_release_steps(repo, version, config):
|
||||
raise
|
||||
|
||||
# Handle special merging cases
|
||||
if re.search(r'rc\d+$', version) and repo_name in ["batteries", "mathlib4"]:
|
||||
if version.endswith('-rc1') and repo_name in ["batteries", "mathlib4"]:
|
||||
print(blue("This repo uses `bump/v4.X.0` branches for reviewed content from nightly-testing."))
|
||||
|
||||
# Determine which remote to use for bump branches
|
||||
@@ -474,7 +474,7 @@ def execute_release_steps(repo, version, config):
|
||||
|
||||
print(green("✅ Merge completed successfully with automatic conflict resolution"))
|
||||
|
||||
elif re.search(r'rc\d+$', version):
|
||||
elif version.endswith('-rc1'):
|
||||
# For all other repos with rc versions, merge nightly-testing
|
||||
if repo_name in ["verso", "reference-manual"]:
|
||||
print(yellow("This repo does development on nightly-testing: remember to rebase merge the PR."))
|
||||
|
||||
@@ -10,7 +10,7 @@ endif()
|
||||
include(ExternalProject)
|
||||
project(LEAN CXX C)
|
||||
set(LEAN_VERSION_MAJOR 4)
|
||||
set(LEAN_VERSION_MINOR 23)
|
||||
set(LEAN_VERSION_MINOR 24)
|
||||
set(LEAN_VERSION_PATCH 0)
|
||||
set(LEAN_VERSION_IS_RELEASE 0) # This number is 1 in the release revision, and 0 otherwise.
|
||||
set(LEAN_SPECIAL_VERSION_DESC "" CACHE STRING "Additional version description like 'nightly-2018-03-11'")
|
||||
@@ -81,7 +81,7 @@ option(USE_MIMALLOC "use mimalloc" ON)
|
||||
|
||||
# development-specific options
|
||||
option(CHECK_OLEAN_VERSION "Only load .olean files compiled with the current version of Lean" OFF)
|
||||
option(USE_LAKE "Use Lake instead of lean.mk for building core libs from language server" OFF)
|
||||
option(USE_LAKE "Use Lake instead of lean.mk for building core libs from language server" ON)
|
||||
|
||||
set(LEAN_EXTRA_MAKE_OPTS "" CACHE STRING "extra options to lean --make")
|
||||
set(LEANC_CC ${CMAKE_C_COMPILER} CACHE STRING "C compiler to use in `leanc`")
|
||||
@@ -469,6 +469,7 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
string(APPEND CMAKE_CXX_FLAGS " -ftls-model=initial-exec")
|
||||
string(APPEND INIT_SHARED_LINKER_FLAGS " -install_name @rpath/libInit_shared.dylib")
|
||||
string(APPEND LEANSHARED_1_LINKER_FLAGS " -install_name @rpath/libleanshared_1.dylib")
|
||||
string(APPEND LEANSHARED_2_LINKER_FLAGS " -install_name @rpath/libleanshared_2.dylib")
|
||||
string(APPEND LEANSHARED_LINKER_FLAGS " -install_name @rpath/libleanshared.dylib")
|
||||
string(APPEND LAKESHARED_LINKER_FLAGS " -Wl,-force_load,${CMAKE_BINARY_DIR}/lib/lean/libLake.a.export -install_name @rpath/libLake_shared.dylib")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-rpath,@executable_path/../lib -Wl,-rpath,@executable_path/../lib/lean")
|
||||
@@ -502,7 +503,7 @@ endif()
|
||||
# are already loaded) and probably fail unless we set up LD_LIBRARY_PATH.
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
# import libraries created by the stdlib.make targets
|
||||
string(APPEND LEANC_SHARED_LINKER_FLAGS " -lInit_shared -lleanshared_1 -lleanshared")
|
||||
string(APPEND LEANC_SHARED_LINKER_FLAGS " -lInit_shared -lleanshared_2 -lleanshared_1 -lleanshared")
|
||||
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
|
||||
# The second flag is necessary to even *load* dylibs without resolved symbols, as can happen
|
||||
# if a Lake `extern_lib` depends on a symbols defined by the Lean library but is loaded even
|
||||
@@ -533,12 +534,21 @@ else()
|
||||
OUTPUT_VARIABLE GIT_SHA1
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
message(STATUS "stage0 sha1: ${GIT_SHA1}")
|
||||
# Now that we've prepared the information for the next stage, we can forget that we will use
|
||||
# Lake in the future as we won't use it in this stage
|
||||
set(USE_LAKE OFF)
|
||||
else()
|
||||
set(GIT_SHA1 "")
|
||||
endif()
|
||||
endif()
|
||||
configure_file("${LEAN_SOURCE_DIR}/githash.h.in" "${LEAN_BINARY_DIR}/githash.h")
|
||||
|
||||
if(USE_LAKE AND ${STAGE} EQUAL 0)
|
||||
# Now that we've prepared the information for the next stage, we can forget that we will use
|
||||
# Lake in the future as we won't use it in this stage
|
||||
set(USE_LAKE OFF)
|
||||
endif()
|
||||
|
||||
# Windows uses ";" as a path separator. We use `LEAN_PATH_SEPARATOR` on scripts such as lean.mk.in
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(LEAN_PATH_SEPARATOR ";")
|
||||
@@ -580,7 +590,7 @@ endif()
|
||||
|
||||
add_subdirectory(initialize)
|
||||
add_subdirectory(shell)
|
||||
# to be included in `leanshared` but not the smaller `leanshared_1` (as it would pull
|
||||
# to be included in `leanshared` but not the smaller `leanshared_*` (as it would pull
|
||||
# in the world)
|
||||
add_library(leaninitialize STATIC $<TARGET_OBJECTS:initialize>)
|
||||
set_target_properties(leaninitialize PROPERTIES
|
||||
@@ -675,12 +685,17 @@ if (LLVM AND ${STAGE} GREATER 0)
|
||||
set(EXTRA_LEANMAKE_OPTS "LLVM=1")
|
||||
endif()
|
||||
|
||||
set(STDLIBS Init Std Lean Leanc)
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
list(APPEND STDLIBS Lake)
|
||||
endif()
|
||||
|
||||
add_custom_target(make_stdlib ALL
|
||||
WORKING_DIRECTORY ${LEAN_SOURCE_DIR}
|
||||
# The actual rule is in a separate makefile because we want to prefix it with '+' to use the Make job server
|
||||
# for a parallelized nested build, but CMake doesn't let us do that.
|
||||
# We use `lean` from the previous stage, but `leanc`, headers, etc. from the current stage
|
||||
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make Init Std Lean Leanc
|
||||
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make ${STDLIBS}
|
||||
VERBATIM)
|
||||
|
||||
# if we have LLVM enabled, then build `lean.h.bc` which has the LLVM bitcode
|
||||
@@ -700,6 +715,7 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
)
|
||||
add_custom_target(leanshared ALL
|
||||
DEPENDS Init_shared leancpp
|
||||
COMMAND touch ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libleanshared_2${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
COMMAND touch ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libleanshared_1${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
COMMAND touch ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libleanshared${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
)
|
||||
@@ -720,18 +736,13 @@ else()
|
||||
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make leanshared
|
||||
VERBATIM)
|
||||
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS " -lInit_shared -lleanshared_1 -lleanshared")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS " -lInit_shared -lleanshared_2 -lleanshared_1 -lleanshared")
|
||||
endif()
|
||||
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
add_custom_target(lake_lib
|
||||
WORKING_DIRECTORY ${LEAN_SOURCE_DIR}
|
||||
DEPENDS leanshared
|
||||
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make Lake
|
||||
VERBATIM)
|
||||
add_custom_target(lake_shared
|
||||
WORKING_DIRECTORY ${LEAN_SOURCE_DIR}
|
||||
DEPENDS lake_lib
|
||||
DEPENDS leanshared
|
||||
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make libLake_shared
|
||||
VERBATIM)
|
||||
add_custom_target(lake ALL
|
||||
@@ -812,6 +823,12 @@ if(LEAN_INSTALL_PREFIX)
|
||||
set(CMAKE_INSTALL_PREFIX "${LEAN_INSTALL_PREFIX}/lean-${LEAN_VERSION_STRING}${LEAN_INSTALL_SUFFIX}")
|
||||
endif()
|
||||
|
||||
if (STAGE GREATER 1)
|
||||
# The build of stage2+ may depend on local changes made to src/ that are not reflected by the
|
||||
# commit hash in stage1/bin/lean, so we make sure to disable the global cache
|
||||
string(APPEND LEAN_EXTRA_LAKEFILE_TOML "\n\nenableArtifactCache = false")
|
||||
endif()
|
||||
|
||||
# Escape for `make`. Yes, twice.
|
||||
string(REPLACE "$" "\\\$$" CMAKE_EXE_LINKER_FLAGS_MAKE "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
configure_file(${LEAN_SOURCE_DIR}/stdlib.make.in ${CMAKE_BINARY_DIR}/stdlib.make)
|
||||
@@ -838,6 +855,10 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(LAKE_LIB_PREFIX "lib")
|
||||
endif()
|
||||
|
||||
if(USE_LAKE AND STAGE EQUAL 1)
|
||||
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/lakefile.toml)
|
||||
if(USE_LAKE)
|
||||
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${CMAKE_BINARY_DIR}/lakefile.toml)
|
||||
# copy for editing
|
||||
if(STAGE EQUAL 1)
|
||||
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/lakefile.toml)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -39,7 +39,7 @@ This gadget is supported by
|
||||
* `simp`, `dsimp` and `rw` in the right-hand-side of an equation
|
||||
* `simp` in the assumptions of congruence rules
|
||||
|
||||
It is ineffective in other positions (hyptheses of rewrite rules) or when used by other tactics
|
||||
It is ineffective in other positions (hypotheses of rewrite rules) or when used by other tactics
|
||||
(e.g. `apply`).
|
||||
-/
|
||||
@[simp ↓, expose]
|
||||
|
||||
@@ -9,7 +9,7 @@ prelude
|
||||
public import Init.Core
|
||||
public import Init.BinderNameHint
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
universe u v w
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ public import Init.Control.Basic
|
||||
public import Init.Control.Id
|
||||
public import Init.Coe
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
namespace Except
|
||||
variable {ε : Type u}
|
||||
|
||||
@@ -7,8 +7,10 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Control.Lawful.Basic
|
||||
public import all Init.Control.Except
|
||||
public import all Init.Control.State
|
||||
public import Init.Control.Except
|
||||
import all Init.Control.Except
|
||||
public import Init.Control.State
|
||||
import all Init.Control.State
|
||||
public import Init.Control.StateRef
|
||||
public import Init.Ext
|
||||
|
||||
|
||||
@@ -6,12 +6,18 @@ Authors: Quang Dao, Paul Reichert
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Control.Option
|
||||
public import all Init.Control.Except
|
||||
public import all Init.Control.ExceptCps
|
||||
public import all Init.Control.StateRef
|
||||
public import all Init.Control.StateCps
|
||||
public import all Init.Control.Id
|
||||
public import Init.Control.Option
|
||||
import all Init.Control.Option
|
||||
public import Init.Control.Except
|
||||
import all Init.Control.Except
|
||||
public import Init.Control.ExceptCps
|
||||
import all Init.Control.ExceptCps
|
||||
public import Init.Control.StateRef
|
||||
import all Init.Control.StateRef
|
||||
public import Init.Control.StateCps
|
||||
import all Init.Control.StateCps
|
||||
public import Init.Control.Id
|
||||
import all Init.Control.Id
|
||||
public import Init.Control.Lawful.MonadLift.Lemmas
|
||||
public import Init.Control.Lawful.Instances
|
||||
|
||||
|
||||
@@ -52,4 +52,4 @@ instance ReaderT.tryFinally [MonadFinally m] : MonadFinally (ReaderT ρ m) where
|
||||
A monad with access to a read-only value of type `ρ`. The value can be locally overridden by
|
||||
`withReader`, but it cannot be mutated.
|
||||
-/
|
||||
@[reducible] def ReaderM (ρ : Type u) := ReaderT ρ Id
|
||||
abbrev ReaderM (ρ : Type u) := ReaderT ρ Id
|
||||
|
||||
@@ -187,6 +187,9 @@ match [a, b] with
|
||||
simplifies to `a`. -/
|
||||
syntax (name := simpMatch) "simp_match" : conv
|
||||
|
||||
/-- Removes one or more hypotheses from the local context. -/
|
||||
syntax (name := clear) "clear" (ppSpace colGt term:max)+ : conv
|
||||
|
||||
/-- Executes the given tactic block without converting `conv` goal into a regular goal. -/
|
||||
syntax (name := nestedTacticCore) "tactic'" " => " tacticSeq : conv
|
||||
|
||||
@@ -262,7 +265,7 @@ resulting in `t'`, which becomes the new target subgoal. -/
|
||||
syntax (name := convConvSeq) "conv" " => " convSeq : conv
|
||||
|
||||
/-- `· conv` focuses on the main conv goal and tries to solve it using `s`. -/
|
||||
macro dot:patternIgnore("·" <|> ".") s:convSeq : conv => `(conv| {%$dot ($s) })
|
||||
macro dot:patternIgnore("· " <|> ". ") s:convSeq : conv => `(conv| {%$dot ($s) })
|
||||
|
||||
|
||||
/-- `fail_if_success t` fails if the tactic `t` succeeds. -/
|
||||
@@ -287,13 +290,17 @@ macro "right" : conv => `(conv| rhs)
|
||||
/-- `intro` traverses into binders. Synonym for `ext`. -/
|
||||
macro "intro" xs:(ppSpace colGt binderIdent)* : conv => `(conv| ext $xs*)
|
||||
|
||||
syntax enterArg := binderIdent <|> argArg
|
||||
syntax enterPattern := "in " (occs)? term
|
||||
|
||||
syntax enterArg := binderIdent <|> argArg <|> enterPattern
|
||||
|
||||
/-- `enter [arg, ...]` is a compact way to describe a path to a subterm.
|
||||
It is a shorthand for other conv tactics as follows:
|
||||
* `enter [i]` is equivalent to `arg i`.
|
||||
* `enter [@i]` is equivalent to `arg @i`.
|
||||
* `enter [x]` (where `x` is an identifier) is equivalent to `ext x`.
|
||||
* `enter [in e]` (where `e` is a term) is equivalent to `pattern e`.
|
||||
Occurrences can be specified with `enter [in (occs := ...) e]`.
|
||||
For example, given the target `f (g a (fun x => x b))`, `enter [1, 2, x, 1]`
|
||||
will traverse to the subterm `b`. -/
|
||||
syntax (name := enter) "enter" " [" withoutPosition(enterArg,+) "]" : conv
|
||||
@@ -342,7 +349,7 @@ This is the conv mode version of the `lift_lets` tactic.
|
||||
syntax (name := liftLets) "lift_lets " optConfig : conv
|
||||
|
||||
/--
|
||||
Transforms `let` expressions into `have` expressions within th etarget expression when possible.
|
||||
Transforms `let` expressions into `have` expressions within the target expression when possible.
|
||||
This is the conv mode version of the `let_to_have` tactic.
|
||||
-/
|
||||
syntax (name := letToHave) "let_to_have" : conv
|
||||
|
||||
@@ -29,6 +29,29 @@ theorem id_def {α : Sort u} (a : α) : id a = a := rfl
|
||||
|
||||
attribute [grind] id
|
||||
|
||||
/--
|
||||
A helper gadget for instructing the kernel to eagerly reduce terms.
|
||||
|
||||
When the gadget wraps the argument of an application, then when checking that
|
||||
the expected and inferred type of the argument match, the kernel will evaluate terms more eagerly.
|
||||
It is often used to wrap `Eq.refl true` proof terms as `eagerReduce (Eq.refl true)`
|
||||
when using proof by reflection.
|
||||
As an example, consider the theorem:
|
||||
```
|
||||
theorem eq_norm (ctx : Context) (p₁ p₂ : Poly) (h : (p₁.norm == p₂) = true) :
|
||||
p₁.denote ctx = 0 → p₂.denote ctx = 0
|
||||
```
|
||||
The argument `h : (p₁.norm == p₂) = true` is a candidate for `eagerReduce`.
|
||||
When applying this theorem, we would write:
|
||||
|
||||
```
|
||||
eq_norm ctx p q (eagerReduce (Eq.refl true)) h
|
||||
```
|
||||
to instruct the kernel to use eager reduction when establishing that `(p.norm == q) = true` is
|
||||
definitionally equal to `true = true`.
|
||||
-/
|
||||
@[expose] def eagerReduce {α : Sort u} (a : α) : α := a
|
||||
|
||||
/--
|
||||
`flip f a b` is `f b a`. It is useful for "point-free" programming,
|
||||
since it can sometimes be used to avoid introducing variables.
|
||||
@@ -78,6 +101,7 @@ instance : DecidableEq Empty := fun a => a.elim
|
||||
/-- Decidable equality for PEmpty -/
|
||||
instance : DecidableEq PEmpty := fun a => a.elim
|
||||
|
||||
set_option genInjectivity false in
|
||||
/--
|
||||
Delays evaluation. The delayed code is evaluated at most once.
|
||||
|
||||
@@ -593,6 +617,7 @@ class Sep (α : outParam <| Type u) (γ : Type v) where
|
||||
/-- Computes `{ a ∈ c | p a }`. -/
|
||||
sep : (α → Prop) → γ → γ
|
||||
|
||||
set_option genInjectivity false in
|
||||
/--
|
||||
`Task α` is a primitive for asynchronous computation.
|
||||
It represents a computation that will resolve to a value of type `α`,
|
||||
@@ -752,6 +777,8 @@ Unlike `x ≠ y` (which is notation for `Ne x y`), this is `Bool` valued instead
|
||||
|
||||
@[inherit_doc] infix:50 " != " => bne
|
||||
|
||||
macro_rules | `($x != $y) => `(binrel_no_prop% bne $x $y)
|
||||
|
||||
recommended_spelling "bne" for "!=" in [bne, «term_!=_»]
|
||||
|
||||
/-- `ReflBEq α` says that the `BEq` implementation is reflexive. -/
|
||||
@@ -853,6 +880,8 @@ and asserts that `a` and `b` are not equal.
|
||||
|
||||
@[inherit_doc] infix:50 " ≠ " => Ne
|
||||
|
||||
macro_rules | `($x ≠ $y) => `(binrel% Ne $x $y)
|
||||
|
||||
recommended_spelling "ne" for "≠" in [Ne, «term_≠_»]
|
||||
|
||||
section Ne
|
||||
@@ -1532,38 +1561,13 @@ end Setoid
|
||||
/-! # Propositional extensionality -/
|
||||
|
||||
/--
|
||||
The axiom of **propositional extensionality**. It asserts that if propositions
|
||||
`a` and `b` are logically equivalent (i.e. we can prove `a` from `b` and vice versa),
|
||||
then `a` and `b` are *equal*, meaning that we can replace `a` with `b` in all
|
||||
contexts.
|
||||
The [axiom](lean-manual://section/axioms) of **propositional extensionality**. It asserts that if
|
||||
propositions `a` and `b` are logically equivalent (that is, if `a` can be proved from `b` and vice
|
||||
versa), then `a` and `b` are *equal*, meaning `a` can be replaced with `b` in all contexts.
|
||||
|
||||
For simple expressions like `a ∧ c ∨ d → e` we can prove that because all the logical
|
||||
connectives respect logical equivalence, we can replace `a` with `b` in this expression
|
||||
without using `propext`. However, for higher order expressions like `P a` where
|
||||
`P : Prop → Prop` is unknown, or indeed for `a = b` itself, we cannot replace `a` with `b`
|
||||
without an axiom which says exactly this.
|
||||
|
||||
This is a relatively uncontroversial axiom, which is intuitionistically valid.
|
||||
It does however block computation when using `#reduce` to reduce proofs directly
|
||||
(which is not recommended), meaning that canonicity,
|
||||
the property that all closed terms of type `Nat` normalize to numerals,
|
||||
fails to hold when this (or any) axiom is used:
|
||||
```
|
||||
set_option pp.proofs true
|
||||
|
||||
def foo : Nat := by
|
||||
have : (True → True) ↔ True := ⟨λ _ => trivial, λ _ _ => trivial⟩
|
||||
have := propext this ▸ (2 : Nat)
|
||||
exact this
|
||||
|
||||
#reduce foo
|
||||
-- propext { mp := fun x x => True.intro, mpr := fun x => True.intro } ▸ 2
|
||||
|
||||
#eval foo -- 2
|
||||
```
|
||||
`#eval` can evaluate it to a numeral because the compiler erases casts and
|
||||
does not evaluate proofs, so `propext`, whose return type is a proposition,
|
||||
can never block it.
|
||||
The standard logical connectives provably respect propositional extensionality. However, an axiom is
|
||||
needed for higher order expressions like `P a` where `P : Prop → Prop` is unknown, as well as for
|
||||
equality. Propositional extensionality is intuitionistically valid.
|
||||
-/
|
||||
axiom propext {a b : Prop} : (a ↔ b) → a = b
|
||||
|
||||
@@ -1594,6 +1598,7 @@ gen_injective_theorems% MProd
|
||||
gen_injective_theorems% NonScalar
|
||||
gen_injective_theorems% Option
|
||||
gen_injective_theorems% PLift
|
||||
gen_injective_theorems% PULift
|
||||
gen_injective_theorems% PNonScalar
|
||||
gen_injective_theorems% PProd
|
||||
gen_injective_theorems% Prod
|
||||
@@ -2519,12 +2524,17 @@ class Antisymm (r : α → α → Prop) : Prop where
|
||||
/-- An antisymmetric relation `r` satisfies `r a b → r b a → a = b`. -/
|
||||
antisymm (a b : α) : r a b → r b a → a = b
|
||||
|
||||
/-- `Asymm X r` means that the binary relation `r` on `X` is asymmetric, that is,
|
||||
/-- `Asymm r` means that the binary relation `r` is asymmetric, that is,
|
||||
`r a b → ¬ r b a`. -/
|
||||
class Asymm (r : α → α → Prop) : Prop where
|
||||
/-- An asymmetric relation satisfies `r a b → ¬ r b a`. -/
|
||||
asymm : ∀ a b, r a b → ¬r b a
|
||||
|
||||
/-- `Symm r` means that the binary relation `r` is symmetric, that is, `r a b → r b a`. -/
|
||||
class Symm (r : α → α → Prop) : Prop where
|
||||
/-- A symmetric relation satisfies `r a b → r b a`. -/
|
||||
symm : ∀ a b, r a b → r b a
|
||||
|
||||
/-- `Total X r` means that the binary relation `r` on `X` is total, that is, that for any
|
||||
`x y : X` we have `r x y` or `r y x`. -/
|
||||
class Total (r : α → α → Prop) : Prop where
|
||||
@@ -2538,3 +2548,7 @@ class Irrefl (r : α → α → Prop) : Prop where
|
||||
irrefl : ∀ a, ¬r a a
|
||||
|
||||
end Std
|
||||
|
||||
/-- Deprecated alias for `XorOp`. -/
|
||||
@[deprecated XorOp (since := "2025-07-30")]
|
||||
abbrev Xor := XorOp
|
||||
|
||||
@@ -49,5 +49,8 @@ public import Init.Data.Vector
|
||||
public import Init.Data.Iterators
|
||||
public import Init.Data.Range.Polymorphic
|
||||
public import Init.Data.Slice
|
||||
public import Init.Data.Order
|
||||
public import Init.Data.Rat
|
||||
public import Init.Data.Dyadic
|
||||
|
||||
public section
|
||||
|
||||
@@ -10,7 +10,7 @@ prelude
|
||||
public import Init.Classical
|
||||
public import Init.ByCases
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
namespace Lean.Data.AC
|
||||
inductive Expr
|
||||
|
||||
@@ -9,7 +9,8 @@ prelude
|
||||
public import Init.Data.Array.Mem
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.Count
|
||||
public import all Init.Data.List.Attach
|
||||
public import Init.Data.List.Attach
|
||||
import all Init.Data.List.Attach
|
||||
|
||||
public section
|
||||
|
||||
|
||||
@@ -13,8 +13,10 @@ public import Init.Data.UInt.BasicAux
|
||||
public import Init.Data.Repr
|
||||
public import Init.Data.ToString.Basic
|
||||
public import Init.GetElem
|
||||
public import all Init.Data.List.ToArrayImpl
|
||||
public import all Init.Data.Array.Set
|
||||
public import Init.Data.List.ToArrayImpl
|
||||
import all Init.Data.List.ToArrayImpl
|
||||
public import Init.Data.Array.Set
|
||||
import all Init.Data.Array.Set
|
||||
|
||||
public section
|
||||
|
||||
@@ -163,7 +165,7 @@ representation of arrays. While this is not provable, `Array.usize` always retur
|
||||
the array since the implementation only supports arrays of size less than `USize.size`.
|
||||
-/
|
||||
@[extern "lean_array_size", simp]
|
||||
def usize (a : @& Array α) : USize := a.size.toUSize
|
||||
def usize (xs : @& Array α) : USize := xs.size.toUSize
|
||||
|
||||
/--
|
||||
Low-level indexing operator which is as fast as a C array read.
|
||||
@@ -171,8 +173,8 @@ Low-level indexing operator which is as fast as a C array read.
|
||||
This avoids overhead due to unboxing a `Nat` used as an index.
|
||||
-/
|
||||
@[extern "lean_array_uget", simp, expose]
|
||||
def uget (a : @& Array α) (i : USize) (h : i.toNat < a.size) : α :=
|
||||
a[i.toNat]
|
||||
def uget (xs : @& Array α) (i : USize) (h : i.toNat < xs.size) : α :=
|
||||
xs[i.toNat]
|
||||
|
||||
/--
|
||||
Low-level modification operator which is as fast as a C array write. The modification is performed
|
||||
@@ -1165,7 +1167,7 @@ Examples:
|
||||
def zipIdx (xs : Array α) (start := 0) : Array (α × Nat) :=
|
||||
xs.mapIdx fun i a => (a, start + i)
|
||||
|
||||
@[deprecated zipIdx (since := "2025-01-21")] abbrev zipWithIndex := @zipIdx
|
||||
|
||||
|
||||
/--
|
||||
Returns the first element of the array for which the predicate `p` returns `true`, or `none` if no
|
||||
@@ -1285,7 +1287,7 @@ def findFinIdx? {α : Type u} (p : α → Bool) (as : Array α) : Option (Fin as
|
||||
decreasing_by simp_wf; decreasing_trivial_pre_omega
|
||||
loop 0
|
||||
|
||||
theorem findIdx?_loop_eq_map_findFinIdx?_loop_val {xs : Array α} {p : α → Bool} {j} :
|
||||
private theorem findIdx?_loop_eq_map_findFinIdx?_loop_val {xs : Array α} {p : α → Bool} {j} :
|
||||
findIdx?.loop p xs j = (findFinIdx?.loop p xs j).map (·.val) := by
|
||||
unfold findIdx?.loop
|
||||
unfold findFinIdx?.loop
|
||||
@@ -1322,8 +1324,7 @@ def idxOfAux [BEq α] (xs : Array α) (v : α) (i : Nat) : Option (Fin xs.size)
|
||||
else none
|
||||
decreasing_by simp_wf; decreasing_trivial_pre_omega
|
||||
|
||||
@[deprecated idxOfAux (since := "2025-01-29")]
|
||||
abbrev indexOfAux := @idxOfAux
|
||||
|
||||
|
||||
/--
|
||||
Returns the index of the first element equal to `a`, or the size of the array if no element is equal
|
||||
@@ -1338,8 +1339,7 @@ Examples:
|
||||
def finIdxOf? [BEq α] (xs : Array α) (v : α) : Option (Fin xs.size) :=
|
||||
idxOfAux xs v 0
|
||||
|
||||
@[deprecated "`Array.indexOf?` has been deprecated, use `idxOf?` or `finIdxOf?` instead." (since := "2025-01-29")]
|
||||
abbrev indexOf? := @finIdxOf?
|
||||
|
||||
|
||||
/--
|
||||
Returns the index of the first element equal to `a`, or the size of the array if no element is equal
|
||||
@@ -1956,16 +1956,16 @@ def isPrefixOf [BEq α] (as bs : Array α) : Bool :=
|
||||
false
|
||||
|
||||
@[semireducible, specialize] -- This is otherwise irreducible because it uses well-founded recursion.
|
||||
def zipWithAux (as : Array α) (bs : Array β) (f : α → β → γ) (i : Nat) (cs : Array γ) : Array γ :=
|
||||
def zipWithMAux {m : Type v → Type w} [Monad m] (as : Array α) (bs : Array β) (f : α → β → m γ) (i : Nat) (cs : Array γ) : m (Array γ) := do
|
||||
if h : i < as.size then
|
||||
let a := as[i]
|
||||
if h : i < bs.size then
|
||||
let b := bs[i]
|
||||
zipWithAux as bs f (i+1) <| cs.push <| f a b
|
||||
zipWithMAux as bs f (i+1) <| cs.push (← f a b)
|
||||
else
|
||||
cs
|
||||
return cs
|
||||
else
|
||||
cs
|
||||
return cs
|
||||
decreasing_by simp_wf; decreasing_trivial_pre_omega
|
||||
|
||||
/--
|
||||
@@ -1979,7 +1979,7 @@ Examples:
|
||||
* `#[x₁, x₂, x₃].zipWith f #[y₁, y₂, y₃, y₄] = #[f x₁ y₁, f x₂ y₂, f x₃ y₃]`
|
||||
-/
|
||||
@[inline] def zipWith (f : α → β → γ) (as : Array α) (bs : Array β) : Array γ :=
|
||||
zipWithAux as bs f 0 #[]
|
||||
Id.run (zipWithMAux as bs (pure <| f · ·) 0 #[])
|
||||
|
||||
/--
|
||||
Combines two arrays into an array of pairs in which the first and second components are the
|
||||
@@ -2016,6 +2016,13 @@ where go (as : Array α) (bs : Array β) (i : Nat) (cs : Array γ) :=
|
||||
termination_by max as.size bs.size - i
|
||||
decreasing_by simp_wf; decreasing_trivial_pre_omega
|
||||
|
||||
/--
|
||||
Applies a monadic function to the corresponding elements of two arrays, left-to-right, stopping at
|
||||
the end of the shorter array. `zipWithM f as bs` is equivalent to `mapM id (zipWith f as bs)`.
|
||||
-/
|
||||
@[inline] def zipWithM {m : Type v → Type w} [Monad m] (f : α → β → m γ) (as : Array α) (bs : Array β) : m (Array γ) :=
|
||||
zipWithMAux as bs f 0 #[]
|
||||
|
||||
/--
|
||||
Separates an array of pairs into two arrays that contain the respective first and second components.
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ Authors: Leonardo de Moura
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Nat.Linear
|
||||
public import Init.NotationExtra
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.List.TakeDrop
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
|
||||
public section
|
||||
|
||||
@@ -34,8 +35,8 @@ the index is in bounds. This is because the tactic itself needs to look up value
|
||||
arrays.
|
||||
-/
|
||||
@[deprecated "Use indexing notation `as[i]` instead" (since := "2025-02-17")]
|
||||
def get {α : Type u} (a : @& Array α) (i : @& Nat) (h : LT.lt i a.size) : α :=
|
||||
a.toList.get ⟨i, h⟩
|
||||
def get {α : Type u} (xs : @& Array α) (i : @& Nat) (h : LT.lt i xs.size) : α :=
|
||||
xs.toList.get ⟨i, h⟩
|
||||
|
||||
/--
|
||||
Use the indexing notation `a[i]!` instead.
|
||||
@@ -43,8 +44,8 @@ Use the indexing notation `a[i]!` instead.
|
||||
Access an element from an array, or panic if the index is out of bounds.
|
||||
-/
|
||||
@[deprecated "Use indexing notation `as[i]!` instead" (since := "2025-02-17"), expose]
|
||||
def get! {α : Type u} [Inhabited α] (a : @& Array α) (i : @& Nat) : α :=
|
||||
Array.getD a i default
|
||||
def get! {α : Type u} [Inhabited α] (xs : @& Array α) (i : @& Nat) : α :=
|
||||
Array.getD xs i default
|
||||
|
||||
theorem foldlM_toList.aux [Monad m]
|
||||
{f : β → α → m β} {xs : Array α} {i j} (H : xs.size ≤ i + j) {b} :
|
||||
@@ -123,15 +124,9 @@ abbrev pop_toList := @Array.toList_pop
|
||||
@[simp, grind =] theorem append_empty {xs : Array α} : xs ++ #[] = xs := by
|
||||
apply ext'; simp only [toList_append, List.append_nil]
|
||||
|
||||
@[deprecated append_empty (since := "2025-01-13")]
|
||||
abbrev append_nil := @append_empty
|
||||
|
||||
@[simp, grind =] theorem empty_append {xs : Array α} : #[] ++ xs = xs := by
|
||||
apply ext'; simp only [toList_append, List.nil_append]
|
||||
|
||||
@[deprecated empty_append (since := "2025-01-13")]
|
||||
abbrev nil_append := @empty_append
|
||||
|
||||
@[simp, grind _=_] theorem append_assoc {xs ys zs : Array α} : xs ++ ys ++ zs = xs ++ (ys ++ zs) := by
|
||||
apply ext'; simp only [toList_append, List.append_assoc]
|
||||
|
||||
@@ -142,7 +137,6 @@ abbrev nil_append := @empty_append
|
||||
rw [← appendList_eq_append]; unfold Array.appendList
|
||||
induction l generalizing xs <;> simp [*]
|
||||
|
||||
@[deprecated toList_appendList (since := "2024-12-11")]
|
||||
abbrev appendList_toList := @toList_appendList
|
||||
|
||||
|
||||
end Array
|
||||
|
||||
@@ -6,7 +6,8 @@ Authors: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.List.Nat.Count
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ Authors: Leonardo de Moura
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.BEq
|
||||
public import Init.Data.List.Nat.BEq
|
||||
public import Init.ByCases
|
||||
|
||||
@@ -6,7 +6,8 @@ Authors: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.List.Nat.Erase
|
||||
public import Init.Data.List.Nat.Basic
|
||||
|
||||
@@ -7,7 +7,8 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.List.Nat.Find
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.Attach
|
||||
public import Init.Data.Array.Range
|
||||
|
||||
@@ -8,19 +8,20 @@ module
|
||||
prelude
|
||||
public import Init.Data.Nat.Lemmas
|
||||
public import Init.Data.List.Range
|
||||
public import all Init.Data.List.Control
|
||||
public import Init.Data.List.Nat.TakeDrop
|
||||
public import Init.Data.List.Nat.Modify
|
||||
public import Init.Data.List.Nat.Basic
|
||||
public import Init.Data.List.Monadic
|
||||
public import Init.Data.List.OfFn
|
||||
public import all Init.Data.Array.Bootstrap
|
||||
public import Init.Data.Array.Mem
|
||||
public import Init.Data.Array.DecidableEq
|
||||
public import Init.Data.Array.Lex.Basic
|
||||
public import Init.Data.Range.Lemmas
|
||||
public import Init.TacticsExtra
|
||||
public import Init.Data.List.ToArray
|
||||
import all Init.Data.List.Control
|
||||
import all Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Bootstrap
|
||||
|
||||
public section
|
||||
|
||||
@@ -311,7 +312,7 @@ theorem eq_push_pop_back!_of_size_ne_zero [Inhabited α] {xs : Array α} (h : xs
|
||||
xs = xs.pop.push xs.back! := by
|
||||
apply ext
|
||||
· simp [Nat.sub_add_cancel (Nat.zero_lt_of_ne_zero h)]
|
||||
· intros i h h'
|
||||
· intro i h h'
|
||||
if hlt : i < xs.pop.size then
|
||||
rw [getElem_push_lt (h:=hlt), getElem_pop]
|
||||
else
|
||||
@@ -837,15 +838,10 @@ theorem mem_of_contains_eq_true [BEq α] [LawfulBEq α] {a : α} {as : Array α}
|
||||
cases as
|
||||
simp
|
||||
|
||||
@[deprecated mem_of_contains_eq_true (since := "2024-12-12")]
|
||||
abbrev mem_of_elem_eq_true := @mem_of_contains_eq_true
|
||||
|
||||
theorem contains_eq_true_of_mem [BEq α] [LawfulBEq α] {a : α} {as : Array α} (h : a ∈ as) : as.contains a = true := by
|
||||
theorem contains_eq_true_of_mem [BEq α] [ReflBEq α] {a : α} {as : Array α} (h : a ∈ as) :
|
||||
as.contains a = true := by
|
||||
cases as
|
||||
simpa using h
|
||||
|
||||
@[deprecated contains_eq_true_of_mem (since := "2024-12-12")]
|
||||
abbrev elem_eq_true_of_mem := @contains_eq_true_of_mem
|
||||
simpa using List.elem_eq_true_of_mem (Array.mem_toList_iff.mpr h)
|
||||
|
||||
@[simp] theorem elem_eq_contains [BEq α] {a : α} {xs : Array α} :
|
||||
elem a xs = xs.contains a := by
|
||||
@@ -872,24 +868,24 @@ theorem elem_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
|
||||
@[grind] theorem all_empty [BEq α] {p : α → Bool} : (#[] : Array α).all p = true := by simp
|
||||
|
||||
/-- Variant of `any_push` with a side condition on `stop`. -/
|
||||
@[simp, grind] theorem any_push' [BEq α] {xs : Array α} {a : α} {p : α → Bool} (h : stop = xs.size + 1) :
|
||||
@[simp, grind] theorem any_push' {xs : Array α} {a : α} {p : α → Bool} (h : stop = xs.size + 1) :
|
||||
(xs.push a).any p 0 stop = (xs.any p || p a) := by
|
||||
cases xs
|
||||
rw [List.push_toArray]
|
||||
simp [h]
|
||||
|
||||
theorem any_push [BEq α] {xs : Array α} {a : α} {p : α → Bool} :
|
||||
theorem any_push {xs : Array α} {a : α} {p : α → Bool} :
|
||||
(xs.push a).any p = (xs.any p || p a) :=
|
||||
any_push' (by simp)
|
||||
|
||||
/-- Variant of `all_push` with a side condition on `stop`. -/
|
||||
@[simp, grind] theorem all_push' [BEq α] {xs : Array α} {a : α} {p : α → Bool} (h : stop = xs.size + 1) :
|
||||
@[simp, grind] theorem all_push' {xs : Array α} {a : α} {p : α → Bool} (h : stop = xs.size + 1) :
|
||||
(xs.push a).all p 0 stop = (xs.all p && p a) := by
|
||||
cases xs
|
||||
rw [List.push_toArray]
|
||||
simp [h]
|
||||
|
||||
theorem all_push [BEq α] {xs : Array α} {a : α} {p : α → Bool} :
|
||||
theorem all_push {xs : Array α} {a : α} {p : α → Bool} :
|
||||
(xs.push a).all p = (xs.all p && p a) :=
|
||||
all_push' (by simp)
|
||||
|
||||
@@ -904,15 +900,9 @@ theorem all_push [BEq α] {xs : Array α} {a : α} {p : α → Bool} :
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[deprecated getElem_set_self (since := "2024-12-11")]
|
||||
abbrev getElem_set_eq := @getElem_set_self
|
||||
|
||||
@[simp] theorem getElem?_set_self {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} :
|
||||
(xs.set i v)[i]? = some v := by simp [h]
|
||||
|
||||
@[deprecated getElem?_set_self (since := "2024-12-11")]
|
||||
abbrev getElem?_set_eq := @getElem?_set_self
|
||||
|
||||
@[simp] theorem getElem_set_ne {xs : Array α} {i : Nat} (h' : i < xs.size) {v : α} {j : Nat}
|
||||
(pj : j < xs.size) (h : i ≠ j) :
|
||||
(xs.set i v)[j]'(by simp [*]) = xs[j] := by
|
||||
@@ -1003,9 +993,6 @@ grind_pattern mem_or_eq_of_mem_set => a ∈ xs.set i b
|
||||
theorem setIfInBounds_def (xs : Array α) (i : Nat) (a : α) :
|
||||
xs.setIfInBounds i a = if h : i < xs.size then xs.set i a else xs := rfl
|
||||
|
||||
@[deprecated set!_eq_setIfInBounds (since := "2024-12-12")]
|
||||
abbrev set!_is_setIfInBounds := @set!_eq_setIfInBounds
|
||||
|
||||
@[simp, grind] theorem size_setIfInBounds {xs : Array α} {i : Nat} {a : α} :
|
||||
(xs.setIfInBounds i a).size = xs.size := by
|
||||
if h : i < xs.size then
|
||||
@@ -1027,9 +1014,6 @@ abbrev set!_is_setIfInBounds := @set!_eq_setIfInBounds
|
||||
simp at h
|
||||
simp only [setIfInBounds, h, ↓reduceDIte, getElem_set_self]
|
||||
|
||||
@[deprecated getElem_setIfInBounds_self (since := "2024-12-11")]
|
||||
abbrev getElem_setIfInBounds_eq := @getElem_setIfInBounds_self
|
||||
|
||||
@[simp] theorem getElem_setIfInBounds_ne {xs : Array α} {i : Nat} {a : α} {j : Nat}
|
||||
(hj : j < xs.size) (h : i ≠ j) :
|
||||
(xs.setIfInBounds i a)[j]'(by simpa using hj) = xs[j] := by
|
||||
@@ -1049,9 +1033,6 @@ theorem getElem?_setIfInBounds_self_of_lt {xs : Array α} {i : Nat} {a : α} (h
|
||||
(xs.setIfInBounds i a)[i]? = some a := by
|
||||
simp [h]
|
||||
|
||||
@[deprecated getElem?_setIfInBounds_self (since := "2024-12-11")]
|
||||
abbrev getElem?_setIfInBounds_eq := @getElem?_setIfInBounds_self
|
||||
|
||||
@[simp] theorem getElem?_setIfInBounds_ne {xs : Array α} {i j : Nat} (h : i ≠ j) {a : α} :
|
||||
(xs.setIfInBounds i a)[j]? = xs[j]? := by
|
||||
simp [getElem?_setIfInBounds, h]
|
||||
@@ -1377,23 +1358,6 @@ theorem mapM_eq_mapM_toList [Monad m] [LawfulMonad m] {f : α → m β} {xs : Ar
|
||||
toList <$> xs.mapM f = xs.toList.mapM f := by
|
||||
simp [mapM_eq_mapM_toList]
|
||||
|
||||
@[deprecated "Use `mapM_eq_foldlM` instead" (since := "2025-01-08")]
|
||||
theorem mapM_map_eq_foldl {as : Array α} {f : α → β} {i : Nat} :
|
||||
mapM.map (m := Id) (pure <| f ·) as i b = pure (as.foldl (start := i) (fun acc a => acc.push (f a)) b) := by
|
||||
unfold mapM.map
|
||||
split <;> rename_i h
|
||||
· ext : 1
|
||||
dsimp [foldl, foldlM]
|
||||
rw [mapM_map_eq_foldl, dif_pos (by omega), foldlM.loop, dif_pos h]
|
||||
-- Calling `split` here gives a bad goal.
|
||||
have : size as - i = Nat.succ (size as - i - 1) := by omega
|
||||
rw [this]
|
||||
simp [foldl, foldlM, Nat.sub_add_eq]
|
||||
· dsimp [foldl, foldlM]
|
||||
rw [dif_pos (by omega), foldlM.loop, dif_neg h]
|
||||
rfl
|
||||
termination_by as.size - i
|
||||
|
||||
/--
|
||||
Use this as `induction ass using array₂_induction` on a hypothesis of the form `ass : Array (Array α)`.
|
||||
The hypothesis `ass` will be replaced with a hypothesis `ass : List (List α)`,
|
||||
@@ -1676,12 +1640,12 @@ theorem filterMap_eq_map' {f : α → β} (w : stop = as.size) :
|
||||
filterMap (fun x => some (f x)) as 0 stop = map f as :=
|
||||
filterMap_eq_map w
|
||||
|
||||
@[simp] theorem filterMap_some_fun : filterMap (some : α → Option α) = id := by
|
||||
theorem filterMap_some_fun : filterMap (some : α → Option α) = id := by
|
||||
funext xs
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[grind] theorem filterMap_some {xs : Array α} : filterMap some xs = xs := by
|
||||
@[simp, grind] theorem filterMap_some {xs : Array α} : filterMap some xs = xs := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@@ -2930,14 +2894,14 @@ theorem getElem_extract_loop_ge_aux {xs ys : Array α} {size start : Nat} (hge :
|
||||
exact Nat.sub_lt_left_of_lt_add hge h
|
||||
|
||||
theorem getElem_extract_loop_ge {xs ys : Array α} {size start : Nat} (hge : i ≥ ys.size)
|
||||
(h : i < (extract.loop xs size start ys).size)
|
||||
(h' := getElem_extract_loop_ge_aux hge h) :
|
||||
(extract.loop xs size start ys)[i] = xs[start + i - ys.size] := by
|
||||
(h : i < (extract.loop xs size start ys).size) :
|
||||
(extract.loop xs size start ys)[i] = xs[start + i - ys.size]'(getElem_extract_loop_ge_aux hge h) := by
|
||||
induction size using Nat.recAux generalizing start ys with
|
||||
| zero =>
|
||||
rw [size_extract_loop, Nat.zero_min, Nat.add_zero] at h
|
||||
omega
|
||||
| succ size ih =>
|
||||
have h' : start + i - ys.size < xs.size := getElem_extract_loop_ge_aux hge h
|
||||
have : start < xs.size := by
|
||||
apply Nat.lt_of_le_of_lt (Nat.le_add_right start (i - ys.size))
|
||||
rwa [← Nat.add_sub_assoc hge]
|
||||
@@ -2991,7 +2955,7 @@ theorem getElem?_extract {xs : Array α} {start stop : Nat} :
|
||||
apply List.ext_getElem
|
||||
· simp only [length_toList, size_extract, List.length_take, List.length_drop]
|
||||
omega
|
||||
· intros n h₁ h₂
|
||||
· intro n h₁ h₂
|
||||
simp
|
||||
|
||||
@[simp] theorem extract_size {xs : Array α} : xs.extract 0 xs.size = xs := by
|
||||
@@ -2999,9 +2963,6 @@ theorem getElem?_extract {xs : Array α} {start stop : Nat} :
|
||||
· rw [size_extract, Nat.min_self, Nat.sub_zero]
|
||||
· intros; rw [getElem_extract]; congr; rw [Nat.zero_add]
|
||||
|
||||
@[deprecated extract_size (since := "2025-01-19")]
|
||||
abbrev extract_all := @extract_size
|
||||
|
||||
theorem extract_empty_of_stop_le_start {xs : Array α} {start stop : Nat} (h : stop ≤ start) :
|
||||
xs.extract start stop = #[] := by
|
||||
simp only [extract, Nat.sub_eq, emptyWithCapacity_eq]
|
||||
@@ -3036,14 +2997,14 @@ theorem take_size {xs : Array α} : xs.take xs.size = xs := by
|
||||
|
||||
/-! ### shrink -/
|
||||
|
||||
@[simp] theorem size_shrink_loop {xs : Array α} {n : Nat} : (shrink.loop n xs).size = xs.size - n := by
|
||||
@[simp] private theorem size_shrink_loop {xs : Array α} {n : Nat} : (shrink.loop n xs).size = xs.size - n := by
|
||||
induction n generalizing xs with
|
||||
| zero => simp [shrink.loop]
|
||||
| succ n ih =>
|
||||
simp [shrink.loop, ih]
|
||||
omega
|
||||
|
||||
@[simp] theorem getElem_shrink_loop {xs : Array α} {n i : Nat} (h : i < (shrink.loop n xs).size) :
|
||||
@[simp] private theorem getElem_shrink_loop {xs : Array α} {n i : Nat} (h : i < (shrink.loop n xs).size) :
|
||||
(shrink.loop n xs)[i] = xs[i]'(by simp at h; omega) := by
|
||||
induction n generalizing xs i with
|
||||
| zero => simp [shrink.loop]
|
||||
@@ -3312,11 +3273,11 @@ theorem foldl_induction
|
||||
let rec go {i j b} (h₁ : j ≤ as.size) (h₂ : as.size ≤ i + j) (H : motive j b) :
|
||||
(motive as.size) (foldlM.loop (m := Id) f as as.size (Nat.le_refl _) i j b) := by
|
||||
unfold foldlM.loop; split
|
||||
· next hj =>
|
||||
next hj =>
|
||||
split
|
||||
· cases Nat.not_le_of_gt (by simp [hj]) h₂
|
||||
· exact go hj (by rwa [Nat.succ_add] at h₂) (hf ⟨j, hj⟩ b H)
|
||||
· next hj => exact Nat.le_antisymm h₁ (Nat.ge_of_not_lt hj) ▸ H
|
||||
next hj => exact Nat.le_antisymm h₁ (Nat.ge_of_not_lt hj) ▸ H
|
||||
simpa [foldl, foldlM] using go (Nat.zero_le _) (Nat.le_refl _) h0
|
||||
|
||||
theorem foldr_induction
|
||||
@@ -3326,13 +3287,13 @@ theorem foldr_induction
|
||||
let rec go {i b} (hi : i ≤ as.size) (H : motive i b) :
|
||||
(motive 0) (foldrM.fold (m := Id) f as 0 i hi b) := by
|
||||
unfold foldrM.fold; simp; split
|
||||
· next hi => exact (hi ▸ H)
|
||||
· next hi =>
|
||||
next hi => exact (hi ▸ H)
|
||||
next hi =>
|
||||
split; {simp at hi}
|
||||
· next i hi' =>
|
||||
next i hi' =>
|
||||
exact go _ (hf ⟨i, hi'⟩ b H)
|
||||
simp [foldr, foldrM]; split; {exact go _ h0}
|
||||
· next h => exact (Nat.eq_zero_of_not_pos h ▸ h0)
|
||||
next h => exact (Nat.eq_zero_of_not_pos h ▸ h0)
|
||||
|
||||
@[congr]
|
||||
theorem foldl_congr {as bs : Array α} (h₀ : as = bs) {f g : β → α → β} (h₁ : f = g)
|
||||
@@ -4319,7 +4280,7 @@ Examples:
|
||||
|
||||
/-! ### Preliminaries about `ofFn` -/
|
||||
|
||||
@[simp] theorem size_ofFn_go {n} {f : Fin n → α} {i acc h} :
|
||||
@[simp] private theorem size_ofFn_go {n} {f : Fin n → α} {i acc h} :
|
||||
(ofFn.go f acc i h).size = acc.size + i := by
|
||||
induction i generalizing acc with
|
||||
| zero => simp [ofFn.go]
|
||||
@@ -4329,7 +4290,7 @@ Examples:
|
||||
@[simp] theorem size_ofFn {n : Nat} {f : Fin n → α} : (ofFn f).size = n := by simp [ofFn]
|
||||
|
||||
-- Recall `ofFn.go f acc i h = acc ++ #[f (n - i), ..., f(n - 1)]`
|
||||
theorem getElem_ofFn_go {f : Fin n → α} {acc i k} (h : i ≤ n) (w₁ : k < acc.size + i) :
|
||||
private theorem getElem_ofFn_go {f : Fin n → α} {acc i k} (h : i ≤ n) (w₁ : k < acc.size + i) :
|
||||
(ofFn.go f acc i h)[k]'(by simpa using w₁) =
|
||||
if w₂ : k < acc.size then acc[k] else f ⟨n - i + k - acc.size, by omega⟩ := by
|
||||
induction i generalizing acc k with
|
||||
@@ -4413,10 +4374,17 @@ theorem getElem?_range {n : Nat} {i : Nat} : (Array.range n)[i]? = if i < n then
|
||||
|
||||
-- Without further algebraic hypotheses, there's no useful `sum_push` lemma.
|
||||
|
||||
@[simp, grind =]
|
||||
theorem sum_eq_sum_toList [Add α] [Zero α] {as : Array α} : as.toList.sum = as.sum := by
|
||||
cases as
|
||||
simp [Array.sum, List.sum]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem sum_append_nat {as₁ as₂ : Array Nat} : (as₁ ++ as₂).sum = as₁.sum + as₂.sum := by
|
||||
cases as₁
|
||||
cases as₂
|
||||
simp [List.sum_append_nat]
|
||||
|
||||
theorem foldl_toList_eq_flatMap {l : List α} {acc : Array β}
|
||||
{F : Array β → α → Array β} {G : α → List β}
|
||||
(H : ∀ acc a, (F acc a).toList = acc.toList ++ G a) :
|
||||
@@ -4727,27 +4695,10 @@ end List
|
||||
/-! ### Deprecations -/
|
||||
namespace Array
|
||||
|
||||
@[deprecated size_toArray (since := "2024-12-11")]
|
||||
theorem size_mk (as : List α) : (Array.mk as).size = as.length := by simp
|
||||
|
||||
@[deprecated getElem?_eq_getElem (since := "2024-12-11")]
|
||||
theorem getElem?_lt
|
||||
(xs : Array α) {i : Nat} (h : i < xs.size) : xs[i]? = some xs[i] := dif_pos h
|
||||
|
||||
@[deprecated getElem?_eq_none (since := "2024-12-11")]
|
||||
theorem getElem?_ge
|
||||
(xs : Array α) {i : Nat} (h : i ≥ xs.size) : xs[i]? = none := dif_neg (Nat.not_lt_of_le h)
|
||||
|
||||
set_option linter.deprecated false in
|
||||
@[deprecated "`get?` is deprecated" (since := "2025-02-12"), simp]
|
||||
theorem get?_eq_getElem? (xs : Array α) (i : Nat) : xs.get? i = xs[i]? := rfl
|
||||
|
||||
@[deprecated getElem?_eq_none (since := "2024-12-11")]
|
||||
theorem getElem?_len_le (xs : Array α) {i : Nat} (h : xs.size ≤ i) : xs[i]? = none := by
|
||||
simp [h]
|
||||
|
||||
@[deprecated getD_getElem? (since := "2024-12-11")] abbrev getD_get? := @getD_getElem?
|
||||
|
||||
@[deprecated getD_eq_getD_getElem? (since := "2025-02-12")] abbrev getD_eq_get? := @getD_eq_getD_getElem?
|
||||
|
||||
set_option linter.deprecated false in
|
||||
@@ -4772,64 +4723,9 @@ theorem get?_eq_get?_toList (xs : Array α) (i : Nat) : xs.get? i = xs.toList.ge
|
||||
set_option linter.deprecated false in
|
||||
@[deprecated get!_eq_getD_getElem? (since := "2025-02-12")] abbrev get!_eq_get? := @get!_eq_getD_getElem?
|
||||
|
||||
@[deprecated getElem_set_self (since := "2025-01-17")]
|
||||
theorem get_set_eq (xs : Array α) (i : Nat) (v : α) (h : i < xs.size) :
|
||||
(xs.set i v h)[i]'(by simp [h]) = v := by
|
||||
simp only [set, ← getElem_toList, List.getElem_set_self]
|
||||
|
||||
@[deprecated Array.getElem_toList (since := "2024-12-08")]
|
||||
theorem getElem_eq_getElem_toList {xs : Array α} (h : i < xs.size) : xs[i] = xs.toList[i] := rfl
|
||||
|
||||
@[deprecated Array.getElem?_toList (since := "2024-12-08")]
|
||||
theorem getElem?_eq_getElem?_toList (xs : Array α) (i : Nat) : xs[i]? = xs.toList[i]? := by
|
||||
rw [getElem?_def]
|
||||
split <;> simp_all
|
||||
|
||||
@[deprecated LawfulGetElem.getElem?_def (since := "2024-12-08")]
|
||||
theorem getElem?_eq {xs : Array α} {i : Nat} :
|
||||
xs[i]? = if h : i < xs.size then some xs[i] else none := by
|
||||
rw [getElem?_def]
|
||||
|
||||
/-! ### map -/
|
||||
|
||||
@[deprecated "Use `toList_map` or `List.map_toArray` to characterize `Array.map`." (since := "2025-01-06")]
|
||||
theorem map_induction (xs : Array α) (f : α → β) (motive : Nat → Prop) (h0 : motive 0)
|
||||
(p : Fin xs.size → β → Prop) (hs : ∀ i, motive i.1 → p i (f xs[i]) ∧ motive (i+1)) :
|
||||
motive xs.size ∧
|
||||
∃ eq : (xs.map f).size = xs.size, ∀ i h, p ⟨i, h⟩ ((xs.map f)[i]) := by
|
||||
have t := foldl_induction (as := xs) (β := Array β)
|
||||
(motive := fun i xs => motive i ∧ xs.size = i ∧ ∀ i h2, p i xs[i.1])
|
||||
(init := #[]) (f := fun acc a => acc.push (f a)) ?_ ?_
|
||||
obtain ⟨m, eq, w⟩ := t
|
||||
· refine ⟨m, by simp, ?_⟩
|
||||
intro i h
|
||||
simp only [eq] at w
|
||||
specialize w ⟨i, h⟩ h
|
||||
simpa using w
|
||||
· exact ⟨h0, rfl, nofun⟩
|
||||
· intro i bs ⟨m, ⟨eq, w⟩⟩
|
||||
refine ⟨?_, ?_, ?_⟩
|
||||
· exact (hs _ m).2
|
||||
· simp_all
|
||||
· intro j h
|
||||
simp at h ⊢
|
||||
by_cases h' : j < size bs
|
||||
· rw [getElem_push]
|
||||
simp_all
|
||||
· rw [getElem_push, dif_neg h']
|
||||
simp only [show j = i by omega]
|
||||
exact (hs _ m).1
|
||||
|
||||
set_option linter.deprecated false in
|
||||
@[deprecated "Use `toList_map` or `List.map_toArray` to characterize `Array.map`." (since := "2025-01-06")]
|
||||
theorem map_spec (xs : Array α) (f : α → β) (p : Fin xs.size → β → Prop)
|
||||
(hs : ∀ i, p i (f xs[i])) :
|
||||
∃ eq : (xs.map f).size = xs.size, ∀ i h, p ⟨i, h⟩ ((xs.map f)[i]) := by
|
||||
simpa using map_induction xs f (fun _ => True) trivial p (by simp_all)
|
||||
|
||||
/-! ### set -/
|
||||
|
||||
@[deprecated getElem?_set_eq (since := "2025-02-27")] abbrev get?_set_eq := @getElem?_set_self
|
||||
@[deprecated getElem?_set_self (since := "2025-02-27")] abbrev get?_set_eq := @getElem?_set_self
|
||||
@[deprecated getElem?_set_ne (since := "2025-02-27")] abbrev get?_set_ne := @getElem?_set_ne
|
||||
@[deprecated getElem?_set (since := "2025-02-27")] abbrev get?_set := @getElem?_set
|
||||
@[deprecated get_set (since := "2025-02-27")] abbrev get_set := @getElem_set
|
||||
|
||||
@@ -12,9 +12,12 @@ public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.List.Lex
|
||||
import Init.Data.Range.Polymorphic.Lemmas
|
||||
import Init.Data.Range.Polymorphic.NatLemmas
|
||||
import Init.Data.Order.Lemmas
|
||||
|
||||
public section
|
||||
|
||||
open Std
|
||||
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
@@ -28,8 +31,8 @@ namespace Array
|
||||
@[simp] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList ↔ xs < ys := Iff.rfl
|
||||
@[simp] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ≤ ys.toList ↔ xs ≤ ys := Iff.rfl
|
||||
|
||||
grind_pattern _root_.List.lt_toArray => l₁.toArray < l₂.toArray
|
||||
grind_pattern _root_.List.le_toArray => l₁.toArray ≤ l₂.toArray
|
||||
grind_pattern _root_.List.lt_toArray => l₁.toArray < l₂.toArray
|
||||
grind_pattern _root_.List.le_toArray => l₁.toArray ≤ l₂.toArray
|
||||
grind_pattern lt_toList => xs.toList < ys.toList
|
||||
grind_pattern le_toList => xs.toList ≤ ys.toList
|
||||
|
||||
@@ -100,6 +103,14 @@ theorem singleton_lex_singleton [BEq α] {lt : α → α → Bool} : #[a].lex #[
|
||||
xs.toList.lex ys.toList lt = xs.lex ys lt := by
|
||||
cases xs <;> cases ys <;> simp
|
||||
|
||||
instance [LT α] [LE α] [LawfulOrderLT α] [IsLinearOrder α] : IsLinearOrder (Array α) := by
|
||||
apply IsLinearOrder.of_le
|
||||
· constructor
|
||||
intro _ _ hab hba
|
||||
simpa using Std.le_antisymm (α := List α) hab hba
|
||||
· constructor; exact Std.le_trans (α := List α)
|
||||
· constructor; exact fun _ _ => Std.le_total (α := List α)
|
||||
|
||||
protected theorem lt_irrefl [LT α] [Std.Irrefl (· < · : α → α → Prop)] (xs : Array α) : ¬ xs < xs :=
|
||||
List.lt_irrefl xs.toList
|
||||
|
||||
@@ -131,27 +142,35 @@ instance [LT α] [Trans (· < · : α → α → Prop) (· < ·) (· < ·)] :
|
||||
Trans (· < · : Array α → Array α → Prop) (· < ·) (· < ·) where
|
||||
trans h₁ h₂ := Array.lt_trans h₁ h₂
|
||||
|
||||
protected theorem lt_of_le_of_lt [LT α]
|
||||
[i₀ : Std.Irrefl (· < · : α → α → Prop)]
|
||||
protected theorem lt_of_le_of_lt [LE α] [LT α] [LawfulOrderLT α] [IsLinearOrder α]
|
||||
{xs ys zs : Array α} (h₁ : xs ≤ ys) (h₂ : ys < zs) : xs < zs :=
|
||||
Std.lt_of_le_of_lt (α := List α) h₁ h₂
|
||||
|
||||
@[deprecated Array.lt_of_le_of_lt (since := "2025-08-01")]
|
||||
protected theorem lt_of_le_of_lt' [LT α]
|
||||
[i₁ : Std.Asymm (· < · : α → α → Prop)]
|
||||
[i₂ : Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[i₃ : Trans (¬ · < · : α → α → Prop) (¬ · < ·) (¬ · < ·)]
|
||||
{xs ys zs : Array α} (h₁ : xs ≤ ys) (h₂ : ys < zs) : xs < zs :=
|
||||
List.lt_of_le_of_lt h₁ h₂
|
||||
letI := LE.ofLT α
|
||||
haveI : IsLinearOrder α := IsLinearOrder.of_lt
|
||||
Array.lt_of_le_of_lt h₁ h₂
|
||||
|
||||
protected theorem le_trans [LT α]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[Trans (¬ · < · : α → α → Prop) (¬ · < ·) (¬ · < ·)]
|
||||
protected theorem le_trans [LE α] [LT α] [LawfulOrderLT α] [IsLinearOrder α]
|
||||
{xs ys zs : Array α} (h₁ : xs ≤ ys) (h₂ : ys ≤ zs) : xs ≤ zs :=
|
||||
fun h₃ => h₁ (Array.lt_of_le_of_lt h₂ h₃)
|
||||
|
||||
instance [LT α]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[Trans (¬ · < · : α → α → Prop) (¬ · < ·) (¬ · < ·)] :
|
||||
@[deprecated Array.le_trans (since := "2025-08-01")]
|
||||
protected theorem le_trans' [LT α]
|
||||
[i₁ : Std.Asymm (· < · : α → α → Prop)]
|
||||
[i₂ : Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[i₃ : Trans (¬ · < · : α → α → Prop) (¬ · < ·) (¬ · < ·)]
|
||||
{xs ys zs : Array α} (h₁ : xs ≤ ys) (h₂ : ys ≤ zs) : xs ≤ zs :=
|
||||
letI := LE.ofLT α
|
||||
haveI : IsLinearOrder α := IsLinearOrder.of_lt
|
||||
Array.le_trans h₁ h₂
|
||||
|
||||
instance [LE α] [LT α] [LawfulOrderLT α] [IsLinearOrder α] :
|
||||
Trans (· ≤ · : Array α → Array α → Prop) (· ≤ ·) (· ≤ ·) where
|
||||
trans h₁ h₂ := Array.le_trans h₁ h₂
|
||||
|
||||
@@ -165,7 +184,7 @@ instance [LT α]
|
||||
asymm _ _ := Array.lt_asymm
|
||||
|
||||
protected theorem le_total [LT α]
|
||||
[i : Std.Total (¬ · < · : α → α → Prop)] (xs ys : Array α) : xs ≤ ys ∨ ys ≤ xs :=
|
||||
[i : Std.Asymm (· < · : α → α → Prop)] (xs ys : Array α) : xs ≤ ys ∨ ys ≤ xs :=
|
||||
List.le_total xs.toList ys.toList
|
||||
|
||||
@[simp] protected theorem not_lt [LT α]
|
||||
@@ -175,19 +194,22 @@ protected theorem le_total [LT α]
|
||||
{xs ys : Array α} : ¬ ys ≤ xs ↔ xs < ys := Classical.not_not
|
||||
|
||||
protected theorem le_of_lt [LT α]
|
||||
[i : Std.Total (¬ · < · : α → α → Prop)]
|
||||
[i : Std.Asymm (· < · : α → α → Prop)]
|
||||
{xs ys : Array α} (h : xs < ys) : xs ≤ ys :=
|
||||
List.le_of_lt h
|
||||
|
||||
protected theorem le_iff_lt_or_eq [LT α]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[Std.Total (¬ · < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
{xs ys : Array α} : xs ≤ ys ↔ xs < ys ∨ xs = ys := by
|
||||
simpa using List.le_iff_lt_or_eq (l₁ := xs.toList) (l₂ := ys.toList)
|
||||
|
||||
instance [LT α]
|
||||
[Std.Total (¬ · < · : α → α → Prop)] :
|
||||
protected theorem le_antisymm [LT α] [LE α] [IsLinearOrder α] [LawfulOrderLT α]
|
||||
{xs ys : Array α} : xs ≤ ys → ys ≤ xs → xs = ys := by
|
||||
simpa using List.le_antisymm (as := xs.toList) (bs := ys.toList)
|
||||
|
||||
instance [LT α] [Std.Asymm (· < · : α → α → Prop)] :
|
||||
Std.Total (· ≤ · : Array α → Array α → Prop) where
|
||||
total := Array.le_total
|
||||
|
||||
@@ -266,7 +288,6 @@ protected theorem lt_iff_exists [LT α] {xs ys : Array α} :
|
||||
simp [List.lt_iff_exists]
|
||||
|
||||
protected theorem le_iff_exists [LT α]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)] {xs ys : Array α} :
|
||||
xs ≤ ys ↔
|
||||
@@ -286,7 +307,6 @@ theorem append_left_lt [LT α] {xs ys zs : Array α} (h : ys < zs) :
|
||||
simpa using List.append_left_lt h
|
||||
|
||||
theorem append_left_le [LT α]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
{xs ys zs : Array α} (h : ys ≤ zs) :
|
||||
@@ -310,10 +330,8 @@ protected theorem map_lt [LT α] [LT β]
|
||||
simpa using List.map_lt w h
|
||||
|
||||
protected theorem map_le [LT α] [LT β]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[Std.Irrefl (· < · : β → β → Prop)]
|
||||
[Std.Asymm (· < · : β → β → Prop)]
|
||||
[Std.Antisymm (¬ · < · : β → β → Prop)]
|
||||
{xs ys : Array α} {f : α → β} (w : ∀ x y, x < y → f x < f y) (h : xs ≤ ys) :
|
||||
|
||||
@@ -6,11 +6,13 @@ Authors: Mario Carneiro, Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.Attach
|
||||
public import Init.Data.Array.OfFn
|
||||
public import all Init.Data.List.MapIdx
|
||||
public import Init.Data.List.MapIdx
|
||||
import all Init.Data.List.MapIdx
|
||||
|
||||
public section
|
||||
|
||||
@@ -60,7 +62,7 @@ theorem mapFinIdx_spec {xs : Array α} {f : (i : Nat) → α → (h : i < xs.siz
|
||||
@[simp, grind =] theorem size_zipIdx {xs : Array α} {k : Nat} : (xs.zipIdx k).size = xs.size :=
|
||||
Array.size_mapFinIdx
|
||||
|
||||
@[deprecated size_zipIdx (since := "2025-01-21")] abbrev size_zipWithIndex := @size_zipIdx
|
||||
|
||||
|
||||
@[simp, grind =] theorem getElem_mapFinIdx {xs : Array α} {f : (i : Nat) → α → (h : i < xs.size) → β} {i : Nat}
|
||||
(h : i < (xs.mapFinIdx f).size) :
|
||||
@@ -132,23 +134,20 @@ namespace Array
|
||||
(xs.zipIdx k)[i] = (xs[i]'(by simp_all), k + i) := by
|
||||
simp [zipIdx]
|
||||
|
||||
@[deprecated getElem_zipIdx (since := "2025-01-21")]
|
||||
abbrev getElem_zipWithIndex := @getElem_zipIdx
|
||||
|
||||
|
||||
@[simp, grind =] theorem zipIdx_toArray {l : List α} {k : Nat} :
|
||||
l.toArray.zipIdx k = (l.zipIdx k).toArray := by
|
||||
ext i hi₁ hi₂ <;> simp
|
||||
|
||||
@[deprecated zipIdx_toArray (since := "2025-01-21")]
|
||||
abbrev zipWithIndex_toArray := @zipIdx_toArray
|
||||
|
||||
|
||||
@[simp, grind =] theorem toList_zipIdx {xs : Array α} {k : Nat} :
|
||||
(xs.zipIdx k).toList = xs.toList.zipIdx k := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[deprecated toList_zipIdx (since := "2025-01-21")]
|
||||
abbrev toList_zipWithIndex := @toList_zipIdx
|
||||
|
||||
|
||||
theorem mk_mem_zipIdx_iff_le_and_getElem?_sub {k i : Nat} {x : α} {xs : Array α} :
|
||||
(x, i) ∈ xs.zipIdx k ↔ k ≤ i ∧ xs[i - k]? = some x := by
|
||||
@@ -173,11 +172,7 @@ theorem mem_zipIdx_iff_getElem? {x : α × Nat} {xs : Array α} :
|
||||
x ∈ xs.zipIdx ↔ xs[x.2]? = some x.1 := by
|
||||
rw [mk_mem_zipIdx_iff_getElem?]
|
||||
|
||||
@[deprecated mk_mem_zipIdx_iff_getElem? (since := "2025-01-21")]
|
||||
abbrev mk_mem_zipWithIndex_iff_getElem? := @mk_mem_zipIdx_iff_getElem?
|
||||
|
||||
@[deprecated mem_zipIdx_iff_getElem? (since := "2025-01-21")]
|
||||
abbrev mem_zipWithIndex_iff_getElem? := @mem_zipIdx_iff_getElem?
|
||||
|
||||
/-! ### mapFinIdx -/
|
||||
|
||||
@@ -222,8 +217,7 @@ theorem mapFinIdx_eq_zipIdx_map {xs : Array α} {f : (i : Nat) → α → (h : i
|
||||
f i x (by simp [mk_mem_zipIdx_iff_getElem?, getElem?_eq_some_iff] at m; exact m.1) := by
|
||||
ext <;> simp
|
||||
|
||||
@[deprecated mapFinIdx_eq_zipIdx_map (since := "2025-01-21")]
|
||||
abbrev mapFinIdx_eq_zipWithIndex_map := @mapFinIdx_eq_zipIdx_map
|
||||
|
||||
|
||||
@[simp]
|
||||
theorem mapFinIdx_eq_empty_iff {xs : Array α} {f : (i : Nat) → α → (h : i < xs.size) → β} :
|
||||
@@ -332,8 +326,7 @@ theorem mapIdx_eq_zipIdx_map {xs : Array α} {f : Nat → α → β} :
|
||||
xs.mapIdx f = xs.zipIdx.map fun ⟨a, i⟩ => f i a := by
|
||||
ext <;> simp
|
||||
|
||||
@[deprecated mapIdx_eq_zipIdx_map (since := "2025-01-21")]
|
||||
abbrev mapIdx_eq_zipWithIndex_map := @mapIdx_eq_zipIdx_map
|
||||
|
||||
|
||||
@[grind =]
|
||||
theorem mapIdx_append {xs ys : Array α} :
|
||||
|
||||
@@ -18,11 +18,11 @@ set_option linter.indexVariables true -- Enforce naming conventions for index va
|
||||
namespace Array
|
||||
|
||||
theorem sizeOf_lt_of_mem [SizeOf α] {as : Array α} (h : a ∈ as) : sizeOf a < sizeOf as := by
|
||||
cases as with | _ as =>
|
||||
cases as with | _ as
|
||||
exact Nat.lt_trans (List.sizeOf_lt_of_mem h.val) (by simp +arith)
|
||||
|
||||
theorem sizeOf_get [SizeOf α] (as : Array α) (i : Nat) (h : i < as.size) : sizeOf as[i] < sizeOf as := by
|
||||
cases as with | _ as =>
|
||||
cases as with | _ as
|
||||
simpa using Nat.lt_trans (List.sizeOf_get _ ⟨i, h⟩) (by simp +arith)
|
||||
|
||||
@[simp] theorem sizeOf_getElem [SizeOf α] (as : Array α) (i : Nat) (h : i < as.size) :
|
||||
|
||||
@@ -6,8 +6,10 @@ Authors: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.List.Control
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.List.Control
|
||||
import all Init.Data.List.Control
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.Attach
|
||||
public import Init.Data.List.Monadic
|
||||
|
||||
@@ -6,7 +6,8 @@ Authors: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.Monadic
|
||||
public import Init.Data.List.OfFn
|
||||
|
||||
@@ -7,7 +7,8 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.List.Nat.Perm
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
|
||||
public section
|
||||
|
||||
@@ -7,7 +7,7 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Vector.Basic
|
||||
public import Init.Data.Ord
|
||||
public import Init.Data.Ord.Basic
|
||||
|
||||
public section
|
||||
|
||||
|
||||
@@ -7,8 +7,10 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.OfFn
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.OfFn
|
||||
import all Init.Data.Array.OfFn
|
||||
public import Init.Data.Array.MapIdx
|
||||
public import Init.Data.Array.Zip
|
||||
public import Init.Data.List.Nat.Range
|
||||
|
||||
@@ -161,7 +161,8 @@ instance : Inhabited (Subarray α) :=
|
||||
⟨{}⟩
|
||||
|
||||
/-!
|
||||
`ForIn` and `foldlM` are implemented in `Init.Data.Slice.Array.Iterator` using the slice iterator.
|
||||
`ForIn`, `foldlM`, `foldl` and other operations are implemented in `Init.Data.Slice.Array.Iterator`
|
||||
using the slice iterator.
|
||||
-/
|
||||
|
||||
/--
|
||||
@@ -266,8 +267,8 @@ An accumulator of type `β` is constructed by starting with `init` and combining
|
||||
subarray with the current accumulator value in turn, moving from the end to the start.
|
||||
|
||||
Examples:
|
||||
* `#eval #["red", "green", "blue"].toSubarray.foldr (·.length + ·) 0 = 12`
|
||||
* `#["red", "green", "blue"].toSubarray.popFront.foldlr (·.length + ·) 0 = 9`
|
||||
* `#["red", "green", "blue"].toSubarray.foldr (·.length + ·) 0 = 12`
|
||||
* `#["red", "green", "blue"].toSubarray.popFront.foldr (·.length + ·) 0 = 9`
|
||||
-/
|
||||
@[inline]
|
||||
def foldr {α : Type u} {β : Type v} (f : α → β → β) (init : β) (as : Subarray α) : β :=
|
||||
|
||||
@@ -8,7 +8,8 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Subarray
|
||||
public import Init.Data.Array.Subarray
|
||||
import all Init.Data.Array.Subarray
|
||||
public import Init.Omega
|
||||
|
||||
public section
|
||||
|
||||
@@ -6,7 +6,8 @@ Authors: Markus Himmel
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.List.Nat.TakeDrop
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ Authors: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.TakeDrop
|
||||
public import Init.Data.List.Zip
|
||||
|
||||
@@ -118,7 +119,7 @@ theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} {i : δ} :
|
||||
theorem zipWith_eq_empty_iff {f : α → β → γ} {as : Array α} {bs : Array β} : zipWith f as bs = #[] ↔ as = #[] ∨ bs = #[] := by
|
||||
cases as <;> cases bs <;> simp
|
||||
|
||||
@[grind =]
|
||||
@[simp, grind =]
|
||||
theorem map_zipWith {δ : Type _} {f : α → β} {g : γ → δ → α} {cs : Array γ} {ds : Array δ} :
|
||||
map f (zipWith g cs ds) = zipWith (fun x y => f (g x y)) cs ds := by
|
||||
cases cs
|
||||
@@ -230,11 +231,9 @@ theorem zip_map {f : α → γ} {g : β → δ} {as : Array α} {bs : Array β}
|
||||
cases bs
|
||||
simp [List.zip_map]
|
||||
|
||||
@[grind _=_]
|
||||
theorem zip_map_left {f : α → γ} {as : Array α} {bs : Array β} :
|
||||
zip (as.map f) bs = (zip as bs).map (Prod.map f id) := by rw [← zip_map, map_id]
|
||||
|
||||
@[grind _=_]
|
||||
theorem zip_map_right {f : β → γ} {as : Array α} {bs : Array β} :
|
||||
zip as (bs.map f) = (zip as bs).map (Prod.map id f) := by rw [← zip_map, map_id]
|
||||
|
||||
@@ -354,6 +353,15 @@ theorem map_zipWithAll {δ : Type _} {f : α → β} {g : Option γ → Option
|
||||
@[deprecated zipWithAll_replicate (since := "2025-03-18")]
|
||||
abbrev zipWithAll_mkArray := @zipWithAll_replicate
|
||||
|
||||
/-! ### zipWithM -/
|
||||
|
||||
@[simp, grind =]
|
||||
theorem zipWithM_eq_mapM_id_zipWith {m : Type v → Type w} [Monad m] [LawfulMonad m] {f : α → β → m γ} {as : Array α} {bs : Array β} :
|
||||
zipWithM f as bs = mapM id (zipWith f as bs) := by
|
||||
cases as
|
||||
cases bs
|
||||
simp [List.zipWithM_toArray, ← List.zipWithM'_eq_zipWithM]
|
||||
|
||||
/-! ### unzip -/
|
||||
|
||||
@[deprecated fst_unzip (since := "2025-05-26")]
|
||||
|
||||
@@ -23,11 +23,14 @@ class PartialEquivBEq (α) [BEq α] : Prop where
|
||||
/-- Transitivity for `BEq`. If `a == b` and `b == c` then `a == c`. -/
|
||||
trans : (a : α) == b → b == c → a == c
|
||||
|
||||
instance [BEq α] [PartialEquivBEq α] : Std.Symm (α := α) (· == ·) where
|
||||
symm _ _ h := PartialEquivBEq.symm h
|
||||
|
||||
/-- `EquivBEq` says that the `BEq` implementation is an equivalence relation. -/
|
||||
class EquivBEq (α) [BEq α] : Prop extends PartialEquivBEq α, ReflBEq α
|
||||
|
||||
theorem BEq.symm [BEq α] [PartialEquivBEq α] {a b : α} : a == b → b == a :=
|
||||
PartialEquivBEq.symm
|
||||
theorem BEq.symm [BEq α] [Std.Symm (α := α) (· == ·)] {a b : α} : a == b → b == a :=
|
||||
Std.Symm.symm a b (r := (· == ·))
|
||||
|
||||
theorem BEq.comm [BEq α] [PartialEquivBEq α] {a b : α} : (a == b) = (b == a) :=
|
||||
Bool.eq_iff_iff.2 ⟨BEq.symm, BEq.symm⟩
|
||||
|
||||
@@ -9,10 +9,10 @@ prelude
|
||||
public import Init.Data.Fin.Basic
|
||||
public import Init.Data.Nat.Bitwise.Lemmas
|
||||
public import Init.Data.Nat.Power2
|
||||
public import Init.Data.Int.Bitwise
|
||||
public import Init.Data.Int.Bitwise.Basic
|
||||
public import Init.Data.BitVec.BasicAux
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
/-!
|
||||
We define the basic algebraic structure of bitvectors. We choose the `Fin` representation over
|
||||
@@ -552,7 +552,7 @@ Example:
|
||||
@[expose]
|
||||
protected def xor (x y : BitVec n) : BitVec n :=
|
||||
(x.toNat ^^^ y.toNat)#'(Nat.xor_lt_two_pow x.isLt y.isLt)
|
||||
instance : Xor (BitVec w) := ⟨.xor⟩
|
||||
instance : XorOp (BitVec w) := ⟨.xor⟩
|
||||
|
||||
/--
|
||||
Bitwise complement for bitvectors. Usually accessed via the `~~~` prefix operator.
|
||||
@@ -736,10 +736,10 @@ def twoPow (w : Nat) (i : Nat) : BitVec w := 1#w <<< i
|
||||
end bitwise
|
||||
|
||||
/-- The bitvector of width `w` that has the smallest value when interpreted as an integer. -/
|
||||
def intMin (w : Nat) := twoPow w (w - 1)
|
||||
@[expose] def intMin (w : Nat) := twoPow w (w - 1)
|
||||
|
||||
/-- The bitvector of width `w` that has the largest value when interpreted as an integer. -/
|
||||
def intMax (w : Nat) := (twoPow w (w - 1)) - 1
|
||||
@[expose] def intMax (w : Nat) := (twoPow w (w - 1)) - 1
|
||||
|
||||
/--
|
||||
Computes a hash of a bitvector, combining 64-bit words using `mixHash`.
|
||||
|
||||
@@ -6,16 +6,19 @@ Authors: Harun Khan, Abdalrhman M Mohamed, Joe Hendrix, Siddharth Bhat
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Nat.Bitwise.Basic
|
||||
public import Init.Data.Nat.Bitwise.Basic
|
||||
import all Init.Data.Nat.Bitwise.Basic
|
||||
public import Init.Data.Nat.Mod
|
||||
public import all Init.Data.Int.DivMod
|
||||
public import Init.Data.Int.DivMod
|
||||
import all Init.Data.Int.DivMod
|
||||
public import Init.Data.Int.LemmasAux
|
||||
public import all Init.Data.BitVec.Basic
|
||||
public import Init.Data.BitVec.Basic
|
||||
import all Init.Data.BitVec.Basic
|
||||
public import Init.Data.BitVec.Decidable
|
||||
public import Init.Data.BitVec.Lemmas
|
||||
public import Init.Data.BitVec.Folds
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
/-!
|
||||
# Bit blasting of bitvectors
|
||||
@@ -336,13 +339,13 @@ theorem add_eq_or_of_and_eq_zero {w : Nat} (x y : BitVec w)
|
||||
(h : x &&& y = 0#w) : x + y = x ||| y := by
|
||||
rw [add_eq_adc, adc, iunfoldr_replace (fun _ => false) (x ||| y)]
|
||||
· rfl
|
||||
· simp only [adcb, atLeastTwo, Bool.and_false, Bool.or_false, bne_false,
|
||||
· simp only [adcb, atLeastTwo, Bool.and_false, Bool.or_false, bne_false,
|
||||
Prod.mk.injEq, and_eq_false_imp]
|
||||
intros i
|
||||
intro i
|
||||
replace h : (x &&& y).getLsbD i = (0#w).getLsbD i := by rw [h]
|
||||
simp only [getLsbD_and, getLsbD_zero, and_eq_false_imp] at h
|
||||
constructor
|
||||
· intros hx
|
||||
· intro hx
|
||||
simp_all
|
||||
· by_cases hx : x.getLsbD i <;> simp_all
|
||||
|
||||
@@ -586,7 +589,6 @@ A recurrence that describes multiplication as repeated addition.
|
||||
|
||||
This function is useful for bit blasting multiplication.
|
||||
-/
|
||||
@[expose]
|
||||
def mulRec (x y : BitVec w) (s : Nat) : BitVec w :=
|
||||
let cur := if y.getLsbD s then (x <<< s) else 0
|
||||
match s with
|
||||
@@ -622,7 +624,7 @@ theorem setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow (x : BitVec w) (i
|
||||
simp [hik', hik'']
|
||||
omega
|
||||
· ext k
|
||||
simp only [and_twoPow,
|
||||
simp only [and_twoPow,
|
||||
]
|
||||
by_cases hi : x.getLsbD i <;> simp [hi] <;> omega
|
||||
|
||||
@@ -1047,7 +1049,6 @@ theorem lawful_divSubtractShift (qr : DivModState w) (h : qr.Poised args) :
|
||||
/-! ### Core division algorithm circuit -/
|
||||
|
||||
/-- A recursive definition of division for bit blasting, in terms of a shift-subtraction circuit. -/
|
||||
@[expose]
|
||||
def divRec {w : Nat} (m : Nat) (args : DivModArgs w) (qr : DivModState w) :
|
||||
DivModState w :=
|
||||
match m with
|
||||
@@ -1668,7 +1669,7 @@ private theorem neg_udiv_eq_intMin_iff_eq_intMin_eq_one_of_msb_eq_true
|
||||
{x y : BitVec w} (hx : x.msb = true) (hy : y.msb = false) :
|
||||
-x / y = intMin w ↔ (x = intMin w ∧ y = 1#w) := by
|
||||
constructor
|
||||
· intros h
|
||||
· intro h
|
||||
rcases w with _ | w; decide +revert
|
||||
have : (-x / y).msb = true := by simp [h, msb_intMin]
|
||||
rw [msb_udiv] at this
|
||||
@@ -1744,7 +1745,7 @@ theorem msb_sdiv_eq_decide {x y : BitVec w} :
|
||||
Bool.and_self, ne_zero_of_msb_true, decide_false, Bool.and_true, Bool.true_and, Bool.not_true,
|
||||
Bool.false_and, Bool.or_false, bool_to_prop]
|
||||
have : x / -y ≠ intMin (w + 1) := by
|
||||
intros h
|
||||
intro h
|
||||
have : (x / -y).msb = (intMin (w + 1)).msb := by simp only [h]
|
||||
simp only [msb_udiv, msb_intMin, show 0 < w + 1 by omega, decide_true, and_eq_true, beq_iff_eq] at this
|
||||
obtain ⟨hcontra, _⟩ := this
|
||||
@@ -1873,7 +1874,7 @@ theorem toInt_dvd_toInt_iff {x y : BitVec w} :
|
||||
y.toInt ∣ x.toInt ↔ (if x.msb then -x else x) % (if y.msb then -y else y) = 0#w := by
|
||||
constructor
|
||||
<;> by_cases hxmsb : x.msb <;> by_cases hymsb: y.msb
|
||||
<;> intros h
|
||||
<;> intro h
|
||||
<;> simp only [hxmsb, hymsb, reduceIte, false_eq_true, toNat_eq, toNat_umod, toNat_ofNat,
|
||||
zero_mod, toInt_eq_neg_toNat_neg_of_msb_true, Int.dvd_neg, Int.neg_dvd,
|
||||
toInt_eq_toNat_of_msb] at h
|
||||
@@ -1944,7 +1945,7 @@ The remainder for `srem`, i.e. division with rounding to zero is negative
|
||||
iff `x` is negative and `y` does not divide `x`.
|
||||
|
||||
We can eventually build fast circuits for the divisibility test `x.srem y = 0`.
|
||||
-/
|
||||
-/
|
||||
theorem msb_srem {x y : BitVec w} : (x.srem y).msb =
|
||||
(x.msb && decide (x.srem y ≠ 0)) := by
|
||||
rw [msb_eq_toInt]
|
||||
@@ -2143,7 +2144,7 @@ theorem add_shiftLeft_eq_or_shiftLeft {x y : BitVec w} :
|
||||
ext i hi
|
||||
simp only [shiftLeft_eq', getElem_and, getElem_shiftLeft, getElem_zero, and_eq_false_imp,
|
||||
not_eq_eq_eq_not, Bool.not_true, decide_eq_false_iff_not, Nat.not_lt]
|
||||
intros hxi hxval
|
||||
intro hxi hxval
|
||||
have : 2^i ≤ x.toNat := two_pow_le_toNat_of_getElem_eq_true hi hxi
|
||||
have : i < 2^i := by exact Nat.lt_two_pow_self
|
||||
omega
|
||||
@@ -2154,4 +2155,238 @@ theorem shiftLeft_add_eq_shiftLeft_or {x y : BitVec w} :
|
||||
(y <<< x) + x = (y <<< x) ||| x := by
|
||||
rw [BitVec.add_comm, add_shiftLeft_eq_or_shiftLeft, or_comm]
|
||||
|
||||
/- ### Fast Circuit For Unsigned Overflow Detection -/
|
||||
|
||||
/-!
|
||||
# Note [Fast Unsigned Multiplication Overflow Detection]
|
||||
|
||||
The fast unsigned multiplication overflow detection circuit is described in
|
||||
`Efficient integer multiplication overflow detection circuits` (https://ieeexplore.ieee.org/abstract/document/987767).
|
||||
With this circuit, the computation of the overflow flag for the unsigned multiplication of
|
||||
two bitvectors `x` and `y` with bitwidth `w` requires:
|
||||
· extending the operands by `1` bit and performing the multiplication with the extended operands,
|
||||
· computing the preliminary overflow flag, which describes whether `x` and `y` together have at most
|
||||
`w - 2` leading zeros.
|
||||
If the most significant bit of the extended operands' multiplication is `true` or if the
|
||||
preliminary overflow flag is `true`, overflow happens.
|
||||
In particular, the conditions check two different cases:
|
||||
· if the most significant bit of the extended operands' multiplication is `true`, the result of the
|
||||
multiplication 2 ^ w ≤ x.toNat * y.toNat < 2 ^ (w + 1),
|
||||
· if the preliminary flag is true, then 2 ^ (w + 1) ≤ x.toNat * y.toNat.
|
||||
|
||||
The computation of the preliminary overflow flag `resRec` relies on two quantities:
|
||||
· `uppcRec`: the unsigned parallel prefix circuit for the bits until a certain `i`,
|
||||
· `aandRec`: the conjunction between the parallel prefix circuit at of the first operand until a certain `i`
|
||||
and the `i`-th bit in the second operand.
|
||||
-/
|
||||
|
||||
/--
|
||||
`uppcRec` is the unsigned parallel prefix, `x.uppcRec s = true` iff `x.toNat` is greater or equal
|
||||
than `2 ^ (w - 1 - (s - 1))`.
|
||||
-/
|
||||
def uppcRec {w} (x : BitVec w) (s : Nat) (hs : s < w) : Bool :=
|
||||
match s with
|
||||
| 0 => x.msb
|
||||
| i + 1 => x[w - 1 - i] || uppcRec x i (by omega)
|
||||
|
||||
/-- The unsigned parallel prefix of `x` at `s` is `true` if and only if x interpreted
|
||||
as a natural number is greater or equal than `2 ^ (w - 1 - (s - 1))`. -/
|
||||
@[simp]
|
||||
theorem uppcRec_true_iff (x : BitVec w) (s : Nat) (h : s < w) :
|
||||
uppcRec x s h ↔ 2 ^ (w - 1 - (s - 1)) ≤ x.toNat := by
|
||||
rcases w with _|w
|
||||
· omega
|
||||
· induction s
|
||||
· case succ.zero =>
|
||||
simp only [uppcRec, msb_eq_true_iff_two_mul_ge, Nat.pow_add, Nat.pow_one,
|
||||
Nat.mul_comm (2 ^ w) 2, ge_iff_le, Nat.add_one_sub_one, zero_le, Nat.sub_eq_zero_of_le,
|
||||
Nat.sub_zero]
|
||||
apply Nat.mul_le_mul_left_iff (by omega)
|
||||
· case succ.succ s ihs =>
|
||||
simp only [uppcRec, or_eq_true, ihs, Nat.add_one_sub_one]
|
||||
have := Nat.pow_le_pow_of_le (a := 2) ( n := (w - s)) (m := (w - (s - 1))) (by omega) (by omega)
|
||||
constructor
|
||||
· intro h'
|
||||
rcases h' with h'|h'
|
||||
· apply ge_two_pow_of_testBit h'
|
||||
· omega
|
||||
· intro h'
|
||||
by_cases hbit: x[w - s]
|
||||
· simp [hbit]
|
||||
· have := BitVec.le_toNat_iff_getLsbD_eq_true (x := x) (i := w - s) (by omega)
|
||||
simp only [h', true_iff] at this
|
||||
obtain ⟨k, hk⟩ := this
|
||||
by_cases hwk : w - s + k < w + 1
|
||||
· by_cases hk' : 0 < k
|
||||
· have hle := ge_two_pow_of_testBit hk
|
||||
have hpowle := Nat.pow_le_pow_of_le (a := 2) ( n := (w - (s - 1))) (m := (w - s + k)) (by omega) (by omega)
|
||||
omega
|
||||
· rw [getLsbD_eq_getElem (by omega)] at hk
|
||||
simp [hbit, show k = 0 by omega] at hk
|
||||
· simp_all
|
||||
|
||||
/--
|
||||
Conjunction for fast umulOverflow circuit
|
||||
-/
|
||||
def aandRec (x y : BitVec w) (s : Nat) (hs : s < w) : Bool :=
|
||||
y[s] && uppcRec x s (by omega)
|
||||
|
||||
|
||||
/--
|
||||
Preliminary overflow flag for fast umulOverflow circuit as introduced in
|
||||
`Efficient integer multiplication overflow detection circuits` (https://ieeexplore.ieee.org/abstract/document/987767).
|
||||
-/
|
||||
def resRec (x y : BitVec w) (s : Nat) (hs : s < w) (hslt : 0 < s) : Bool :=
|
||||
match hs0 : s with
|
||||
| 0 => by omega
|
||||
| s' + 1 =>
|
||||
match hs' : s' with
|
||||
| 0 => aandRec x y 1 (by omega)
|
||||
| s'' + 1 =>
|
||||
(resRec x y s' (by omega) (by omega)) || (aandRec x y s (by omega))
|
||||
|
||||
/-- The preliminary overflow flag is true for a certain `s` if and only if the conjunction returns true at
|
||||
any `k` smaller than or equal to `s`. -/
|
||||
theorem resRec_true_iff (x y : BitVec w) (s : Nat) (hs : s < w) (hs' : 0 < s) :
|
||||
resRec x y s hs hs' = true ↔ ∃ (k : Nat), ∃ (h : k ≤ s), ∃ (_ : 0 < k), aandRec x y k (by omega) := by
|
||||
unfold resRec
|
||||
rcases s with _|s
|
||||
· omega
|
||||
· rcases s
|
||||
· case zero =>
|
||||
constructor
|
||||
· intro ha
|
||||
exists 1, by omega, by omega
|
||||
· intro hr
|
||||
obtain ⟨k, hk, hk', hk''⟩ := hr
|
||||
simp only [show k = 1 by omega] at hk''
|
||||
exact hk''
|
||||
· case succ s =>
|
||||
induction s
|
||||
· case zero =>
|
||||
unfold resRec
|
||||
simp only [Nat.zero_add, Nat.reduceAdd, or_eq_true]
|
||||
constructor
|
||||
· intro h
|
||||
rcases h with h|h
|
||||
· exists 1, by omega, by omega
|
||||
· exists 2, by omega, by omega
|
||||
· intro h
|
||||
obtain ⟨k, hk, hk', hk''⟩ := h
|
||||
have h : k = 1 ∨ k = 2 := by omega
|
||||
rcases h with h|h
|
||||
<;> simp only [h] at hk''
|
||||
<;> simp [hk'']
|
||||
· case succ s ihs =>
|
||||
specialize ihs (by omega) (by omega)
|
||||
unfold resRec
|
||||
simp only [or_eq_true, ihs]
|
||||
constructor
|
||||
· intro h
|
||||
rcases h with h|h
|
||||
· obtain ⟨k, hk, hk', hk''⟩ := h
|
||||
exists k, by omega, by omega
|
||||
· exists s + 1 + 1 + 1, by omega, by omega
|
||||
· intro h
|
||||
obtain ⟨k, hk, hk', hk''⟩ := h
|
||||
by_cases h' : x.aandRec y (s + 1 + 1 + 1) (by omega) = true
|
||||
· simp [h']
|
||||
· simp only [h', false_eq_true, _root_.or_false]
|
||||
by_cases h'' : k ≤ s + 1 + 1
|
||||
· exists k, h'', by omega
|
||||
· have : k = s + 1 + 1 + 1 := by omega
|
||||
simp_all
|
||||
|
||||
/-- If the sum of the leading zeroes of two bitvecs with bitwidth `w` is less than or equal to
|
||||
(`w - 2`), then the preliminary overflow flag is true and their unsigned multiplication overflows.
|
||||
The explanation is in `Efficient integer multiplication overflow detection circuits`
|
||||
https://ieeexplore.ieee.org/abstract/document/987767
|
||||
-/
|
||||
theorem resRec_of_clz_le {x y : BitVec w} (hw : 1 < w) (hx : x ≠ 0#w) (hy : y ≠ 0#w):
|
||||
(clz x).toNat + (clz y).toNat ≤ w - 2 → resRec x y (w - 1) (by omega) (by omega) := by
|
||||
intro h
|
||||
rw [resRec_true_iff]
|
||||
exists (w - 1 - y.clz.toNat), by omega, by omega
|
||||
simp only [aandRec]
|
||||
by_cases hw0 : w - 1 - y.clz.toNat = 0
|
||||
· have := clz_lt_iff_ne_zero.mpr (by omega)
|
||||
omega
|
||||
· simp only [and_eq_true, getLsbD_true_clz_of_ne_zero (x := y) (by omega) (by omega),
|
||||
getElem_of_getLsbD_eq_true, uppcRec_true_iff,
|
||||
show w - 1 - (w - 1 - y.clz.toNat - 1) = y.clz.toNat + 1 by omega, _root_.true_and]
|
||||
exact Nat.le_trans (Nat.pow_le_pow_of_le (a := 2) (n := y.clz.toNat + 1)
|
||||
(m := w - 1 - x.clz.toNat) (by omega) (by omega))
|
||||
(BitVec.two_pow_sub_clz_le_toNat_of_ne_zero (x := x) (by omega) (by omega))
|
||||
|
||||
/--
|
||||
Complete fast overflow detection circuit for unsigned multiplication.
|
||||
-/
|
||||
theorem fastUmulOverflow (x y : BitVec w) :
|
||||
umulOverflow x y = if hw : w ≤ 1 then false
|
||||
else (setWidth (w + 1) x * setWidth (w + 1) y)[w] || x.resRec y (w - 1) (by omega) (by omega) := by
|
||||
rcases w with _|_|w
|
||||
· simp [of_length_zero, umulOverflow]
|
||||
· have hx : x.toNat ≤ 1 := by omega
|
||||
have hy : y.toNat ≤ 1 := by omega
|
||||
have := Nat.mul_le_mul (n₁ := x.toNat) (m₁ := y.toNat) (n₂ := 1) (m₂ := 1) hx hy
|
||||
simp [umulOverflow]
|
||||
omega
|
||||
· by_cases h : umulOverflow x y
|
||||
· simp only [h, Nat.reduceLeDiff, reduceDIte, Nat.add_one_sub_one, true_eq, or_eq_true]
|
||||
simp only [umulOverflow, ge_iff_le, decide_eq_true_eq] at h
|
||||
by_cases h' : x.toNat * y.toNat < 2 ^ (w + 1 + 1 + 1)
|
||||
· have hlt := BitVec.getElem_eq_true_of_lt_of_le
|
||||
(x := (setWidth (w + 1 + 1 + 1) x * setWidth (w + 1 + 1 + 1) y))
|
||||
(k := w + 1 + 1) (by omega)
|
||||
simp only [toNat_mul, toNat_setWidth, Nat.lt_add_one, toNat_mod_cancel_of_lt,
|
||||
Nat.mod_eq_of_lt (a := x.toNat * y.toNat) (b := 2 ^ (w + 1 + 1 + 1)) (by omega), h', h,
|
||||
forall_const] at hlt
|
||||
simp [hlt]
|
||||
· by_cases hsw : (setWidth (w + 1 + 1 + 1) x * setWidth (w + 1 + 1 + 1) y)[w + 1 + 1] = true
|
||||
· simp [hsw]
|
||||
· simp only [hsw, false_eq_true, _root_.false_or]
|
||||
have := Nat.two_pow_pos (w := w + 1 + 1)
|
||||
have hltx := BitVec.toNat_lt_two_pow_sub_clz (x := x)
|
||||
have hlty := BitVec.toNat_lt_two_pow_sub_clz (x := y)
|
||||
have := Nat.mul_ne_zero_iff (m := y.toNat) (n := x.toNat)
|
||||
simp only [ne_eq, show ¬x.toNat * y.toNat = 0 by omega, not_false_eq_true,
|
||||
true_iff] at this
|
||||
obtain ⟨hxz,hyz⟩ := this
|
||||
apply resRec_of_clz_le (x := x) (y := y) (by omega) (by simp [toNat_eq]; exact hxz) (by simp [toNat_eq]; exact hyz)
|
||||
by_cases hzxy : x.clz.toNat + y.clz.toNat ≤ w
|
||||
· omega
|
||||
· by_cases heq : w + 1 - y.clz.toNat = 0
|
||||
· by_cases heq' : w + 1 + 1 - y.clz.toNat = 0
|
||||
· simp [heq', hyz] at hlty
|
||||
· simp only [show y.clz.toNat = w + 1 by omega, Nat.add_sub_cancel_left,
|
||||
Nat.pow_one] at hlty
|
||||
simp only [show y.toNat = 1 by omega, Nat.mul_one, Nat.not_lt] at h'
|
||||
omega
|
||||
· by_cases w + 1 < y.clz.toNat
|
||||
· omega
|
||||
· simp only [Nat.not_lt] at h'
|
||||
have := Nat.mul_lt_mul'' (a := x.toNat) (b := y.toNat) (c := 2 ^ (w + 1 + 1 - x.clz.toNat)) (d := 2 ^ (w + 1 + 1 - y.clz.toNat)) hltx hlty
|
||||
simp only [← Nat.pow_add] at this
|
||||
have := Nat.pow_le_pow_of_le (a := 2) (n := w + 1 + 1 - x.clz.toNat + (w + 1 + 1 - y.clz.toNat)) (m := w + 1 + 1 + 1)
|
||||
(by omega) (by omega)
|
||||
omega
|
||||
· simp only [h, Nat.reduceLeDiff, reduceDIte, Nat.add_one_sub_one, false_eq, or_eq_false_iff]
|
||||
simp only [umulOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h
|
||||
and_intros
|
||||
· simp only [← getLsbD_eq_getElem, getLsbD_eq_getMsbD, Nat.lt_add_one, decide_true,
|
||||
Nat.add_one_sub_one, Nat.sub_self, ← msb_eq_getMsbD_zero, Bool.true_and,
|
||||
msb_eq_false_iff_two_mul_lt, toNat_mul, toNat_setWidth, toNat_mod_cancel_of_lt]
|
||||
rw [Nat.mod_eq_of_lt (by omega),Nat.pow_add (m := w + 1 + 1) (n := 1)]
|
||||
simp [Nat.mul_comm 2 (x.toNat * y.toNat), h]
|
||||
· apply Classical.byContradiction
|
||||
intro hcontra
|
||||
simp only [not_eq_false, resRec_true_iff, exists_prop, exists_and_left] at hcontra
|
||||
obtain ⟨k,hk,hk',hk''⟩ := hcontra
|
||||
simp only [aandRec, and_eq_true, uppcRec_true_iff, Nat.add_one_sub_one] at hk''
|
||||
obtain ⟨hky, hkx⟩ := hk''
|
||||
have hyle := two_pow_le_toNat_of_getElem_eq_true (x := y) (i := k) (by omega) hky
|
||||
have := Nat.mul_le_mul (n₁ := 2 ^ (w + 1 - (k - 1))) (m₁ := 2 ^ k) (n₂ := x.toNat) (m₂ := y.toNat) hkx hyle
|
||||
simp [← Nat.pow_add, show w + 1 - (k - 1) + k = w + 1 + 1 by omega] at this
|
||||
omega
|
||||
|
||||
end BitVec
|
||||
|
||||
@@ -6,7 +6,9 @@ Authors: Joe Hendrix, Harun Khan, Alex Keizer, Abdalrhman M Mohamed, Siddharth B
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.BitVec.Basic
|
||||
public import Init.Data.BitVec.Basic
|
||||
import all Init.Data.BitVec.Basic
|
||||
import Init.Data.Int.Bitwise.Lemmas
|
||||
|
||||
public section
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ Authors: Joe Hendrix, Harun Khan
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.BitVec.Basic
|
||||
public import Init.Data.BitVec.Basic
|
||||
import all Init.Data.BitVec.Basic
|
||||
public import Init.Data.BitVec.Lemmas
|
||||
public import Init.Data.Nat.Lemmas
|
||||
public import Init.Data.Fin.Iterate
|
||||
|
||||
@@ -7,8 +7,10 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Bool
|
||||
public import all Init.Data.BitVec.Basic
|
||||
public import all Init.Data.BitVec.BasicAux
|
||||
public import Init.Data.BitVec.Basic
|
||||
import all Init.Data.BitVec.Basic
|
||||
public import Init.Data.BitVec.BasicAux
|
||||
import all Init.Data.BitVec.BasicAux
|
||||
public import Init.Data.Fin.Lemmas
|
||||
public import Init.Data.Nat.Lemmas
|
||||
public import Init.Data.Nat.Div.Lemmas
|
||||
@@ -19,9 +21,12 @@ public import Init.Data.Int.LemmasAux
|
||||
public import Init.Data.Int.Pow
|
||||
public import Init.Data.Int.LemmasAux
|
||||
public import Init.Data.BitVec.Bootstrap
|
||||
public import Init.Data.Order.Factories
|
||||
|
||||
public section
|
||||
|
||||
open Std
|
||||
|
||||
set_option linter.missingDocs true
|
||||
|
||||
namespace BitVec
|
||||
@@ -238,11 +243,11 @@ theorem eq_of_getLsbD_eq_iff {w : Nat} {x y : BitVec w} :
|
||||
x = y ↔ ∀ (i : Nat), i < w → x.getLsbD i = y.getLsbD i := by
|
||||
have iff := @BitVec.eq_of_getElem_eq_iff w x y
|
||||
constructor
|
||||
· intros heq i lt
|
||||
· intro heq i lt
|
||||
have hext := iff.mp heq i lt
|
||||
simp only [← getLsbD_eq_getElem] at hext
|
||||
exact hext
|
||||
· intros heq
|
||||
· intro heq
|
||||
exact iff.mpr heq
|
||||
|
||||
theorem eq_of_getMsbD_eq {x y : BitVec w}
|
||||
@@ -505,6 +510,18 @@ theorem getElem_ofBool {b : Bool} {h : i < 1}: (ofBool b)[i] = b := by
|
||||
@[simp] theorem zero_eq_one_iff (w : Nat) : (0#w = 1#w) ↔ (w = 0) := by
|
||||
rw [← one_eq_zero_iff, eq_comm]
|
||||
|
||||
/-- A bitvector is equal to 0#w if and only if all bits are `false` -/
|
||||
theorem zero_iff_eq_false {x: BitVec w} :
|
||||
x = 0#w ↔ ∀ i, x.getLsbD i = false := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· constructor
|
||||
· intro hzero
|
||||
simp [hzero]
|
||||
· intro hfalse
|
||||
ext j hj
|
||||
simp [← getLsbD_eq_getElem, hfalse]
|
||||
|
||||
/-! ### msb -/
|
||||
|
||||
@[simp] theorem msb_zero : (0#w).msb = false := by simp [BitVec.msb, getMsbD]
|
||||
@@ -702,7 +719,7 @@ theorem eq_zero_or_eq_one (a : BitVec 1) : a = 0#1 ∨ a = 1#1 := by
|
||||
have acases : a = 0 ∨ a = 1 := by omega
|
||||
rcases acases with ⟨rfl | rfl⟩
|
||||
· simp
|
||||
· case inr h =>
|
||||
case inr h =>
|
||||
subst h
|
||||
simp
|
||||
|
||||
@@ -818,14 +835,14 @@ its most significant bit is true.
|
||||
theorem slt_zero_iff_msb_cond {x : BitVec w} : x.slt 0#w ↔ x.msb = true := by
|
||||
have := toInt_eq_msb_cond x
|
||||
constructor
|
||||
· intros h
|
||||
· intro h
|
||||
apply Classical.byContradiction
|
||||
intros hmsb
|
||||
intro hmsb
|
||||
simp only [Bool.not_eq_true] at hmsb
|
||||
simp only [hmsb, Bool.false_eq_true, ↓reduceIte] at this
|
||||
simp only [BitVec.slt, toInt_zero, decide_eq_true_eq] at h
|
||||
omega /- Can't have `x.toInt` which is equal to `x.toNat` be strictly less than zero -/
|
||||
· intros h
|
||||
· intro h
|
||||
simp only [h, ↓reduceIte] at this
|
||||
simp only [BitVec.slt, this, toInt_zero, decide_eq_true_eq]
|
||||
omega
|
||||
@@ -1393,7 +1410,7 @@ theorem or_eq_zero_iff {x y : BitVec w} : (x ||| y) = 0#w ↔ x = 0#w ∧ y = 0#
|
||||
· intro h
|
||||
constructor
|
||||
all_goals
|
||||
· ext i ih
|
||||
ext i ih
|
||||
have := BitVec.eq_of_getElem_eq_iff.mp h i ih
|
||||
simp only [getElem_or, getElem_zero, Bool.or_eq_false_iff] at this
|
||||
simp [this]
|
||||
@@ -1493,7 +1510,7 @@ theorem and_eq_allOnes_iff {x y : BitVec w} :
|
||||
· intro h
|
||||
constructor
|
||||
all_goals
|
||||
· ext i ih
|
||||
ext i ih
|
||||
have := BitVec.eq_of_getElem_eq_iff.mp h i ih
|
||||
simp only [getElem_and, getElem_allOnes, Bool.and_eq_true] at this
|
||||
simp [this]
|
||||
@@ -2094,7 +2111,7 @@ theorem toInt_ushiftRight_of_lt {x : BitVec w} {n : Nat} (hn : 0 < n) :
|
||||
(x >>> n).toInt = x.toNat >>> n := by
|
||||
rw [toInt_eq_toNat_cond]
|
||||
simp only [toNat_ushiftRight, ite_eq_left_iff, Nat.not_lt]
|
||||
intros h
|
||||
intro h
|
||||
by_cases hn : n ≤ w
|
||||
· have h1 := Nat.mul_lt_mul_of_pos_left (toNat_ushiftRight_lt x n hn) Nat.two_pos
|
||||
simp only [toNat_ushiftRight, Nat.zero_lt_succ, Nat.mul_lt_mul_left] at h1
|
||||
@@ -2189,8 +2206,7 @@ theorem sshiftRight_eq_of_msb_false {x : BitVec w} {s : Nat} (h : x.msb = false)
|
||||
apply BitVec.eq_of_toNat_eq
|
||||
rw [BitVec.sshiftRight_eq, BitVec.toInt_eq_toNat_cond]
|
||||
have hxbound : 2 * x.toNat < 2 ^ w := BitVec.msb_eq_false_iff_two_mul_lt.mp h
|
||||
simp only [hxbound, ↓reduceIte, Int.natCast_shiftRight, ofInt_natCast,
|
||||
toNat_ofNat, toNat_ushiftRight]
|
||||
simp only [hxbound, ↓reduceIte, toNat_ushiftRight]
|
||||
replace hxbound : x.toNat >>> s < 2 ^ w := by
|
||||
rw [Nat.shiftRight_eq_div_pow]
|
||||
exact Nat.lt_of_le_of_lt (Nat.div_le_self ..) x.isLt
|
||||
@@ -2232,7 +2248,7 @@ theorem getLsbD_sshiftRight (x : BitVec w) (s i : Nat) :
|
||||
omega
|
||||
· simp only [hi, decide_false, Bool.not_false, Bool.true_and, Bool.eq_and_self,
|
||||
decide_eq_true_eq]
|
||||
intros hlsb
|
||||
intro hlsb
|
||||
apply BitVec.lt_of_getLsbD hlsb
|
||||
· by_cases hi : i ≥ w
|
||||
· simp [hi]
|
||||
@@ -2286,7 +2302,7 @@ theorem msb_sshiftRight {n : Nat} {x : BitVec w} :
|
||||
· simp [hw₀]
|
||||
· simp only [show ¬(w ≤ w - 1) by omega, decide_false, Bool.not_false, Bool.true_and,
|
||||
ite_eq_right_iff]
|
||||
intros h
|
||||
intro h
|
||||
simp [show n = 0 by omega]
|
||||
|
||||
@[simp] theorem sshiftRight_zero {x : BitVec w} : x.sshiftRight 0 = x := by
|
||||
@@ -2774,7 +2790,7 @@ theorem toInt_append {x : BitVec n} {y : BitVec m} :
|
||||
(x ++ 0#m).toInt = (2 ^ m) * x.toInt := by
|
||||
simp only [toInt_append, beq_iff_eq, toInt_zero, toNat_ofNat, Nat.zero_mod, Int.cast_ofNat_Int, Int.add_zero,
|
||||
ite_eq_right_iff]
|
||||
intros h
|
||||
intro h
|
||||
subst h
|
||||
simp [BitVec.eq_nil x]
|
||||
|
||||
@@ -2958,7 +2974,7 @@ theorem extractLsb'_append_extractLsb'_eq_extractLsb' {x : BitVec w} (h : start
|
||||
ext i h
|
||||
simp only [getElem_append, getElem_extractLsb', dite_eq_ite, getElem_cast, ite_eq_left_iff,
|
||||
Nat.not_lt]
|
||||
intros hi
|
||||
intro hi
|
||||
congr 1
|
||||
omega
|
||||
|
||||
@@ -2985,7 +3001,7 @@ theorem signExtend_eq_append_extractLsb' {w v : Nat} {x : BitVec w} :
|
||||
· simp only [hx, signExtend_eq_setWidth_of_msb_false, getElem_setWidth, Bool.false_eq_true,
|
||||
↓reduceIte, getElem_append, getElem_extractLsb', Nat.zero_add, getElem_zero, dite_eq_ite,
|
||||
Bool.if_false_right, Bool.eq_and_self, decide_eq_true_eq]
|
||||
intros hi
|
||||
intro hi
|
||||
have hw : i < w := lt_of_getLsbD hi
|
||||
omega
|
||||
· simp [signExtend_eq_not_setWidth_not_of_msb_true hx, getElem_append, Nat.lt_min, hi]
|
||||
@@ -3006,7 +3022,7 @@ which performs a case analysis on the start index, length, and the lengths of `x
|
||||
· If the start index is entirely contained in the `xlo` bitvector, then grab the bits from `xlo`.
|
||||
· If the start index is split between the two bitvectors,
|
||||
then append `(w - start)` bits from `xlo` with `(len - (w - start))` bits from xhi.
|
||||
Diagramatically:
|
||||
Diagrammatically:
|
||||
```
|
||||
xhi xlo
|
||||
(<---------------------](<-------w--------]
|
||||
@@ -3033,7 +3049,7 @@ theorem extractLsb'_append_eq_ite {v w} {xhi : BitVec v} {xlo : BitVec w} {start
|
||||
· simp only [hlen, ↓reduceDIte]
|
||||
ext i hi
|
||||
simp only [getElem_extractLsb', getLsbD_append, ite_eq_left_iff, Nat.not_lt]
|
||||
intros hcontra
|
||||
intro hcontra
|
||||
omega
|
||||
· simp only [hlen, ↓reduceDIte]
|
||||
ext i hi
|
||||
@@ -3480,7 +3496,7 @@ theorem toInt_sub_toInt_lt_twoPow_iff {x y : BitVec w} :
|
||||
have := two_mul_toInt_lt (x := y)
|
||||
simp only [Nat.add_one_sub_one]
|
||||
constructor
|
||||
· intros h
|
||||
· intro h
|
||||
rw_mod_cast [← Int.add_bmod_right, Int.bmod_eq_of_le]
|
||||
<;> omega
|
||||
· have := Int.bmod_neg_iff (x := x.toInt - y.toInt) (m := 2 ^ (w + 1))
|
||||
@@ -3496,7 +3512,7 @@ theorem twoPow_le_toInt_sub_toInt_iff {x y : BitVec w} :
|
||||
have := le_two_mul_toInt (x := y); have := two_mul_toInt_lt (x := y)
|
||||
simp only [Nat.add_one_sub_one]
|
||||
constructor
|
||||
· intros h
|
||||
· intro h
|
||||
simp only [show 0 ≤ x.toInt by omega, show y.toInt < 0 by omega, _root_.true_and]
|
||||
rw_mod_cast [← Int.sub_bmod_right, Int.bmod_eq_of_le (by omega) (by omega)]
|
||||
omega
|
||||
@@ -4015,6 +4031,16 @@ protected theorem ne_of_lt {x y : BitVec n} : x < y → x ≠ y := by
|
||||
simp only [lt_def, ne_eq, toNat_eq]
|
||||
apply Nat.ne_of_lt
|
||||
|
||||
instance instIsLinearOrder : IsLinearOrder (BitVec n) := by
|
||||
apply IsLinearOrder.of_le
|
||||
case le_antisymm => constructor; apply BitVec.le_antisymm
|
||||
case le_trans => constructor; apply BitVec.le_trans
|
||||
case le_total => constructor; apply BitVec.le_total
|
||||
|
||||
instance instLawfulOrderLT : LawfulOrderLT (BitVec n) := by
|
||||
apply LawfulOrderLT.of_le
|
||||
simpa using fun _ _ => BitVec.lt_asymm
|
||||
|
||||
protected theorem umod_lt (x : BitVec n) {y : BitVec n} : 0 < y → x % y < y := by
|
||||
simp only [ofNat_eq_ofNat, lt_def, toNat_ofNat, Nat.zero_mod]
|
||||
apply Nat.mod_lt
|
||||
@@ -4419,8 +4445,8 @@ theorem neg_one_ediv_toInt_eq {w : Nat} {y : BitVec w} :
|
||||
rcases w with _|_|w
|
||||
· simp [of_length_zero]
|
||||
· cases eq_zero_or_eq_one y
|
||||
· case _ h => simp [h]
|
||||
· case _ h => simp [h]
|
||||
case _ h => simp [h]
|
||||
case _ h => simp [h]
|
||||
· by_cases 0 < y.toInt
|
||||
· simp [Int.sign_eq_one_of_pos (a := y.toInt) (by omega), Int.neg_one_ediv]
|
||||
omega
|
||||
@@ -5138,7 +5164,7 @@ theorem setWidth_setWidth_succ_eq_setWidth_setWidth_of_getLsbD_false
|
||||
|
||||
/--
|
||||
When the `(i+1)`th bit of `x` is true,
|
||||
keeping the lower `(i + 1)` bits of `x` equalsk eeping the lower `i` bits
|
||||
keeping the lower `(i + 1)` bits of `x` equals keeping the lower `i` bits
|
||||
and then performing bitwise-or with `twoPow i = (1 << i)`,
|
||||
-/
|
||||
theorem setWidth_setWidth_succ_eq_setWidth_setWidth_or_twoPow_of_getLsbD_true
|
||||
@@ -5753,40 +5779,6 @@ theorem msb_replicate {n w : Nat} {x : BitVec w} :
|
||||
simp only [BitVec.msb, getMsbD_replicate, Nat.zero_mod]
|
||||
cases n <;> cases w <;> simp
|
||||
|
||||
/-! ### Count leading zeros -/
|
||||
|
||||
theorem clzAuxRec_zero (x : BitVec w) :
|
||||
x.clzAuxRec 0 = if x.getLsbD 0 then BitVec.ofNat w (w - 1) else BitVec.ofNat w w := by rfl
|
||||
|
||||
theorem clzAuxRec_succ (x : BitVec w) :
|
||||
x.clzAuxRec (n + 1) = if x.getLsbD (n + 1) then BitVec.ofNat w (w - 1 - (n + 1)) else BitVec.clzAuxRec x n := by rfl
|
||||
|
||||
theorem clzAuxRec_eq_clzAuxRec_of_le (x : BitVec w) (h : w - 1 ≤ n) :
|
||||
x.clzAuxRec n = x.clzAuxRec (w - 1) := by
|
||||
let k := n - (w - 1)
|
||||
rw [show n = (w - 1) + k by omega]
|
||||
induction k
|
||||
· case zero => simp
|
||||
· case succ k ihk =>
|
||||
simp [show w - 1 + (k + 1) = (w - 1 + k) + 1 by omega, clzAuxRec_succ, ihk,
|
||||
show x.getLsbD (w - 1 + k + 1) = false by simp only [show w ≤ w - 1 + k + 1 by omega, getLsbD_of_ge]]
|
||||
|
||||
theorem clzAuxRec_eq_clzAuxRec_of_getLsbD_false {x : BitVec w} (h : ∀ i, n < i → x.getLsbD i = false) :
|
||||
x.clzAuxRec n = x.clzAuxRec (n + k) := by
|
||||
induction k
|
||||
· case zero => simp
|
||||
· case succ k ihk =>
|
||||
simp only [show n + (k + 1) = (n + k) + 1 by omega, clzAuxRec_succ]
|
||||
by_cases hxn : x.getLsbD (n + k + 1)
|
||||
· have : ¬ ∀ (i : Nat), n < i → x.getLsbD i = false := by
|
||||
simp only [Classical.not_forall, Bool.not_eq_false]
|
||||
exists n + k + 1
|
||||
simp [show n < n + k + 1 by omega, hxn]
|
||||
contradiction
|
||||
· simp only [hxn, Bool.false_eq_true, ↓reduceIte]
|
||||
exact ihk
|
||||
|
||||
|
||||
/-! ### Inequalities (le / lt) -/
|
||||
|
||||
theorem ule_eq_not_ult (x y : BitVec w) : x.ule y = !y.ult x := by
|
||||
@@ -5835,6 +5827,362 @@ theorem sle_eq_ule {x y : BitVec w} : x.sle y = (x.msb != y.msb ^^ x.ule y) := b
|
||||
theorem sle_eq_ule_of_msb_eq {x y : BitVec w} (h : x.msb = y.msb) : x.sle y = x.ule y := by
|
||||
simp [BitVec.sle_eq_ule, h]
|
||||
|
||||
/-- A bitvector interpreted as a natural number is greater than or equal to `2 ^ i` if and only if
|
||||
there exists at least one bit with `true` value at position `i` or higher. -/
|
||||
theorem le_toNat_iff_getLsbD_eq_true {x : BitVec w} (hi : i < w ) :
|
||||
(2 ^ i ≤ x.toNat) ↔ (∃ k, x.getLsbD (i + k) = true) := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· constructor
|
||||
· intro hle
|
||||
apply Classical.byContradiction
|
||||
intros hcontra
|
||||
let x' := setWidth (i + 1) x
|
||||
have hx' : setWidth (i + 1) x = x' := by rfl
|
||||
have hcast : w - i + (i + 1) = w + 1 := by omega
|
||||
simp only [not_exists, Bool.not_eq_true] at hcontra
|
||||
have hx'' : x = BitVec.cast hcast (0#(w - i) ++ x') := by
|
||||
ext j
|
||||
by_cases hj : j < i + 1
|
||||
· simp only [← hx', getElem_cast, getElem_append, hj, reduceDIte, getElem_setWidth]
|
||||
rw [getLsbD_eq_getElem]
|
||||
· simp only [getElem_cast, getElem_append, hj, reduceDIte, getElem_zero]
|
||||
let j' := j - i
|
||||
simp only [show j = i + j' by omega]
|
||||
apply hcontra
|
||||
have : x'.toNat < 2 ^ i := by
|
||||
apply Nat.lt_pow_two_of_testBit (n := i) x'.toNat
|
||||
intro j hj
|
||||
let j' := j - i
|
||||
specialize hcontra j'
|
||||
have : x'.getLsbD (i + j') = x.getLsbD (i + j') := by
|
||||
subst x'
|
||||
simp [hcontra]
|
||||
simp [show j = i + j' by omega, testBit_toNat, this, hcontra]
|
||||
have : x'.toNat = x.toNat := by
|
||||
have := BitVec.setWidth_eq_append (w := (w + 1)) (v := i + 1) (x := x')
|
||||
specialize this (by omega)
|
||||
rw [toNat_eq, toNat_setWidth, Nat.mod_eq_of_lt (by omega)] at this
|
||||
simp [hx'']
|
||||
omega
|
||||
· intro h
|
||||
obtain ⟨k, hk⟩ := h
|
||||
by_cases hk' : i + k < w + 1
|
||||
· have := Nat.ge_two_pow_of_testBit hk
|
||||
have := Nat.pow_le_pow_of_le (a := 2) (n := i) (m := i + k) (by omega) (by omega)
|
||||
omega
|
||||
· simp [show w + 1 ≤ i + k by omega] at hk
|
||||
|
||||
/-- A bitvector interpreted as a natural number is strictly smaller than `2 ^ i` if and only if
|
||||
all bits at position `i` or higher are false. -/
|
||||
theorem toNat_lt_iff_getLsbD_eq_false {x : BitVec w} (i : Nat) (hi : i < w) :
|
||||
x.toNat < 2 ^ i ↔ (∀ k, x.getLsbD (i + k) = false) := by
|
||||
constructor
|
||||
· intro h
|
||||
apply Classical.byContradiction
|
||||
intro hcontra
|
||||
simp only [Classical.not_forall, Bool.not_eq_false] at hcontra
|
||||
obtain ⟨k, hk⟩ := hcontra
|
||||
have hle := Nat.ge_two_pow_of_testBit hk
|
||||
by_cases hlt : i + k < w
|
||||
· have := Nat.pow_le_pow_of_le (a := 2) (n := i) (m := i + k) (by omega) (by omega)
|
||||
omega
|
||||
· simp [show w ≤ i + k by omega] at hk
|
||||
· intro h
|
||||
apply Classical.byContradiction
|
||||
intro hcontra
|
||||
simp [BitVec.le_toNat_iff_getLsbD_eq_true (x := x) (i := i) hi, h] at hcontra
|
||||
|
||||
/-- If a bitvector interpreted as a natural number is strictly smaller than `2 ^ (k + 1)` and greater than or
|
||||
equal to 2 ^ k, then the bit at position `k` must be `true` -/
|
||||
theorem getElem_eq_true_of_lt_of_le {x : BitVec w} (hk' : k < w) (hlt: x.toNat < 2 ^ (k + 1)) (hle : 2 ^ k ≤ x.toNat) :
|
||||
x[k] = true := by
|
||||
have := le_toNat_iff_getLsbD_eq_true (x := x) (i := k) hk'
|
||||
simp only [hle, true_iff] at this
|
||||
obtain ⟨k',hk'⟩ := this
|
||||
by_cases hkk' : k + k' < w
|
||||
· have := Nat.ge_two_pow_of_testBit hk'
|
||||
by_cases hzk' : k' = 0
|
||||
· simp [hzk'] at hk'; exact hk'
|
||||
· have := Nat.pow_lt_pow_of_lt (a := 2) (n := k) (m := k + k') (by omega) (by omega)
|
||||
have := Nat.pow_le_pow_of_le (a := 2) (n := k + 1) (m := k + k') (by omega) (by omega)
|
||||
omega
|
||||
· simp [show w ≤ k + k' by omega] at hk'
|
||||
|
||||
/-! ### Count leading zeros -/
|
||||
|
||||
theorem clzAuxRec_zero (x : BitVec w) :
|
||||
x.clzAuxRec 0 = if x.getLsbD 0 then BitVec.ofNat w (w - 1) else BitVec.ofNat w w := by rfl
|
||||
|
||||
theorem clzAuxRec_succ (x : BitVec w) :
|
||||
x.clzAuxRec (n + 1) = if x.getLsbD (n + 1) then BitVec.ofNat w (w - 1 - (n + 1)) else BitVec.clzAuxRec x n := by rfl
|
||||
|
||||
theorem clzAuxRec_eq_clzAuxRec_of_le {x : BitVec w} (h : w - 1 ≤ n) :
|
||||
x.clzAuxRec n = x.clzAuxRec (w - 1) := by
|
||||
let k := n - (w - 1)
|
||||
rw [show n = (w - 1) + k by omega]
|
||||
induction k
|
||||
· case zero => simp
|
||||
· case succ k ihk =>
|
||||
simp [show w - 1 + (k + 1) = (w - 1 + k) + 1 by omega, clzAuxRec_succ, ihk,
|
||||
show x.getLsbD (w - 1 + k + 1) = false by simp only [show w ≤ w - 1 + k + 1 by omega, getLsbD_of_ge]]
|
||||
|
||||
theorem clzAuxRec_eq_clzAuxRec_of_getLsbD_false {x : BitVec w} (h : ∀ i, n < i → x.getLsbD i = false) :
|
||||
x.clzAuxRec n = x.clzAuxRec (n + k) := by
|
||||
induction k
|
||||
· case zero => simp
|
||||
· case succ k ihk =>
|
||||
simp only [show n + (k + 1) = (n + k) + 1 by omega, clzAuxRec_succ]
|
||||
by_cases hxn : x.getLsbD (n + k + 1)
|
||||
· have : ¬ ∀ (i : Nat), n < i → x.getLsbD i = false := by
|
||||
simp only [Classical.not_forall, Bool.not_eq_false]
|
||||
exists n + k + 1
|
||||
simp [show n < n + k + 1 by omega, hxn]
|
||||
contradiction
|
||||
· simp only [hxn, Bool.false_eq_true, ↓reduceIte]
|
||||
exact ihk
|
||||
|
||||
theorem clzAuxRec_le {x : BitVec w} (n : Nat) :
|
||||
clzAuxRec x n ≤ w := by
|
||||
have := Nat.lt_pow_self (a := 2) (n := w) (by omega)
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· induction n
|
||||
· case zero =>
|
||||
simp only [clzAuxRec_zero]
|
||||
by_cases hx0 : x.getLsbD 0
|
||||
· simp only [hx0, Nat.add_one_sub_one, reduceIte, natCast_eq_ofNat, ofNat_le_ofNat,
|
||||
Nat.mod_two_pow_self, ge_iff_le, Nat.mod_eq_of_lt (a := w) (b := 2 ^ (w + 1)) (by omega)]
|
||||
omega
|
||||
· simp only [hx0, Bool.false_eq_true, reduceIte, natCast_eq_ofNat, BitVec.le_refl]
|
||||
· case succ n ihn =>
|
||||
simp only [clzAuxRec_succ, Nat.add_one_sub_one, natCast_eq_ofNat, ge_iff_le]
|
||||
by_cases hxn : x.getLsbD (n + 1)
|
||||
· simp [hxn, Nat.mod_eq_of_lt (a := w - (n + 1)) (b := 2 ^(w + 1)) (by omega)]
|
||||
omega
|
||||
· simp only [hxn, Bool.false_eq_true, reduceIte]
|
||||
exact ihn
|
||||
|
||||
theorem clzAuxRec_eq_iff_of_getLsbD_false {x : BitVec w} (h : ∀ i, n < i → x.getLsbD i = false) :
|
||||
x.clzAuxRec n = BitVec.ofNat w w ↔ ∀ j, j ≤ n → x.getLsbD j = false := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· have := Nat.lt_pow_self (a := 2) (n := w + 1)
|
||||
induction n
|
||||
· case zero =>
|
||||
simp only [clzAuxRec_zero, Nat.zero_lt_succ, getLsbD_eq_getElem, Nat.add_one_sub_one,
|
||||
ite_eq_right_iff, Nat.le_zero_eq, forall_eq]
|
||||
by_cases hx0 : x.getLsbD 0
|
||||
· simp [hx0, toNat_eq, toNat_ofNat, Nat.mod_eq_of_lt (a := w) (b := 2 ^ (w + 1)) (by omega)]
|
||||
· simp only [Nat.zero_lt_succ, getLsbD_eq_getElem, Bool.not_eq_true] at hx0
|
||||
simp [hx0]
|
||||
· case succ n ihn =>
|
||||
simp only [clzAuxRec_succ, Nat.add_one_sub_one]
|
||||
by_cases hxn : x.getLsbD (n + 1)
|
||||
· simp only [hxn, reduceIte, toNat_eq, toNat_ofNat,
|
||||
Nat.mod_eq_of_lt (a := w - (n + 1)) (b := 2 ^ (w + 1)) (by omega), Nat.mod_two_pow_self,
|
||||
show ¬w - (n + 1) = w + 1 by omega, false_iff, Classical.not_forall,
|
||||
Bool.not_eq_false]
|
||||
exists n + 1, by omega
|
||||
· have : ∀ (i : Nat), n < i → x.getLsbD i = false := by
|
||||
intro i hi
|
||||
by_cases hi' : i = n + 1
|
||||
· simp [hi', hxn]
|
||||
· apply h; omega
|
||||
specialize ihn this
|
||||
simp only [Bool.not_eq_true] at ihn hxn
|
||||
simp only [hxn, Bool.false_eq_true, reduceIte, ihn]
|
||||
constructor
|
||||
<;> intro h' j hj
|
||||
<;> (by_cases hj' : j = n + 1; simp [hj', hxn]; (apply h'; omega))
|
||||
|
||||
theorem clz_le {x : BitVec w} :
|
||||
clz x ≤ w := by
|
||||
unfold clz
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· exact clzAuxRec_le (n := w)
|
||||
|
||||
@[simp]
|
||||
theorem clz_eq_iff_eq_zero {x : BitVec w} :
|
||||
clz x = w ↔ x = 0#w := by
|
||||
rcases w with _|w
|
||||
· simp [clz, of_length_zero]
|
||||
· simp only [clz, Nat.add_one_sub_one, natCast_eq_ofNat, zero_iff_eq_false]
|
||||
rw [clzAuxRec_eq_iff_of_getLsbD_false (x := x) (n := w) (w := w + 1) (by intros i hi; simp [show w + 1 ≤ i by omega])]
|
||||
constructor
|
||||
· intro h i
|
||||
by_cases i ≤ w
|
||||
· apply h; omega
|
||||
· simp [show w + 1 ≤ i by omega]
|
||||
· intro h j hj
|
||||
apply h
|
||||
|
||||
theorem clzAuxRec_eq_zero_iff {x : BitVec w} (h : ∀ i, n < i → x.getLsbD i = false) (hw : 0 < w) :
|
||||
(x.clzAuxRec n).toNat = 0 ↔ x[w - 1] = true := by
|
||||
have := Nat.lt_pow_self (a := 2) (n := w)
|
||||
induction n
|
||||
· case zero =>
|
||||
simp only [clzAuxRec_zero]
|
||||
by_cases hw1 : w - 1 = 0
|
||||
· by_cases hx0 : x.getLsbD 0
|
||||
· simp [hw1, hx0]
|
||||
· simp [hw1, show ¬ w = 0 by omega, hx0, ← getLsbD_eq_getElem]
|
||||
· by_cases hx0 : x.getLsbD 0
|
||||
· simp only [hx0, ↓reduceIte, toNat_ofNat,
|
||||
Nat.mod_eq_of_lt (a := w - 1) (b := 2 ^ w) (by omega), show ¬w - 1 = 0 by omega, false_iff,
|
||||
Bool.not_eq_true]
|
||||
specialize h (w - 1) (by omega)
|
||||
exact h
|
||||
· simp [hx0, show ¬ w = 0 by omega]
|
||||
specialize h (w - 1) (by omega)
|
||||
exact h
|
||||
· case succ n ihn =>
|
||||
by_cases hxn : x.getLsbD (n + 1)
|
||||
· simp only [clzAuxRec_succ, hxn, reduceIte, toNat_ofNat]
|
||||
rw [Nat.mod_eq_of_lt (by omega)]
|
||||
by_cases hwn : w - 1 - (n + 1) = 0
|
||||
· have := lt_of_getLsbD hxn
|
||||
simp only [show w - 1 = n + 1 by omega, Nat.sub_self, true_iff]
|
||||
exact hxn
|
||||
· simp only [hwn, false_iff, Bool.not_eq_true]
|
||||
specialize h (w - 1) (by omega)
|
||||
exact h
|
||||
· simp only [clzAuxRec_succ, hxn, Bool.false_eq_true, reduceIte]
|
||||
apply ihn
|
||||
intro i hi
|
||||
by_cases hi : i = n + 1
|
||||
· simp [hi, hxn]
|
||||
· apply h; omega
|
||||
|
||||
theorem clz_eq_zero_iff {x : BitVec w} (hw : 0 < w) :
|
||||
(clz x).toNat = 0 ↔ 2 ^ (w - 1) ≤ x.toNat := by
|
||||
simp only [clz, clzAuxRec_eq_zero_iff (x := x) (n := w - 1) (by intro i hi; simp [show w ≤ i by omega]) hw]
|
||||
by_cases hxw : x[w - 1]
|
||||
· simp [hxw, two_pow_le_toNat_of_getElem_eq_true (x := x) (i := w - 1) (by omega) hxw]
|
||||
· simp only [hxw, Bool.false_eq_true, false_iff, Nat.not_le]
|
||||
simp only [← getLsbD_eq_getElem, ← msb_eq_getLsbD_last, Bool.not_eq_true] at hxw
|
||||
exact toNat_lt_of_msb_false hxw
|
||||
|
||||
/-- The number of leading zeroes is strictly less than the bitwidth iff the bitvector is nonzero. -/
|
||||
theorem clz_lt_iff_ne_zero {x : BitVec w} :
|
||||
clz x < w ↔ x ≠ 0#w := by
|
||||
have hle := clz_le (x := x)
|
||||
have heq := clz_eq_iff_eq_zero (x := x)
|
||||
constructor
|
||||
· intro h
|
||||
simp only [natCast_eq_ofNat, BitVec.ne_of_lt (x := x.clz) (y := BitVec.ofNat w w) h,
|
||||
false_iff] at heq
|
||||
simp only [ne_eq, heq, not_false_eq_true]
|
||||
· intro h
|
||||
simp only [natCast_eq_ofNat, h, iff_false] at heq
|
||||
apply BitVec.lt_of_le_ne (x := x.clz) (y := BitVec.ofNat w w) hle heq
|
||||
|
||||
theorem getLsbD_false_of_clzAuxRec {x : BitVec w} (h : ∀ i, n < i → x.getLsbD i = false) :
|
||||
∀ j, x.getLsbD (w - (x.clzAuxRec n).toNat + j) = false := by
|
||||
rcases w with _|w
|
||||
· simp
|
||||
· have := Nat.lt_pow_self (a := 2) (n := w + 1)
|
||||
induction n
|
||||
· case zero =>
|
||||
intro j
|
||||
simp only [clzAuxRec_zero, Nat.zero_lt_succ, getLsbD_eq_getElem, Nat.add_one_sub_one]
|
||||
by_cases hx0 : x[0]
|
||||
· specialize h (1 + j) (by omega)
|
||||
simp [h, hx0, Nat.mod_eq_of_lt (a := w) (b := 2 ^ (w + 1)) (by omega)]
|
||||
· simp only [hx0, Bool.false_eq_true, ↓reduceIte, toNat_ofNat, Nat.mod_two_pow_self,
|
||||
Nat.sub_self, Nat.zero_add]
|
||||
by_cases hj0 : j = 0
|
||||
· simp [hj0, hx0]
|
||||
· specialize h j (by omega)
|
||||
exact h
|
||||
· case succ n ihn =>
|
||||
intro j
|
||||
by_cases hxn : x.getLsbD (n + 1)
|
||||
· have := lt_of_getLsbD hxn
|
||||
specialize h (n + j + 1 + 1) (by omega)
|
||||
simp [h, clzAuxRec_succ, hxn, Nat.mod_eq_of_lt (a := w - (n + 1)) (b := 2 ^ (w + 1)) (by omega),
|
||||
show (w + 1 - (w - (n + 1)) + j) = n + j + 1 + 1 by omega]
|
||||
· simp only [clzAuxRec_succ, hxn, Bool.false_eq_true, reduceIte]
|
||||
apply ihn
|
||||
intro i hi
|
||||
by_cases hin : i = n + 1
|
||||
· simp [hin, hxn]
|
||||
· specialize h i (by omega)
|
||||
exact h
|
||||
|
||||
theorem getLsbD_true_of_eq_clzAuxRec_of_ne_zero {x : BitVec w} (hx : ¬ x = 0#w) (hn : ∀ i, n < i → x.getLsbD i = false) :
|
||||
x.getLsbD (w - 1 - (x.clzAuxRec n).toNat) = true := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero] at hx
|
||||
· have := Nat.lt_pow_self (a := 2) (n := w + 1)
|
||||
induction n
|
||||
· case zero =>
|
||||
by_cases hx0 : x[0]
|
||||
· simp only [Nat.add_one_sub_one, clzAuxRec_zero, Nat.zero_lt_succ, getLsbD_eq_getElem, hx0,
|
||||
reduceIte, toNat_ofNat, Nat.mod_eq_of_lt (a := w) (b := 2 ^(w + 1)) (by omega), show w - w = 0 by omega]
|
||||
· simp only [zero_iff_eq_false, Classical.not_forall, Bool.not_eq_false] at hx
|
||||
obtain ⟨m,hm⟩ := hx
|
||||
specialize hn m
|
||||
by_cases hm0 : m = 0
|
||||
· simp [hm0, hx0] at hm
|
||||
· simp [show 0 < m by omega, hm] at hn
|
||||
· case succ n ihn =>
|
||||
by_cases hxn : x.getLsbD (n + 1)
|
||||
· have := lt_of_getLsbD hxn
|
||||
simp [clzAuxRec_succ, hxn, toNat_ofNat, Nat.mod_eq_of_lt (a := w - (n + 1)) (b := 2 ^ (w + 1)) (by omega),
|
||||
show w - (w - (n + 1)) = n + 1 by omega]
|
||||
· simp only [Nat.add_one_sub_one, clzAuxRec_succ, hxn, Bool.false_eq_true, reduceIte]
|
||||
simp only [Nat.add_one_sub_one] at ihn
|
||||
apply ihn
|
||||
intro j hj
|
||||
by_cases hjn : j = n + 1
|
||||
· simp [hjn, hxn]
|
||||
· specialize hn j (by omega)
|
||||
exact hn
|
||||
|
||||
theorem getLsbD_true_clz_of_ne_zero {x : BitVec w} (hw : 0 < w) (hx : x ≠ 0#w) :
|
||||
x.getLsbD (w - 1 - (clz x).toNat) = true := by
|
||||
unfold clz
|
||||
apply getLsbD_true_of_eq_clzAuxRec_of_ne_zero (x := x) (n := w - 1) (by omega)
|
||||
intro i hi
|
||||
simp [show w ≤ i by omega]
|
||||
|
||||
/-- A nonzero bitvector is lower-bounded by its leading zeroes. -/
|
||||
theorem two_pow_sub_clz_le_toNat_of_ne_zero {x : BitVec w} (hw : 0 < w) (hx : x ≠ 0#w) :
|
||||
2 ^ (w - 1 - (clz x).toNat) ≤ x.toNat := by
|
||||
by_cases hc0 : x.clz.toNat = 0
|
||||
· simp [hc0, ← clz_eq_zero_iff (x := x) hw]
|
||||
· have hclz := getLsbD_true_clz_of_ne_zero (x := x) hw hx
|
||||
rw [getLsbD_eq_getElem (by omega)] at hclz
|
||||
have hge := Nat.ge_two_pow_of_testBit hclz
|
||||
push_cast at hge
|
||||
exact hge
|
||||
|
||||
/-- A bitvector is upper bounded by the number of leading zeroes. -/
|
||||
theorem toNat_lt_two_pow_sub_clz {x : BitVec w} :
|
||||
x.toNat < 2 ^ (w - (clz x).toNat) := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· unfold clz
|
||||
have hlt := toNat_lt_iff_getLsbD_eq_false (x := x)
|
||||
have hzero := clzAuxRec_eq_zero_iff (x := x) (n := w) (by intro i hi; simp [show w + 1 ≤ i by omega]) (by omega)
|
||||
simp only [Nat.add_one_sub_one] at hzero
|
||||
by_cases hxw : x[w]
|
||||
· simp only [hxw, iff_true] at hzero
|
||||
simp only [Nat.add_one_sub_one, hzero, Nat.sub_zero, gt_iff_lt]
|
||||
omega
|
||||
· simp only [hxw, Bool.false_eq_true, iff_false] at hzero
|
||||
rw [hlt]
|
||||
· intro k
|
||||
apply getLsbD_false_of_clzAuxRec (x := x) (n := w)
|
||||
intro i hi
|
||||
by_cases hiw : i = w
|
||||
· simp [hiw, hxw]
|
||||
· simp [show w + 1 ≤ i by omega]
|
||||
· simp; omega
|
||||
|
||||
|
||||
/-! ### Deprecations -/
|
||||
|
||||
set_option linter.missingDocs false
|
||||
@@ -5842,13 +6190,8 @@ set_option linter.missingDocs false
|
||||
@[deprecated toFin_uShiftRight (since := "2025-02-18")]
|
||||
abbrev toFin_uShiftRight := @toFin_ushiftRight
|
||||
|
||||
@[deprecated signExtend_eq_setWidth_of_msb_false (since := "2024-12-08")]
|
||||
abbrev signExtend_eq_not_setWidth_not_of_msb_false := @signExtend_eq_setWidth_of_msb_false
|
||||
|
||||
@[deprecated replicate_zero (since := "2025-01-08")]
|
||||
abbrev replicate_zero_eq := @replicate_zero
|
||||
|
||||
@[deprecated replicate_succ (since := "2025-01-08")]
|
||||
abbrev replicate_succ_eq := @replicate_succ
|
||||
|
||||
|
||||
end BitVec
|
||||
|
||||
@@ -696,3 +696,23 @@ but may be used locally.
|
||||
|
||||
@[simp] theorem Subtype.beq_iff {α : Type u} [BEq α] {p : α → Prop} {x y : {a : α // p a}} :
|
||||
(x == y) = (x.1 == y.1) := rfl
|
||||
|
||||
/-! ### Proof by reflection support -/
|
||||
|
||||
@[expose] protected noncomputable def Bool.and' (a b : Bool) : Bool :=
|
||||
Bool.rec false b a
|
||||
|
||||
@[expose] protected noncomputable def Bool.or' (a b : Bool) : Bool :=
|
||||
Bool.rec b true a
|
||||
|
||||
@[expose] protected noncomputable def Bool.not' (a : Bool) : Bool :=
|
||||
Bool.rec true false a
|
||||
|
||||
@[simp] theorem Bool.and'_eq_and (a b : Bool) : a.and' b = a.and b := by
|
||||
cases a <;> simp [Bool.and']
|
||||
|
||||
@[simp] theorem Bool.or'_eq_or (a b : Bool) : a.or' b = a.or b := by
|
||||
cases a <;> simp [Bool.or']
|
||||
|
||||
@[simp] theorem Bool.not'_eq_not (a : Bool) : a.not' = a.not := by
|
||||
cases a <;> simp [Bool.not']
|
||||
|
||||
@@ -9,18 +9,22 @@ prelude
|
||||
public import Init.Data.Array.Basic
|
||||
public import Init.Data.Array.DecidableEq
|
||||
public import Init.Data.UInt.Basic
|
||||
public import all Init.Data.UInt.BasicAux
|
||||
public import Init.Data.UInt.BasicAux
|
||||
import all Init.Data.UInt.BasicAux
|
||||
public import Init.Data.Option.Basic
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
universe u
|
||||
|
||||
set_option genInjectivity false in
|
||||
structure ByteArray where
|
||||
data : Array UInt8
|
||||
|
||||
attribute [extern "lean_byte_array_mk"] ByteArray.mk
|
||||
attribute [extern "lean_byte_array_data"] ByteArray.data
|
||||
|
||||
gen_injective_theorems% ByteArray
|
||||
|
||||
namespace ByteArray
|
||||
|
||||
deriving instance BEq for ByteArray
|
||||
|
||||
@@ -8,5 +8,6 @@ module
|
||||
prelude
|
||||
public import Init.Data.Char.Basic
|
||||
public import Init.Data.Char.Lemmas
|
||||
public import Init.Data.Char.Order
|
||||
|
||||
public section
|
||||
|
||||
@@ -8,7 +8,7 @@ module
|
||||
prelude
|
||||
public import Init.Data.UInt.BasicAux
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
/-- Determines if the given integer is a valid [Unicode scalar value](https://www.unicode.org/glossary/#unicode_scalar_value).
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ Authors: Leonardo de Moura
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Char.Basic
|
||||
public import Init.Data.Char.Basic
|
||||
import all Init.Data.Char.Basic
|
||||
public import Init.Data.UInt.Lemmas
|
||||
|
||||
public section
|
||||
@@ -61,6 +62,7 @@ instance leTotal : Std.Total (· ≤ · : Char → Char → Prop) where
|
||||
total := Char.le_total
|
||||
|
||||
-- This instance is useful while setting up instances for `String`.
|
||||
@[deprecated ltAsymm (since := "2025-08-01")]
|
||||
def notLTTotal : Std.Total (¬ · < · : Char → Char → Prop) where
|
||||
total := fun x y => by simpa using Char.le_total y x
|
||||
|
||||
|
||||
27
src/Init/Data/Char/Order.lean
Normal file
27
src/Init/Data/Char/Order.lean
Normal file
@@ -0,0 +1,27 @@
|
||||
/-
|
||||
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Paul Reichert
|
||||
-/
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Char.Basic
|
||||
import Init.Data.Char.Lemmas
|
||||
public import Init.Data.Order.Factories
|
||||
|
||||
open Std
|
||||
|
||||
namespace Char
|
||||
|
||||
public instance instIsLinearOrder : IsLinearOrder Char := by
|
||||
apply IsLinearOrder.of_le
|
||||
case le_antisymm => constructor; apply Char.le_antisymm
|
||||
case le_trans => constructor; apply Char.le_trans
|
||||
case le_total => constructor; apply Char.le_total
|
||||
|
||||
public instance : LawfulOrderLT Char where
|
||||
lt_iff a b := by
|
||||
simp [← Char.not_le, Decidable.imp_iff_not_or, Std.Total.total]
|
||||
|
||||
end Char
|
||||
11
src/Init/Data/Dyadic.lean
Normal file
11
src/Init/Data/Dyadic.lean
Normal file
@@ -0,0 +1,11 @@
|
||||
/-
|
||||
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Kim Morrison
|
||||
-/
|
||||
module
|
||||
prelude
|
||||
|
||||
public import Init.Data.Dyadic.Basic
|
||||
public import Init.Data.Dyadic.Instances
|
||||
public import Init.Data.Dyadic.Round
|
||||
659
src/Init/Data/Dyadic/Basic.lean
Normal file
659
src/Init/Data/Dyadic/Basic.lean
Normal file
@@ -0,0 +1,659 @@
|
||||
/-
|
||||
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Kim Morrison, Robin Arnez
|
||||
-/
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Rat.Lemmas
|
||||
import Init.Data.Int.Bitwise.Lemmas
|
||||
import Init.Data.Int.DivMod.Lemmas
|
||||
|
||||
/-!
|
||||
# The dyadic rationals
|
||||
|
||||
Constructs the dyadic rationals as an ordered ring, equipped with a compatible embedding into the rationals.
|
||||
-/
|
||||
|
||||
set_option linter.missingDocs true
|
||||
|
||||
@[expose] public section
|
||||
|
||||
open Nat
|
||||
|
||||
namespace Int
|
||||
|
||||
/-- The number of trailing zeros in the binary representation of `i`. -/
|
||||
def trailingZeros (i : Int) : Nat :=
|
||||
if h : i = 0 then 0 else aux i.natAbs i h (Nat.le_refl _) 0
|
||||
where
|
||||
aux (k : Nat) (i : Int) (hi : i ≠ 0) (hk : i.natAbs ≤ k) (acc : Nat) : Nat :=
|
||||
match k, (by omega : k ≠ 0) with
|
||||
| k + 1, _ =>
|
||||
if h : i % 2 = 0 then aux k (i / 2) (by omega) (by omega) (acc + 1)
|
||||
else acc
|
||||
|
||||
-- TODO: check performance of `trailingZeros` in the kernel and VM.
|
||||
|
||||
private theorem trailingZeros_aux_irrel (hi : i ≠ 0) (hk : i.natAbs ≤ k) (hk' : i.natAbs ≤ k') :
|
||||
trailingZeros.aux k i hi hk acc = trailingZeros.aux k' i hi hk' acc := by
|
||||
fun_induction trailingZeros.aux k i hi hk acc generalizing k' <;>
|
||||
fun_cases trailingZeros.aux k' _ _ hk' _
|
||||
· rename_i ih _ _ _ _ _
|
||||
exact ih _
|
||||
· contradiction
|
||||
· contradiction
|
||||
· rfl
|
||||
|
||||
private theorem trailingZeros_aux_succ :
|
||||
trailingZeros.aux k i hi hk (acc + 1) = trailingZeros.aux k i hi hk acc + 1 := by
|
||||
fun_induction trailingZeros.aux k i hi hk acc <;> simp_all [trailingZeros.aux]
|
||||
|
||||
theorem trailingZeros_zero : trailingZeros 0 = 0 := rfl
|
||||
|
||||
theorem trailingZeros_two_mul_add_one (i : Int) :
|
||||
Int.trailingZeros (2 * i + 1) = 0 := by
|
||||
unfold trailingZeros trailingZeros.aux
|
||||
rw [dif_neg (by omega)]
|
||||
split <;> simp_all
|
||||
|
||||
theorem trailingZeros_eq_zero_of_mod_eq {i : Int} (h : i % 2 = 1) :
|
||||
Int.trailingZeros i = 0 := by
|
||||
unfold trailingZeros trailingZeros.aux
|
||||
rw [dif_neg (by omega)]
|
||||
split <;> simp_all
|
||||
|
||||
theorem trailingZeros_two_mul {i : Int} (h : i ≠ 0) :
|
||||
Int.trailingZeros (2 * i) = Int.trailingZeros i + 1 := by
|
||||
rw [Int.trailingZeros, dif_neg (Int.mul_ne_zero (by decide) h), Int.trailingZeros.aux.eq_def]
|
||||
simp only [ne_eq, mul_emod_right, ↓reduceDIte, Int.reduceEq, not_false_eq_true,
|
||||
mul_ediv_cancel_left, Nat.zero_add]
|
||||
split
|
||||
rw [trailingZeros, trailingZeros_aux_succ, dif_neg h]
|
||||
apply congrArg Nat.succ (trailingZeros_aux_irrel ..) <;> omega
|
||||
|
||||
theorem shiftRight_trailingZeros_mod_two {i : Int} (h : i ≠ 0) :
|
||||
(i >>> i.trailingZeros) % 2 = 1 := by
|
||||
rw (occs := .pos [2]) [← Int.emod_add_ediv i 2]
|
||||
rcases i.emod_two_eq with h' | h' <;> rw [h']
|
||||
· rcases Int.dvd_of_emod_eq_zero h' with ⟨a, rfl⟩
|
||||
simp only [ne_eq, Int.mul_eq_zero, Int.reduceEq, false_or] at h
|
||||
rw [Int.zero_add, mul_ediv_cancel_left _ (by decide), trailingZeros_two_mul h, Nat.add_comm,
|
||||
shiftRight_add, shiftRight_eq_div_pow _ 1]
|
||||
simpa using shiftRight_trailingZeros_mod_two h
|
||||
· rwa [Int.add_comm, trailingZeros_two_mul_add_one, shiftRight_zero]
|
||||
termination_by i.natAbs
|
||||
|
||||
theorem two_pow_trailingZeros_dvd {i : Int} (h : i ≠ 0) :
|
||||
2 ^ i.trailingZeros ∣ i := by
|
||||
rcases i.emod_two_eq with h' | h'
|
||||
· rcases Int.dvd_of_emod_eq_zero h' with ⟨a, rfl⟩
|
||||
simp only [ne_eq, Int.mul_eq_zero, Int.reduceEq, false_or] at h
|
||||
rw [trailingZeros_two_mul h, Int.pow_succ']
|
||||
exact Int.mul_dvd_mul_left _ (two_pow_trailingZeros_dvd h)
|
||||
· rw (occs := .pos [1]) [← Int.emod_add_ediv i 2, h', Int.add_comm, trailingZeros_two_mul_add_one]
|
||||
exact Int.one_dvd _
|
||||
termination_by i.natAbs
|
||||
|
||||
theorem trailingZeros_shiftLeft {x : Int} (hx : x ≠ 0) (n : Nat) :
|
||||
trailingZeros (x <<< n) = x.trailingZeros + n := by
|
||||
have : NeZero x := ⟨hx⟩
|
||||
induction n <;> simp [Int.shiftLeft_succ', trailingZeros_two_mul (NeZero.ne _), *, Nat.add_assoc]
|
||||
|
||||
@[simp]
|
||||
theorem trailingZeros_neg (x : Int) : trailingZeros (-x) = x.trailingZeros := by
|
||||
by_cases hx : x = 0
|
||||
· simp [hx]
|
||||
rcases x.emod_two_eq with h | h
|
||||
· rcases Int.dvd_of_emod_eq_zero h with ⟨a, rfl⟩
|
||||
simp only [Int.mul_ne_zero_iff, ne_eq, Int.reduceEq, not_false_eq_true, true_and] at hx
|
||||
rw [← Int.mul_neg, trailingZeros_two_mul hx, trailingZeros_two_mul (Int.neg_ne_zero.mpr hx)]
|
||||
rw [trailingZeros_neg]
|
||||
· simp [trailingZeros_eq_zero_of_mod_eq, h]
|
||||
termination_by x.natAbs
|
||||
|
||||
end Int
|
||||
|
||||
/--
|
||||
A dyadic rational is either zero or of the form `n * 2^(-k)` for some (unique) `n k : Int`
|
||||
where `n` is odd.
|
||||
-/
|
||||
inductive Dyadic where
|
||||
/-- The dyadic number `0`. -/
|
||||
| zero
|
||||
/-- The dyadic number `n * 2^(-k)` for some odd `n` and integer `k`. -/
|
||||
| ofOdd (n : Int) (k : Int) (hn : n % 2 = 1)
|
||||
deriving DecidableEq
|
||||
|
||||
namespace Dyadic
|
||||
|
||||
/-- Returns the dyadic number representation of `i * 2 ^ (-exp)`. -/
|
||||
def ofIntWithPrec (i : Int) (prec : Int) : Dyadic :=
|
||||
if h : i = 0 then .zero
|
||||
else .ofOdd (i >>> i.trailingZeros) (prec - i.trailingZeros) (Int.shiftRight_trailingZeros_mod_two h)
|
||||
|
||||
/-- Convert an integer to a dyadic number (which will necessarily have non-positive precision). -/
|
||||
def ofInt (i : Int) : Dyadic :=
|
||||
Dyadic.ofIntWithPrec i 0
|
||||
|
||||
instance (n : Nat) : OfNat Dyadic n where
|
||||
ofNat := Dyadic.ofInt n
|
||||
|
||||
instance : IntCast Dyadic := ⟨ofInt⟩
|
||||
instance : NatCast Dyadic := ⟨fun x => ofInt x⟩
|
||||
|
||||
/-- Add two dyadic numbers. -/
|
||||
protected def add (x y : Dyadic) : Dyadic :=
|
||||
match x, y with
|
||||
| .zero, y => y
|
||||
| x, .zero => x
|
||||
| .ofOdd n₁ k₁ hn₁, .ofOdd n₂ k₂ hn₂ =>
|
||||
match k₁ - k₂ with
|
||||
| 0 => .ofIntWithPrec (n₁ + n₂) k₁
|
||||
-- TODO: these `simp_all` calls where previously factored out into a `where finally` clause,
|
||||
-- but there is apparently a bad interaction with the module system.
|
||||
| (d@hd:(d' + 1) : Nat) => .ofOdd (n₁ + (n₂ <<< d)) k₁ (by simp_all [Int.shiftLeft_eq, Int.pow_succ, ← Int.mul_assoc])
|
||||
| -(d + 1 : Nat) => .ofOdd (n₁ <<< (d + 1) + n₂) k₂ (by simp_all [Int.shiftLeft_eq, Int.pow_succ, ← Int.mul_assoc])
|
||||
|
||||
instance : Add Dyadic := ⟨Dyadic.add⟩
|
||||
|
||||
/-- Multiply two dyadic numbers. -/
|
||||
protected def mul (x y : Dyadic) : Dyadic :=
|
||||
match x, y with
|
||||
| .zero, _ => .zero
|
||||
| _, .zero => .zero
|
||||
| .ofOdd n₁ k₁ hn₁, .ofOdd n₂ k₂ hn₂ =>
|
||||
.ofOdd (n₁ * n₂) (k₁ + k₂) (by rw [Int.mul_emod, hn₁, hn₂]; rfl)
|
||||
|
||||
instance : Mul Dyadic := ⟨Dyadic.mul⟩
|
||||
|
||||
/-- Multiply two dyadic numbers. -/
|
||||
protected def pow (x : Dyadic) (i : Nat) : Dyadic :=
|
||||
match x with
|
||||
| .zero => if i = 0 then 1 else 0
|
||||
| .ofOdd n k hn =>
|
||||
.ofOdd (n ^ i) (k * i) (by induction i <;> simp [Int.pow_succ, Int.mul_emod, *])
|
||||
|
||||
instance : Pow Dyadic Nat := ⟨Dyadic.pow⟩
|
||||
|
||||
/-- Negate a dyadic number. -/
|
||||
protected def neg (x : Dyadic) : Dyadic :=
|
||||
match x with
|
||||
| .zero => .zero
|
||||
| .ofOdd n k hn => .ofOdd (-n) k (by rwa [Int.neg_emod_two])
|
||||
|
||||
instance : Neg Dyadic := ⟨Dyadic.neg⟩
|
||||
|
||||
/-- Subtract two dyadic numbers. -/
|
||||
protected def sub (x y : Dyadic) : Dyadic := x + (- y)
|
||||
|
||||
instance : Sub Dyadic := ⟨Dyadic.sub⟩
|
||||
|
||||
/-- Shift a dyadic number left by `i` bits. -/
|
||||
protected def shiftLeft (x : Dyadic) (i : Int) : Dyadic :=
|
||||
match x with
|
||||
| .zero => .zero
|
||||
| .ofOdd n k hn => .ofOdd n (k - i) hn
|
||||
|
||||
/-- Shift a dyadic number right by `i` bits. -/
|
||||
protected def shiftRight (x : Dyadic) (i : Int) : Dyadic :=
|
||||
match x with
|
||||
| .zero => .zero
|
||||
| .ofOdd n k hn => .ofOdd n (k + i) hn
|
||||
|
||||
instance : HShiftLeft Dyadic Int Dyadic := ⟨Dyadic.shiftLeft⟩
|
||||
instance : HShiftRight Dyadic Int Dyadic := ⟨Dyadic.shiftRight⟩
|
||||
|
||||
instance : HShiftLeft Dyadic Nat Dyadic := ⟨fun x y => x <<< (y : Int)⟩
|
||||
instance : HShiftRight Dyadic Nat Dyadic := ⟨fun x y => x >>> (y : Int)⟩
|
||||
|
||||
-- TODO: move this
|
||||
theorem _root_.Int.natAbs_emod_two (i : Int) : i.natAbs % 2 = (i % 2).natAbs := by omega
|
||||
|
||||
/-- Convert a dyadic number to a rational number. -/
|
||||
def toRat (x : Dyadic) : Rat :=
|
||||
match x with
|
||||
| .zero => 0
|
||||
| .ofOdd n (k : Nat) hn =>
|
||||
have reduced : n.natAbs.Coprime (2 ^ k) := by
|
||||
apply Coprime.pow_right
|
||||
rw [coprime_iff_gcd_eq_one, Nat.gcd_comm, Nat.gcd_def]
|
||||
simp [hn, Int.natAbs_emod_two]
|
||||
⟨n, 2 ^ k, Nat.ne_of_gt (Nat.pow_pos (by decide)), reduced⟩
|
||||
| .ofOdd n (-((k : Nat) + 1)) hn =>
|
||||
(n * (2 ^ (k + 1) : Nat) : Int)
|
||||
|
||||
@[simp] protected theorem zero_eq : Dyadic.zero = 0 := rfl
|
||||
@[simp] protected theorem add_zero (x : Dyadic) : x + 0 = x := by cases x <;> rfl
|
||||
@[simp] protected theorem zero_add (x : Dyadic) : 0 + x = x := by cases x <;> rfl
|
||||
@[simp] protected theorem neg_zero : (-0 : Dyadic) = 0 := rfl
|
||||
@[simp] protected theorem mul_zero (x : Dyadic) : x * 0 = 0 := by cases x <;> rfl
|
||||
@[simp] protected theorem zero_mul (x : Dyadic) : 0 * x = 0 := by cases x <;> rfl
|
||||
|
||||
@[simp] theorem toRat_zero : toRat 0 = 0 := rfl
|
||||
|
||||
theorem _root_.Rat.mkRat_one (x : Int) : mkRat x 1 = x := by
|
||||
rw [← Rat.mk_den_one, Rat.mk_eq_mkRat]
|
||||
|
||||
theorem toRat_ofOdd_eq_mkRat :
|
||||
toRat (.ofOdd n k hn) = mkRat (n <<< (-k).toNat) (1 <<< k.toNat) := by
|
||||
cases k
|
||||
· simp [toRat, Rat.mk_eq_mkRat, Int.shiftLeft_eq, Nat.shiftLeft_eq]
|
||||
· simp [toRat, Int.neg_negSucc, Rat.mkRat_one, Int.shiftLeft_eq]
|
||||
|
||||
theorem toRat_ofIntWithPrec_eq_mkRat :
|
||||
toRat (.ofIntWithPrec n k) = mkRat (n <<< (-k).toNat) (1 <<< k.toNat) := by
|
||||
simp only [ofIntWithPrec]
|
||||
split
|
||||
· simp_all
|
||||
rw [toRat_ofOdd_eq_mkRat, Rat.mkRat_eq_iff (NeZero.ne _) (NeZero.ne _)]
|
||||
simp only [Int.natCast_shiftLeft, Int.cast_ofNat_Int, Int.shiftLeft_mul_shiftLeft, Int.mul_one]
|
||||
have : (-(k - n.trailingZeros) : Int).toNat + k.toNat =
|
||||
n.trailingZeros + ((-k).toNat + (k - n.trailingZeros).toNat) := by omega
|
||||
rw [this, Int.shiftLeft_add, Int.shiftRight_shiftLeft_cancel]
|
||||
exact Int.two_pow_trailingZeros_dvd ‹_›
|
||||
|
||||
theorem toRat_ofIntWithPrec_eq_mul_two_pow : toRat (.ofIntWithPrec n k) = n * 2 ^ (-k) := by
|
||||
rw [toRat_ofIntWithPrec_eq_mkRat, Rat.zpow_neg, Int.shiftLeft_eq, Nat.one_shiftLeft]
|
||||
rw [Rat.mkRat_eq_div, Rat.div_def]
|
||||
have : ((2 : Int) : Rat) ≠ 0 := by decide
|
||||
simp only [Rat.intCast_mul, Rat.intCast_pow, ← Rat.zpow_natCast, ← Rat.intCast_natCast,
|
||||
Int.natCast_pow, Int.cast_ofNat_Int, ← Rat.zpow_neg, Rat.mul_assoc, ne_eq,
|
||||
Rat.intCast_eq_zero_iff, Int.reduceEq, not_false_eq_true, ← Rat.zpow_add]
|
||||
rw [Int.add_neg_eq_sub, ← Int.neg_sub, Int.toNat_sub_toNat_neg]
|
||||
rfl
|
||||
|
||||
example : ((3 : Dyadic) >>> 2) + ((3 : Dyadic) >>> 2) = ((3 : Dyadic) >>> 1) := rfl -- 3/4 + 3/4 = 3/2
|
||||
example : ((7 : Dyadic) >>> 3) + ((1 : Dyadic) >>> 3) = 1 := rfl -- 7/8 + 1/8 = 1
|
||||
example : (12 : Dyadic) + ((3 : Dyadic) >>> 1) = (27 : Dyadic) >>> 1 := rfl -- 12 + 3/2 = 27/2 = (2 * 13 + 1)/2^1
|
||||
example : ((3 : Dyadic) >>> 1).add 12 = (27 : Dyadic) >>> 1 := rfl -- 3/2 + 12 = 27/2 = (2 * 13 + 1)/2^1
|
||||
example : (12 : Dyadic).add 12 = 24 := rfl -- 12 + 12 = 24
|
||||
|
||||
@[simp]
|
||||
theorem toRat_add (x y : Dyadic) : toRat (x + y) = toRat x + toRat y := by
|
||||
match x, y with
|
||||
| .zero, _ => simp [toRat, Rat.zero_add]
|
||||
| _, .zero => simp [toRat, Rat.add_zero]
|
||||
| .ofOdd n₁ k₁ hn₁, .ofOdd n₂ k₂ hn₂ =>
|
||||
change (Dyadic.add _ _).toRat = _
|
||||
rw [Dyadic.add, toRat_ofOdd_eq_mkRat, toRat_ofOdd_eq_mkRat]
|
||||
rw [Rat.mkRat_add_mkRat _ _ (NeZero.ne _) (NeZero.ne _)]
|
||||
split
|
||||
· rename_i h
|
||||
cases Int.sub_eq_zero.mp h
|
||||
rw [toRat_ofIntWithPrec_eq_mkRat, Rat.mkRat_eq_iff (NeZero.ne _) (NeZero.ne _)]
|
||||
simp [Int.shiftLeft_mul_shiftLeft, Int.add_shiftLeft, Int.add_mul, Nat.add_assoc]
|
||||
· rename_i h
|
||||
cases Int.sub_eq_iff_eq_add.mp h
|
||||
rw [toRat_ofOdd_eq_mkRat, Rat.mkRat_eq_iff (NeZero.ne _) (NeZero.ne _)]
|
||||
simp only [succ_eq_add_one, Int.ofNat_eq_coe, Int.add_shiftLeft, ← Int.shiftLeft_add,
|
||||
Int.natCast_mul, Int.natCast_shiftLeft, Int.shiftLeft_mul_shiftLeft, Int.add_mul]
|
||||
congr 2 <;> omega
|
||||
· rename_i h
|
||||
cases Int.sub_eq_iff_eq_add.mp h
|
||||
rw [toRat_ofOdd_eq_mkRat, Rat.mkRat_eq_iff (NeZero.ne _) (NeZero.ne _)]
|
||||
simp only [Int.add_shiftLeft, ← Int.shiftLeft_add, Int.natCast_mul, Int.natCast_shiftLeft,
|
||||
Int.cast_ofNat_Int, Int.shiftLeft_mul_shiftLeft, Int.mul_one, Int.add_mul]
|
||||
congr 2 <;> omega
|
||||
|
||||
@[simp]
|
||||
theorem toRat_neg (x : Dyadic) : toRat (-x) = - toRat x := by
|
||||
change x.neg.toRat = _
|
||||
cases x
|
||||
· rfl
|
||||
· simp [Dyadic.neg, Rat.neg_mkRat, Int.neg_shiftLeft, toRat_ofOdd_eq_mkRat]
|
||||
|
||||
@[simp]
|
||||
theorem toRat_sub (x y : Dyadic) : toRat (x - y) = toRat x - toRat y := by
|
||||
change toRat (x + -y) = _
|
||||
simp [Rat.sub_eq_add_neg]
|
||||
|
||||
@[simp]
|
||||
theorem toRat_mul (x y : Dyadic) : toRat (x * y) = toRat x * toRat y := by
|
||||
match x, y with
|
||||
| .zero, _ => simp
|
||||
| _, .zero => simp
|
||||
| .ofOdd n₁ k₁ hn₁, .ofOdd n₂ k₂ hn₂ =>
|
||||
change (Dyadic.mul _ _).toRat = _
|
||||
rw [Dyadic.mul, toRat_ofOdd_eq_mkRat, toRat_ofOdd_eq_mkRat, toRat_ofOdd_eq_mkRat,
|
||||
Rat.mkRat_mul_mkRat, Rat.mkRat_eq_iff (NeZero.ne _) (NeZero.ne _)]
|
||||
simp only [Int.natCast_mul, Int.natCast_shiftLeft, Int.cast_ofNat_Int,
|
||||
Int.shiftLeft_mul_shiftLeft, Int.mul_one]
|
||||
congr 1; omega
|
||||
|
||||
@[simp]
|
||||
protected theorem pow_zero (x : Dyadic) : x ^ 0 = 1 := by
|
||||
change x.pow 0 = 1
|
||||
cases x <;> simp [Dyadic.pow] <;> rfl
|
||||
|
||||
protected theorem pow_succ (x : Dyadic) (n : Nat) : x ^ (n + 1) = x ^ n * x := by
|
||||
change x.pow (n + 1) = x.pow n * x
|
||||
cases x
|
||||
· simp [Dyadic.pow]
|
||||
· change _ = Dyadic.mul _ _
|
||||
simp [Dyadic.pow, Dyadic.mul, Int.pow_succ, Int.mul_add]
|
||||
|
||||
@[simp]
|
||||
theorem toRat_pow (x : Dyadic) (n : Nat) : toRat (x ^ n) = toRat x ^ n := by
|
||||
induction n with
|
||||
| zero => simp; rfl
|
||||
| succ k ih => simp [Dyadic.pow_succ, Rat.pow_succ, ih]
|
||||
|
||||
@[simp]
|
||||
theorem toRat_intCast (x : Int) : (x : Dyadic).toRat = x := by
|
||||
change (ofInt x).toRat = x
|
||||
simp [ofInt, toRat_ofIntWithPrec_eq_mul_two_pow]
|
||||
|
||||
@[simp]
|
||||
theorem toRat_natCast (x : Nat) : (x : Dyadic).toRat = x := by
|
||||
change (ofInt x).toRat = x
|
||||
simp [ofInt, toRat_ofIntWithPrec_eq_mul_two_pow, Rat.intCast_natCast]
|
||||
|
||||
@[simp] theorem of_ne_zero : ofOdd n k hn ≠ 0 := Dyadic.noConfusion
|
||||
@[simp] theorem zero_ne_of : 0 ≠ ofOdd n k hn := Dyadic.noConfusion
|
||||
|
||||
@[simp]
|
||||
theorem toRat_eq_zero_iff {x : Dyadic} : x.toRat = 0 ↔ x = 0 := by
|
||||
refine ⟨fun h => ?_, fun h => h ▸ rfl⟩
|
||||
cases x
|
||||
· rfl
|
||||
· simp only [toRat_ofOdd_eq_mkRat, ne_eq, shiftLeft_eq_zero_iff, succ_ne_self, not_false_eq_true,
|
||||
Rat.mkRat_eq_zero, Int.shiftLeft_eq_zero_iff] at h
|
||||
cases h
|
||||
contradiction
|
||||
|
||||
theorem ofOdd_eq_ofIntWithPrec : ofOdd n k hn = ofIntWithPrec n k := by
|
||||
simp only [ofIntWithPrec, Dyadic.zero_eq, Int.trailingZeros_eq_zero_of_mod_eq hn,
|
||||
Int.shiftRight_zero, Int.cast_ofNat_Int, Int.sub_zero, right_eq_dite_iff, of_ne_zero, imp_false]
|
||||
intro rfl; contradiction
|
||||
|
||||
theorem toRat_ofOdd_eq_mul_two_pow : toRat (.ofOdd n k hn) = n * 2 ^ (-k) := by
|
||||
rw [ofOdd_eq_ofIntWithPrec, toRat_ofIntWithPrec_eq_mul_two_pow]
|
||||
|
||||
@[simp]
|
||||
theorem ofIntWithPrec_zero {i : Int} : ofIntWithPrec 0 i = 0 := rfl
|
||||
|
||||
@[simp]
|
||||
theorem neg_ofOdd : -ofOdd n k hn = ofOdd (-n) k (by simpa using hn) := rfl
|
||||
|
||||
@[simp]
|
||||
theorem neg_ofIntWithPrec {i prec : Int} : -ofIntWithPrec i prec = ofIntWithPrec (-i) prec := by
|
||||
rw [ofIntWithPrec, ofIntWithPrec]
|
||||
simp only [Dyadic.zero_eq, Int.neg_eq_zero, Int.trailingZeros_neg]
|
||||
split
|
||||
· rfl
|
||||
· obtain ⟨a, h⟩ := Int.two_pow_trailingZeros_dvd ‹_›
|
||||
rw [Int.mul_comm, ← Int.shiftLeft_eq] at h
|
||||
conv => enter [1, 1, 1, 1]; rw [h]
|
||||
conv => enter [2, 1, 1]; rw [h]
|
||||
simp only [Int.shiftLeft_shiftRight_cancel, neg_ofOdd, ← Int.neg_shiftLeft]
|
||||
|
||||
theorem ofIntWithPrec_shiftLeft_add {n : Nat} :
|
||||
ofIntWithPrec ((x : Int) <<< n) (i + n) = ofIntWithPrec x i := by
|
||||
rw [ofIntWithPrec, ofIntWithPrec]
|
||||
simp only [Int.shiftLeft_eq_zero_iff]
|
||||
split
|
||||
· rfl
|
||||
· simp [Int.trailingZeros_shiftLeft, *, Int.shiftLeft_shiftRight_eq_shiftRight_of_le,
|
||||
Int.add_comm x.trailingZeros n, ← Int.sub_sub]
|
||||
|
||||
/-- The "precision" of a dyadic number, i.e. in `n * 2^(-p)` with `n` odd the precision is `p`. -/
|
||||
-- TODO: If `WithBot` is upstreamed, replace this with `WithBot Int`.
|
||||
def precision : Dyadic → Option Int
|
||||
| .zero => none
|
||||
| .ofOdd _ p _ => some p
|
||||
|
||||
theorem precision_ofIntWithPrec_le {i : Int} (h : i ≠ 0) (prec : Int) :
|
||||
(ofIntWithPrec i prec).precision ≤ some prec := by
|
||||
simp [ofIntWithPrec, h, precision]
|
||||
omega
|
||||
|
||||
@[simp] theorem precision_zero : (0 : Dyadic).precision = none := rfl
|
||||
@[simp] theorem precision_neg {x : Dyadic} : (-x).precision = x.precision :=
|
||||
match x with
|
||||
| .zero => rfl
|
||||
| .ofOdd _ _ _ => rfl
|
||||
|
||||
/--
|
||||
Convert a rational number `x` to the greatest dyadic number with precision at most `prec`
|
||||
which is less than or equal to `x`.
|
||||
-/
|
||||
def _root_.Rat.toDyadic (x : Rat) (prec : Int) : Dyadic :=
|
||||
match prec with
|
||||
| (n : Nat) => .ofIntWithPrec ((x.num <<< n) / x.den) prec
|
||||
| -(n + 1 : Nat) => .ofIntWithPrec (x.num / (x.den <<< (n + 1))) prec
|
||||
|
||||
theorem _root_.Rat.toDyadic_mkRat (a : Int) (b : Nat) (prec : Int) :
|
||||
Rat.toDyadic (mkRat a b) prec =
|
||||
.ofIntWithPrec ((a <<< prec.toNat) / (b <<< (-prec).toNat)) prec := by
|
||||
by_cases hb : b = 0
|
||||
· cases prec <;> simp [hb, Rat.toDyadic]
|
||||
rcases h : mkRat a b with ⟨n, d, hnz, hr⟩
|
||||
obtain ⟨m, hm, rfl, rfl⟩ := Rat.mkRat_num_den hb h
|
||||
cases prec
|
||||
· simp only [Rat.toDyadic, Int.ofNat_eq_coe, Int.toNat_natCast, Int.toNat_neg_nat,
|
||||
shiftLeft_zero, Int.natCast_mul]
|
||||
rw [Int.mul_comm d, ← Int.ediv_ediv (by simp), ← Int.shiftLeft_mul,
|
||||
Int.mul_ediv_cancel _ (by simpa using hm)]
|
||||
· simp only [Rat.toDyadic, Int.natCast_shiftLeft, Int.negSucc_eq, ← Int.natCast_add_one,
|
||||
Int.toNat_neg_nat, Int.shiftLeft_zero, Int.neg_neg, Int.toNat_natCast, Int.natCast_mul]
|
||||
rw [Int.mul_comm d, ← Int.mul_shiftLeft, ← Int.ediv_ediv (by simp),
|
||||
Int.mul_ediv_cancel _ (by simpa using hm)]
|
||||
|
||||
/--
|
||||
Rounds a dyadic rational `x` down to the greatest dyadic number with precision at most `prec`
|
||||
which is less than or equal to `x`.
|
||||
-/
|
||||
def roundDown (x : Dyadic) (prec : Int) : Dyadic :=
|
||||
match x with
|
||||
| .zero => .zero
|
||||
| .ofOdd n k _ =>
|
||||
match k - prec with
|
||||
| .ofNat l => .ofIntWithPrec (n >>> l) prec
|
||||
| .negSucc _ => x
|
||||
|
||||
theorem roundDown_eq_self_of_le {x : Dyadic} {prec : Int} (h : x.precision ≤ some prec) :
|
||||
roundDown x prec = x := by
|
||||
rcases x with _ | ⟨n, k, hn⟩
|
||||
· rfl
|
||||
· simp only [precision] at h
|
||||
obtain ⟨a, rfl⟩ := h.dest
|
||||
rcases a with _ | a
|
||||
· simp [roundDown, ofOdd_eq_ofIntWithPrec]
|
||||
· have : k - (k + (a + 1 : Nat)) = Int.negSucc a := by omega
|
||||
simp only [roundDown, this]
|
||||
|
||||
@[simp]
|
||||
theorem toDyadic_toRat (x : Dyadic) (prec : Int) :
|
||||
x.toRat.toDyadic prec = x.roundDown prec := by
|
||||
rcases x with _ | ⟨n, k, hn⟩
|
||||
· cases prec <;> simp [Rat.toDyadic, roundDown]
|
||||
· simp only [toRat_ofOdd_eq_mkRat, roundDown]
|
||||
rw [Rat.toDyadic_mkRat]
|
||||
simp only [← Int.shiftLeft_add, Int.natCast_shiftLeft, Int.cast_ofNat_Int]
|
||||
rw [Int.shiftLeft_eq' 1, Int.one_mul, ← Int.shiftRight_eq_div_pow]
|
||||
rw [Int.shiftLeft_shiftRight_eq, ← Int.toNat_sub, ← Int.toNat_sub, ← Int.neg_sub]
|
||||
have : ((k.toNat + (-prec).toNat : Nat) - ((-k).toNat + prec.toNat : Nat) : Int) = k - prec := by
|
||||
omega
|
||||
rw [this]
|
||||
cases h : k - prec
|
||||
· simp
|
||||
· simp
|
||||
rw [Int.negSucc_eq, Int.eq_neg_comm, Int.neg_sub, eq_comm, Int.sub_eq_iff_eq_add] at h
|
||||
simp only [Int.neg_negSucc, h, ← Int.natCast_add_one, Int.add_comm _ k,
|
||||
Nat.succ_eq_add_one, Int.toNat_natCast, ofIntWithPrec_shiftLeft_add, ofOdd_eq_ofIntWithPrec]
|
||||
|
||||
theorem toRat_inj {x y : Dyadic} : x.toRat = y.toRat ↔ x = y := by
|
||||
refine ⟨fun h => ?_, fun h => h ▸ rfl⟩
|
||||
cases x <;> cases y
|
||||
· rfl
|
||||
· simp [eq_comm (a := (0 : Rat))] at h
|
||||
· simp at h
|
||||
· rename_i n₁ k₁ hn₁ n₂ k₂ hn₂
|
||||
replace h := congrArg (·.toDyadic (max k₁ k₂)) h
|
||||
simpa [toDyadic_toRat, roundDown_eq_self_of_le, precision, Int.le_max_left, Int.le_max_right]
|
||||
using h
|
||||
|
||||
theorem add_comm (x y : Dyadic) : x + y = y + x := by
|
||||
rw [← toRat_inj, toRat_add, toRat_add, Rat.add_comm]
|
||||
|
||||
theorem add_assoc (x y z : Dyadic) : (x + y) + z = x + (y + z) := by
|
||||
rw [← toRat_inj, toRat_add, toRat_add, toRat_add, toRat_add, Rat.add_assoc]
|
||||
|
||||
theorem mul_comm (x y : Dyadic) : x * y = y * x := by
|
||||
rw [← toRat_inj, toRat_mul, toRat_mul, Rat.mul_comm]
|
||||
|
||||
theorem mul_assoc (x y z : Dyadic) : (x * y) * z = x * (y * z) := by
|
||||
rw [← toRat_inj, toRat_mul, toRat_mul, toRat_mul, toRat_mul, Rat.mul_assoc]
|
||||
|
||||
theorem mul_one (x : Dyadic) : x * 1 = x := by
|
||||
rw [← toRat_inj, toRat_mul]
|
||||
exact Rat.mul_one x.toRat
|
||||
|
||||
theorem one_mul (x : Dyadic) : 1 * x = x := by
|
||||
rw [← toRat_inj, toRat_mul]
|
||||
exact Rat.one_mul x.toRat
|
||||
|
||||
theorem add_mul (x y z : Dyadic) : (x + y) * z = x * z + y * z := by
|
||||
simp [← toRat_inj, Rat.add_mul]
|
||||
|
||||
theorem mul_add (x y z : Dyadic) : x * (y + z) = x * y + x * z := by
|
||||
simp [← toRat_inj, Rat.mul_add]
|
||||
|
||||
theorem neg_add_cancel (x : Dyadic) : -x + x = 0 := by
|
||||
simp [← toRat_inj, Rat.neg_add_cancel]
|
||||
|
||||
theorem neg_mul (x y : Dyadic) : -x * y = -(x * y) := by
|
||||
simp [← toRat_inj, Rat.neg_mul]
|
||||
|
||||
/-- Determine if a dyadic rational is strictly less than another. -/
|
||||
def blt (x y : Dyadic) : Bool :=
|
||||
match x, y with
|
||||
| .zero, .zero => false
|
||||
| .zero, .ofOdd n₂ _ _ => 0 < n₂
|
||||
| .ofOdd n₁ _ _, .zero => n₁ < 0
|
||||
| .ofOdd n₁ k₁ _, .ofOdd n₂ k₂ _ =>
|
||||
match k₂ - k₁ with
|
||||
| (l : Nat) => (n₁ <<< l) < n₂
|
||||
| -((l+1 : Nat)) => n₁ < (n₂ <<< (l + 1))
|
||||
|
||||
/-- Determine if a dyadic rational is less than or equal to another. -/
|
||||
def ble (x y : Dyadic) : Bool :=
|
||||
match x, y with
|
||||
| .zero, .zero => true
|
||||
| .zero, .ofOdd n₂ _ _ => 0 ≤ n₂
|
||||
| .ofOdd n₁ _ _, .zero => n₁ ≤ 0
|
||||
| .ofOdd n₁ k₁ _, .ofOdd n₂ k₂ _ =>
|
||||
match k₂ - k₁ with
|
||||
| (l : Nat) => (n₁ <<< l) ≤ n₂
|
||||
| -((l+1 : Nat)) => n₁ ≤ (n₂ <<< (l + 1))
|
||||
|
||||
theorem blt_iff_toRat {x y : Dyadic} : blt x y ↔ x.toRat < y.toRat := by
|
||||
rcases x with _ | ⟨n₁, k₁, hn₁⟩ <;> rcases y with _ | ⟨n₂, k₂, hn₂⟩
|
||||
· decide
|
||||
· simp only [blt, decide_eq_true_eq, Dyadic.zero_eq, toRat_zero, toRat_ofOdd_eq_mul_two_pow,
|
||||
Rat.mul_pos_iff_of_pos_right (Rat.zpow_pos (by decide : (0 : Rat) < 2)), Rat.intCast_pos]
|
||||
· simp only [blt, decide_eq_true_eq, Dyadic.zero_eq, toRat_zero, toRat_ofOdd_eq_mul_two_pow,
|
||||
Rat.mul_neg_iff_of_pos_right (Rat.zpow_pos (by decide : (0 : Rat) < 2)), Rat.intCast_neg_iff]
|
||||
· simp only [blt, toRat_ofOdd_eq_mul_two_pow,
|
||||
← Rat.div_lt_iff (Rat.zpow_pos (by decide : (0 : Rat) < 2)), Rat.div_def, ← Rat.zpow_neg,
|
||||
Int.neg_neg, Rat.mul_assoc, ne_eq, Rat.ofNat_eq_ofNat, reduceCtorEq, not_false_eq_true,
|
||||
← Rat.zpow_add, Int.shiftLeft_eq]
|
||||
rw [Int.add_comm, Int.add_neg_eq_sub]
|
||||
split
|
||||
· simp [decide_eq_true_eq, ← Rat.intCast_lt_intCast, Rat.zpow_natCast, *]
|
||||
· simp only [decide_eq_true_eq, Int.negSucc_eq, *]
|
||||
rw [Rat.zpow_neg, ← Rat.div_def, Rat.div_lt_iff (Rat.zpow_pos (by decide))]
|
||||
simp [← Rat.intCast_lt_intCast, ← Rat.zpow_natCast, *]
|
||||
|
||||
theorem blt_eq_false_iff : blt x y = false ↔ ble y x = true := by
|
||||
cases x <;> cases y
|
||||
· simp [ble, blt]
|
||||
· simp [ble, blt]
|
||||
· simp [ble, blt]
|
||||
· rename_i n₁ k₁ hn₁ n₂ k₂ hn₂
|
||||
simp only [blt, ble]
|
||||
rw [← Int.neg_sub]
|
||||
rcases k₁ - k₂ with (_ | _) | _
|
||||
· simp
|
||||
· simp [← Int.negSucc_eq]
|
||||
· simp only [Int.neg_negSucc, succ_eq_add_one, decide_eq_false_iff_not, Int.not_lt,
|
||||
decide_eq_true_eq]
|
||||
|
||||
theorem ble_iff_toRat : ble x y ↔ x.toRat ≤ y.toRat := by
|
||||
rw [← blt_eq_false_iff, Bool.eq_false_iff]
|
||||
simp only [ne_eq, blt_iff_toRat, Rat.not_lt]
|
||||
|
||||
instance : LT Dyadic where
|
||||
lt x y := blt x y
|
||||
|
||||
instance : LE Dyadic where
|
||||
le x y := ble x y
|
||||
|
||||
instance : DecidableLT Dyadic := fun _ _ => inferInstanceAs (Decidable (_ = true))
|
||||
instance : DecidableLE Dyadic := fun _ _ => inferInstanceAs (Decidable (_ = true))
|
||||
|
||||
theorem lt_iff_toRat {x y : Dyadic} : x < y ↔ x.toRat < y.toRat := blt_iff_toRat
|
||||
|
||||
theorem le_iff_toRat {x y : Dyadic} : x ≤ y ↔ x.toRat ≤ y.toRat := ble_iff_toRat
|
||||
|
||||
@[simp]
|
||||
protected theorem not_le {x y : Dyadic} : ¬x < y ↔ y ≤ x := by
|
||||
simp only [· ≤ ·, · < ·, Bool.not_eq_true, blt_eq_false_iff]
|
||||
|
||||
@[simp]
|
||||
protected theorem not_lt {x y : Dyadic} : ¬x ≤ y ↔ y < x := by
|
||||
rw [← Dyadic.not_le, Decidable.not_not]
|
||||
|
||||
@[simp]
|
||||
protected theorem le_refl (x : Dyadic) : x ≤ x := by
|
||||
rw [le_iff_toRat]
|
||||
exact Rat.le_refl
|
||||
|
||||
protected theorem le_trans {x y z : Dyadic} (h : x ≤ y) (h' : y ≤ z) : x ≤ z := by
|
||||
rw [le_iff_toRat] at h h' ⊢
|
||||
exact Rat.le_trans h h'
|
||||
|
||||
protected theorem le_antisymm {x y : Dyadic} (h : x ≤ y) (h' : y ≤ x) : x = y := by
|
||||
rw [le_iff_toRat] at h h'
|
||||
rw [← toRat_inj]
|
||||
exact Rat.le_antisymm h h'
|
||||
|
||||
protected theorem le_total (x y : Dyadic) : x ≤ y ∨ y ≤ x := by
|
||||
rw [le_iff_toRat, le_iff_toRat]
|
||||
exact Rat.le_total
|
||||
|
||||
instance : Std.LawfulOrderLT Dyadic where
|
||||
lt_iff a b := by rw [← Dyadic.not_lt, iff_and_self]; exact (Dyadic.le_total _ _).resolve_left
|
||||
|
||||
instance : Std.IsPreorder Dyadic where
|
||||
le_refl := Dyadic.le_refl
|
||||
le_trans _ _ _ := Dyadic.le_trans
|
||||
|
||||
instance : Std.IsPartialOrder Dyadic where
|
||||
le_antisymm _ _ := Dyadic.le_antisymm
|
||||
|
||||
instance : Std.IsLinearPreorder Dyadic where
|
||||
le_total := Dyadic.le_total
|
||||
|
||||
instance : Std.IsLinearOrder Dyadic where
|
||||
|
||||
/-- `roundUp x prec` is the least dyadic number with precision at most `prec` which is greater than or equal to `x`. -/
|
||||
def roundUp (x : Dyadic) (prec : Int) : Dyadic :=
|
||||
match x with
|
||||
| .zero => .zero
|
||||
| .ofOdd n k _ =>
|
||||
match k - prec with
|
||||
| .ofNat l => .ofIntWithPrec (-((-n) >>> l)) prec
|
||||
| .negSucc _ => x
|
||||
|
||||
theorem roundUp_eq_neg_roundDown_neg (x : Dyadic) (prec : Int) :
|
||||
x.roundUp prec = -((-x).roundDown prec) := by
|
||||
rcases x with _ | ⟨n, k, hn⟩
|
||||
· rfl
|
||||
· change _ = -(ofOdd ..).roundDown prec
|
||||
rw [roundDown, roundUp]
|
||||
split <;> simp
|
||||
|
||||
end Dyadic
|
||||
60
src/Init/Data/Dyadic/Instances.lean
Normal file
60
src/Init/Data/Dyadic/Instances.lean
Normal file
@@ -0,0 +1,60 @@
|
||||
/-
|
||||
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Kim Morrison, Robin Arnez
|
||||
-/
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Dyadic.Basic
|
||||
public import Init.Grind.Ring.Basic
|
||||
public import Init.Grind.Ordered.Ring
|
||||
|
||||
/-! # Internal `grind` algebra instances for `Dyadic`. -/
|
||||
|
||||
open Lean.Grind
|
||||
|
||||
namespace Dyadic
|
||||
|
||||
instance : CommRing Dyadic where
|
||||
nsmul := ⟨(· * ·)⟩
|
||||
zsmul := ⟨(· * ·)⟩
|
||||
add_zero := Dyadic.add_zero
|
||||
add_comm := Dyadic.add_comm
|
||||
add_assoc := Dyadic.add_assoc
|
||||
mul_assoc := Dyadic.mul_assoc
|
||||
mul_one := Dyadic.mul_one
|
||||
one_mul := Dyadic.one_mul
|
||||
zero_mul := Dyadic.zero_mul
|
||||
mul_zero := Dyadic.mul_zero
|
||||
mul_comm := Dyadic.mul_comm
|
||||
pow_zero := Dyadic.pow_zero
|
||||
pow_succ := Dyadic.pow_succ
|
||||
sub_eq_add_neg _ _ := rfl
|
||||
neg_add_cancel := Dyadic.neg_add_cancel
|
||||
neg_zsmul i a := by
|
||||
change ((-i : Int) : Dyadic) * a = -(i * a)
|
||||
simp [← toRat_inj, Rat.neg_mul]
|
||||
left_distrib := Dyadic.mul_add
|
||||
right_distrib := Dyadic.add_mul
|
||||
intCast_neg _ := by simp [← toRat_inj]
|
||||
ofNat_succ n := by
|
||||
change ((n + 1 : Int) : Dyadic) = ((n : Int) : Dyadic) + 1
|
||||
simp [← toRat_inj, Rat.intCast_add]; rfl
|
||||
|
||||
instance : IsCharP Dyadic 0 := IsCharP.mk' _ _
|
||||
(ofNat_eq_zero_iff := fun x => by change (x : Dyadic) = 0 ↔ _; simp [← toRat_inj])
|
||||
|
||||
instance : NoNatZeroDivisors Dyadic where
|
||||
no_nat_zero_divisors k a b h₁ h₂ := by
|
||||
change k * a = k * b at h₂
|
||||
simp only [← toRat_inj, toRat_mul, toRat_natCast] at h₂ ⊢
|
||||
simpa [← Rat.mul_assoc, Rat.inv_mul_cancel, h₁] using congrArg ((k : Rat)⁻¹ * ·) h₂
|
||||
|
||||
instance : OrderedRing Dyadic where
|
||||
zero_lt_one := by decide
|
||||
add_le_left_iff _ := by simp [le_iff_toRat, Rat.add_le_add_right]
|
||||
mul_lt_mul_of_pos_left {_ _ _} := by simpa [lt_iff_toRat] using Rat.mul_lt_mul_of_pos_left
|
||||
mul_lt_mul_of_pos_right {_ _ _} := by simpa [lt_iff_toRat] using Rat.mul_lt_mul_of_pos_right
|
||||
|
||||
end Dyadic
|
||||
77
src/Init/Data/Dyadic/Round.lean
Normal file
77
src/Init/Data/Dyadic/Round.lean
Normal file
@@ -0,0 +1,77 @@
|
||||
/-
|
||||
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Kim Morrison
|
||||
-/
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Dyadic.Basic
|
||||
import all Init.Data.Dyadic.Instances
|
||||
import Init.Data.Int.Bitwise.Lemmas
|
||||
import Init.Grind.Ordered.Rat
|
||||
import Init.Grind.Ordered.Field
|
||||
|
||||
namespace Dyadic
|
||||
|
||||
/-!
|
||||
Theorems about `roundUp` and `roundDown`.
|
||||
-/
|
||||
|
||||
public section
|
||||
|
||||
theorem roundDown_le {x : Dyadic} {prec : Int} : roundDown x prec ≤ x :=
|
||||
match x with
|
||||
| .zero => Dyadic.le_refl _
|
||||
| .ofOdd n k _ => by
|
||||
unfold roundDown
|
||||
dsimp
|
||||
match h : k - prec with
|
||||
| .ofNat l =>
|
||||
dsimp
|
||||
rw [ofOdd_eq_ofIntWithPrec, le_iff_toRat]
|
||||
replace h : k = Int.ofNat l + prec := by omega
|
||||
subst h
|
||||
simp only [toRat_ofIntWithPrec_eq_mul_two_pow]
|
||||
rw [Int.neg_add, Rat.zpow_add (by decide), ← Rat.mul_assoc]
|
||||
refine Lean.Grind.OrderedRing.mul_le_mul_of_nonneg_right ?_ (Rat.zpow_nonneg (by decide))
|
||||
rw [Int.shiftRight_eq_div_pow]
|
||||
rw [← Lean.Grind.Field.IsOrdered.mul_le_mul_iff_of_pos_right (c := 2^(Int.ofNat l)) (Rat.zpow_pos (by decide))]
|
||||
simp only [Int.natCast_pow, Int.cast_ofNat_Int, Int.ofNat_eq_coe]
|
||||
rw [Rat.mul_assoc, ← Rat.zpow_add (by decide), Int.add_left_neg, Rat.zpow_zero, Rat.mul_one]
|
||||
have : (2 : Rat) ^ (l : Int) = (2 ^ l : Int) := by
|
||||
rw [Rat.zpow_natCast, Rat.intCast_pow, Rat.intCast_ofNat]
|
||||
rw [this, ← Rat.intCast_mul, Rat.intCast_le_intCast]
|
||||
exact Int.ediv_mul_le n (Int.pow_ne_zero (by decide))
|
||||
| .negSucc _ =>
|
||||
apply Dyadic.le_refl
|
||||
|
||||
theorem precision_roundDown {x : Dyadic} {prec : Int} : (roundDown x prec).precision ≤ some prec := by
|
||||
unfold roundDown
|
||||
match x with
|
||||
| zero => simp [precision]
|
||||
| ofOdd n k hn =>
|
||||
dsimp
|
||||
split
|
||||
· rename_i n' h
|
||||
by_cases h' : n >>> n' = 0
|
||||
· simp [h']
|
||||
· exact precision_ofIntWithPrec_le h' _
|
||||
· simp [precision]
|
||||
omega
|
||||
|
||||
-- This theorem would characterize `roundDown` in terms of the order and `precision`.
|
||||
-- theorem le_roundDown {x y : Dyadic} {prec : Int} (h : y.precision ≤ some prec) (h' : y ≤ x) :
|
||||
-- y ≤ x.roundDown prec := sorry
|
||||
|
||||
theorem le_roundUp {x : Dyadic} {prec : Int} : x ≤ roundUp x prec := by
|
||||
rw [roundUp_eq_neg_roundDown_neg, Lean.Grind.OrderedAdd.le_neg_iff]
|
||||
apply roundDown_le
|
||||
|
||||
theorem precision_roundUp {x : Dyadic} {prec : Int} : (roundUp x prec).precision ≤ some prec := by
|
||||
rw [roundUp_eq_neg_roundDown_neg, precision_neg]
|
||||
exact precision_roundDown
|
||||
|
||||
-- This theorem would characterize `roundUp` in terms of the order and `precision`.
|
||||
-- theorem roundUp_le {x y : Dyadic} {prec : Int} (h : y.precision ≤ some prec) (h' : x ≤ y) :
|
||||
-- x.roundUp prec ≤ y := sorry
|
||||
@@ -221,7 +221,7 @@ instance : AndOp (Fin n) where
|
||||
and := Fin.land
|
||||
instance : OrOp (Fin n) where
|
||||
or := Fin.lor
|
||||
instance : Xor (Fin n) where
|
||||
instance : XorOp (Fin n) where
|
||||
xor := Fin.xor
|
||||
instance : ShiftLeft (Fin n) where
|
||||
shiftLeft := Fin.shiftLeft
|
||||
|
||||
@@ -107,14 +107,14 @@ Fin.foldrM n f xₙ = do
|
||||
subst w
|
||||
rfl
|
||||
|
||||
theorem foldlM_loop_lt [Monad m] (f : α → Fin n → m α) (x) (h : i < n) :
|
||||
private theorem foldlM_loop_lt [Monad m] (f : α → Fin n → m α) (x) (h : i < n) :
|
||||
foldlM.loop n f x i = f x ⟨i, h⟩ >>= (foldlM.loop n f . (i+1)) := by
|
||||
rw [foldlM.loop, dif_pos h]
|
||||
|
||||
theorem foldlM_loop_eq [Monad m] (f : α → Fin n → m α) (x) : foldlM.loop n f x n = pure x := by
|
||||
private theorem foldlM_loop_eq [Monad m] (f : α → Fin n → m α) (x) : foldlM.loop n f x n = pure x := by
|
||||
rw [foldlM.loop, dif_neg (Nat.lt_irrefl _)]
|
||||
|
||||
theorem foldlM_loop [Monad m] (f : α → Fin (n+1) → m α) (x) (h : i < n+1) :
|
||||
private theorem foldlM_loop [Monad m] (f : α → Fin (n+1) → m α) (x) (h : i < n+1) :
|
||||
foldlM.loop (n+1) f x i = f x ⟨i, h⟩ >>= (foldlM.loop n (fun x j => f x j.succ) . i) := by
|
||||
if h' : i < n then
|
||||
rw [foldlM_loop_lt _ _ h]
|
||||
@@ -170,15 +170,15 @@ theorem foldlM_add [Monad m] [LawfulMonad m] (f : α → Fin (n + k) → m α) :
|
||||
subst w
|
||||
rfl
|
||||
|
||||
theorem foldrM_loop_zero [Monad m] (f : Fin n → α → m α) (x) :
|
||||
private theorem foldrM_loop_zero [Monad m] (f : Fin n → α → m α) (x) :
|
||||
foldrM.loop n f ⟨0, Nat.zero_le _⟩ x = pure x := by
|
||||
rw [foldrM.loop]
|
||||
|
||||
theorem foldrM_loop_succ [Monad m] (f : Fin n → α → m α) (x) (h : i < n) :
|
||||
private theorem foldrM_loop_succ [Monad m] (f : Fin n → α → m α) (x) (h : i < n) :
|
||||
foldrM.loop n f ⟨i+1, h⟩ x = f ⟨i, h⟩ x >>= foldrM.loop n f ⟨i, Nat.le_of_lt h⟩ := by
|
||||
rw [foldrM.loop]
|
||||
|
||||
theorem foldrM_loop [Monad m] [LawfulMonad m] (f : Fin (n+1) → α → m α) (x) (h : i+1 ≤ n+1) :
|
||||
private theorem foldrM_loop [Monad m] [LawfulMonad m] (f : Fin (n+1) → α → m α) (x) (h : i+1 ≤ n+1) :
|
||||
foldrM.loop (n+1) f ⟨i+1, h⟩ x =
|
||||
foldrM.loop n (fun j => f j.succ) ⟨i, Nat.le_of_succ_le_succ h⟩ x >>= f 0 := by
|
||||
induction i generalizing x with
|
||||
@@ -228,14 +228,14 @@ theorem foldrM_add [Monad m] [LawfulMonad m] (f : Fin (n + k) → α → m α) :
|
||||
subst w
|
||||
rfl
|
||||
|
||||
theorem foldl_loop_lt (f : α → Fin n → α) (x) (h : i < n) :
|
||||
private theorem foldl_loop_lt (f : α → Fin n → α) (x) (h : i < n) :
|
||||
foldl.loop n f x i = foldl.loop n f (f x ⟨i, h⟩) (i+1) := by
|
||||
rw [foldl.loop, dif_pos h]
|
||||
|
||||
theorem foldl_loop_eq (f : α → Fin n → α) (x) : foldl.loop n f x n = x := by
|
||||
private theorem foldl_loop_eq (f : α → Fin n → α) (x) : foldl.loop n f x n = x := by
|
||||
rw [foldl.loop, dif_neg (Nat.lt_irrefl _)]
|
||||
|
||||
theorem foldl_loop (f : α → Fin (n+1) → α) (x) (h : i < n+1) :
|
||||
private theorem foldl_loop (f : α → Fin (n+1) → α) (x) (h : i < n+1) :
|
||||
foldl.loop (n+1) f x i = foldl.loop n (fun x j => f x j.succ) (f x ⟨i, h⟩) i := by
|
||||
if h' : i < n then
|
||||
rw [foldl_loop_lt _ _ h]
|
||||
@@ -285,15 +285,15 @@ theorem foldlM_pure [Monad m] [LawfulMonad m] {n} {f : α → Fin n → α} :
|
||||
subst w
|
||||
rfl
|
||||
|
||||
theorem foldr_loop_zero (f : Fin n → α → α) (x) :
|
||||
private theorem foldr_loop_zero (f : Fin n → α → α) (x) :
|
||||
foldr.loop n f 0 (Nat.zero_le _) x = x := by
|
||||
rw [foldr.loop]
|
||||
|
||||
theorem foldr_loop_succ (f : Fin n → α → α) (x) (h : i < n) :
|
||||
private theorem foldr_loop_succ (f : Fin n → α → α) (x) (h : i < n) :
|
||||
foldr.loop n f (i+1) h x = foldr.loop n f i (Nat.le_of_lt h) (f ⟨i, h⟩ x) := by
|
||||
rw [foldr.loop]
|
||||
|
||||
theorem foldr_loop (f : Fin (n+1) → α → α) (x) (h : i+1 ≤ n+1) :
|
||||
private theorem foldr_loop (f : Fin (n+1) → α → α) (x) (h : i+1 ≤ n+1) :
|
||||
foldr.loop (n+1) f (i+1) h x =
|
||||
f 0 (foldr.loop n (fun j => f j.succ) i (Nat.le_of_succ_le_succ h) x) := by
|
||||
induction i generalizing x with
|
||||
|
||||
@@ -12,9 +12,13 @@ public import Init.Ext
|
||||
public import Init.ByCases
|
||||
public import Init.Conv
|
||||
public import Init.Omega
|
||||
public import Init.Data.Order.Factories
|
||||
import Init.Data.Order.Lemmas
|
||||
|
||||
public section
|
||||
|
||||
open Std
|
||||
|
||||
namespace Fin
|
||||
|
||||
@[simp] theorem ofNat_zero (n : Nat) [NeZero n] : Fin.ofNat n 0 = 0 := rfl
|
||||
@@ -251,6 +255,16 @@ protected theorem le_antisymm_iff {x y : Fin n} : x = y ↔ x ≤ y ∧ y ≤ x
|
||||
protected theorem le_antisymm {x y : Fin n} (h1 : x ≤ y) (h2 : y ≤ x) : x = y :=
|
||||
Fin.le_antisymm_iff.2 ⟨h1, h2⟩
|
||||
|
||||
instance instIsLinearOrder : IsLinearOrder (Fin n) := by
|
||||
apply IsLinearOrder.of_le
|
||||
case le_antisymm => constructor; apply Fin.le_antisymm
|
||||
case le_total => constructor; apply Fin.le_total
|
||||
case le_trans => constructor; apply Fin.le_trans
|
||||
|
||||
instance : LawfulOrderLT (Fin n) where
|
||||
lt_iff := by
|
||||
simp [← Fin.not_le, Decidable.imp_iff_not_or, Std.Total.total]
|
||||
|
||||
@[simp, grind =] theorem val_rev (i : Fin n) : rev i = n - (i + 1) := rfl
|
||||
|
||||
@[simp] theorem rev_rev (i : Fin n) : rev (rev i) = i := Fin.ext <| by
|
||||
@@ -927,24 +941,34 @@ For the induction:
|
||||
-/
|
||||
@[elab_as_elim] def reverseInduction {motive : Fin (n + 1) → Sort _} (last : motive (Fin.last n))
|
||||
(cast : ∀ i : Fin n, motive i.succ → motive (castSucc i)) (i : Fin (n + 1)) : motive i :=
|
||||
if hi : i = Fin.last n then _root_.cast (congrArg motive hi.symm) last
|
||||
else
|
||||
let j : Fin n := ⟨i, Nat.lt_of_le_of_ne (Nat.le_of_lt_succ i.2) fun h => hi (Fin.ext h)⟩
|
||||
cast _ (reverseInduction last cast j.succ)
|
||||
termination_by n + 1 - i
|
||||
decreasing_by decreasing_with
|
||||
-- FIXME: we put the proof down here to avoid getting a dummy `have` in the definition
|
||||
try simp only [Nat.succ_sub_succ_eq_sub]
|
||||
exact Nat.add_sub_add_right .. ▸ Nat.sub_lt_sub_left i.2 (Nat.lt_succ_self i)
|
||||
let rec go (j : Nat) (h) (h2 : i ≤ j) (x : motive ⟨j, h⟩) : motive i :=
|
||||
if hi : i.1 = j then _root_.cast (by simp [← hi]) x
|
||||
else match j with
|
||||
| 0 => by omega
|
||||
| j + 1 => go j (by omega) (by omega) (cast ⟨j, by omega⟩ x)
|
||||
go _ _ (by omega) last
|
||||
|
||||
@[simp] theorem reverseInduction_last {n : Nat} {motive : Fin (n + 1) → Sort _} {zero succ} :
|
||||
(reverseInduction zero succ (Fin.last n) : motive (Fin.last n)) = zero := by
|
||||
rw [reverseInduction]; simp
|
||||
rw [reverseInduction, reverseInduction.go]; simp
|
||||
|
||||
private theorem reverseInduction_castSucc_aux {n : Nat} {motive : Fin (n + 1) → Sort _} {succ}
|
||||
(i : Fin n) (j : Nat) (h) (h2 : i.1 < j) (zero : motive ⟨j, h⟩) :
|
||||
reverseInduction.go (motive := motive) succ i.castSucc j h (Nat.le_of_lt h2) zero =
|
||||
succ i (reverseInduction.go succ i.succ j h h2 zero) := by
|
||||
induction j generalizing i with
|
||||
| zero => omega
|
||||
| succ j ih =>
|
||||
rw [reverseInduction.go, dif_neg (by exact Nat.ne_of_lt h2)]
|
||||
by_cases hij : i = j
|
||||
· subst hij; simp [reverseInduction.go]
|
||||
dsimp only
|
||||
rw [ih _ _ (by omega), eq_comm, reverseInduction.go, dif_neg (by change i.1 + 1 ≠ _; omega)]
|
||||
|
||||
@[simp] theorem reverseInduction_castSucc {n : Nat} {motive : Fin (n + 1) → Sort _} {zero succ}
|
||||
(i : Fin n) : reverseInduction (motive := motive) zero succ (castSucc i) =
|
||||
succ i (reverseInduction zero succ i.succ) := by
|
||||
rw [reverseInduction, dif_neg (Fin.ne_of_lt (Fin.castSucc_lt_last i))]; rfl
|
||||
rw [reverseInduction, reverseInduction_castSucc_aux _ _ _ i.isLt, reverseInduction]
|
||||
|
||||
/--
|
||||
Proves a statement by cases on the underlying `Nat` value in a `Fin (n + 1)`, checking whether the
|
||||
|
||||
@@ -30,6 +30,7 @@ opaque floatSpec : FloatSpec := {
|
||||
decLe := fun _ _ => inferInstanceAs (Decidable True)
|
||||
}
|
||||
|
||||
set_option genInjectivity false in
|
||||
/--
|
||||
64-bit floating-point numbers.
|
||||
|
||||
@@ -500,3 +501,5 @@ This function does not reduce in the kernel.
|
||||
-/
|
||||
@[extern "lean_float_scaleb"]
|
||||
opaque Float.scaleB (x : Float) (i : @& Int) : Float
|
||||
|
||||
gen_injective_theorems% Float
|
||||
|
||||
@@ -23,6 +23,7 @@ opaque float32Spec : FloatSpec := {
|
||||
decLe := fun _ _ => inferInstanceAs (Decidable True)
|
||||
}
|
||||
|
||||
set_option genInjectivity false in
|
||||
/--
|
||||
32-bit floating-point numbers.
|
||||
|
||||
@@ -513,3 +514,5 @@ This may lose precision.
|
||||
This function does not reduce in the kernel.
|
||||
-/
|
||||
@[extern "lean_float_to_float32"] opaque Float.toFloat32 : Float → Float32
|
||||
|
||||
gen_injective_theorems% Float32
|
||||
|
||||
@@ -15,12 +15,15 @@ public import Init.Data.Array.DecidableEq
|
||||
public section
|
||||
universe u
|
||||
|
||||
set_option genInjectivity false in
|
||||
structure FloatArray where
|
||||
data : Array Float
|
||||
|
||||
attribute [extern "lean_float_array_mk"] FloatArray.mk
|
||||
attribute [extern "lean_float_array_data"] FloatArray.data
|
||||
|
||||
gen_injective_theorems% FloatArray
|
||||
|
||||
namespace FloatArray
|
||||
|
||||
deriving instance BEq for FloatArray
|
||||
|
||||
@@ -31,6 +31,7 @@ This file defines the `Int` type as well as
|
||||
Division and modulus operations are defined in `Init.Data.Int.DivMod.Basic`.
|
||||
-/
|
||||
|
||||
set_option genInjectivity false in
|
||||
/--
|
||||
The integers.
|
||||
|
||||
@@ -314,12 +315,14 @@ Examples:
|
||||
* `(0 : Int).natAbs = 0`
|
||||
* `((-11 : Int).natAbs = 11`
|
||||
-/
|
||||
@[extern "lean_nat_abs"]
|
||||
@[extern "lean_nat_abs", expose]
|
||||
def natAbs (m : @& Int) : Nat :=
|
||||
match m with
|
||||
| ofNat m => m
|
||||
| -[m +1] => m.succ
|
||||
|
||||
gen_injective_theorems% Int
|
||||
|
||||
/-! ## sign -/
|
||||
|
||||
/--
|
||||
@@ -404,6 +407,26 @@ instance : Min Int := minOfLe
|
||||
|
||||
instance : Max Int := maxOfLe
|
||||
|
||||
/-- Equality predicate for kernel reduction. -/
|
||||
@[expose] protected noncomputable def beq' (a b : Int) : Bool :=
|
||||
Int.rec
|
||||
(fun a => Int.rec (fun b => Nat.beq a b) (fun _ => false) b)
|
||||
(fun a => Int.rec (fun _ => false) (fun b => Nat.beq a b) b) a
|
||||
|
||||
/-- `x ≤ y` for kernel reduction. -/
|
||||
@[expose] protected noncomputable def ble' (a b : Int) : Bool :=
|
||||
Int.rec
|
||||
(fun a => Int.rec (fun b => Nat.ble a b) (fun _ => false) b)
|
||||
(fun a => Int.rec (fun _ => true) (fun b => Nat.ble b a) b)
|
||||
a
|
||||
|
||||
/-- `x < y` for kernel reduction. -/
|
||||
@[expose] protected noncomputable def blt' (a b : Int) : Bool :=
|
||||
Int.rec
|
||||
(fun a => Int.rec (fun b => Nat.blt a b) (fun _ => false) b)
|
||||
(fun a => Int.rec (fun _ => true) (fun b => Nat.blt b a) b)
|
||||
a
|
||||
|
||||
end Int
|
||||
|
||||
/--
|
||||
|
||||
@@ -50,4 +50,21 @@ protected def shiftRight : Int → Nat → Int
|
||||
|
||||
instance : HShiftRight Int Nat Int := ⟨.shiftRight⟩
|
||||
|
||||
/--
|
||||
Bitwise left shift, usually accessed via the `<<<` operator.
|
||||
|
||||
Examples:
|
||||
* `1 <<< 2 = 4`
|
||||
* `1 <<< 3 = 8`
|
||||
* `0 <<< 3 = 0`
|
||||
* `0xf1 <<< 4 = 0xf10`
|
||||
* `(-1) <<< 3 = -8`
|
||||
-/
|
||||
@[expose]
|
||||
protected def shiftLeft : Int → Nat → Int
|
||||
| Int.ofNat n, s => Int.ofNat (n <<< s)
|
||||
| Int.negSucc n, s => Int.negSucc (((n + 1) <<< s) - 1)
|
||||
|
||||
instance : HShiftLeft Int Nat Int := ⟨.shiftLeft⟩
|
||||
|
||||
end Int
|
||||
|
||||
@@ -7,7 +7,8 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Nat.Bitwise.Lemmas
|
||||
public import all Init.Data.Int.Bitwise.Basic
|
||||
public import Init.Data.Int.Bitwise.Basic
|
||||
import all Init.Data.Int.Bitwise.Basic
|
||||
public import Init.Data.Int.DivMod.Lemmas
|
||||
|
||||
public section
|
||||
@@ -16,8 +17,8 @@ namespace Int
|
||||
|
||||
theorem shiftRight_eq (n : Int) (s : Nat) : n >>> s = Int.shiftRight n s := rfl
|
||||
|
||||
@[simp]
|
||||
theorem natCast_shiftRight (n s : Nat) : (n : Int) >>> s = n >>> s := rfl
|
||||
@[simp, norm_cast]
|
||||
theorem natCast_shiftRight (n s : Nat) : n >>> s = (n : Int) >>> s := rfl
|
||||
|
||||
@[simp]
|
||||
theorem negSucc_shiftRight (m n : Nat) :
|
||||
@@ -37,11 +38,11 @@ theorem shiftRight_eq_div_pow (m : Int) (n : Nat) :
|
||||
· rw [negSucc_ediv _ (by norm_cast; exact Nat.pow_pos (Nat.zero_lt_two))]
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
@[simp, grind =]
|
||||
theorem zero_shiftRight (n : Nat) : (0 : Int) >>> n = 0 := by
|
||||
simp [Int.shiftRight_eq_div_pow]
|
||||
|
||||
@[simp]
|
||||
@[simp, grind =]
|
||||
theorem shiftRight_zero (n : Int) : n >>> 0 = n := by
|
||||
simp [Int.shiftRight_eq_div_pow]
|
||||
|
||||
@@ -67,7 +68,7 @@ theorem shiftRight_le_of_nonneg {n : Int} {s : Nat} (h : 0 ≤ n) : n >>> s ≤
|
||||
by_cases hm : m = 0
|
||||
· simp [hm]
|
||||
· have := Nat.shiftRight_le m s
|
||||
simp
|
||||
rw [ofNat_eq_coe]
|
||||
omega
|
||||
case _ _ _ m =>
|
||||
omega
|
||||
@@ -88,4 +89,94 @@ theorem shiftRight_le_of_nonpos {n : Int} {s : Nat} (h : n ≤ 0) : (n >>> s)
|
||||
have rl : n / 2 ^ s ≤ 0 := Int.ediv_nonpos_of_nonpos_of_neg (by omega) (by norm_cast at *; omega)
|
||||
norm_cast at *
|
||||
|
||||
@[simp, norm_cast]
|
||||
theorem natCast_shiftLeft (n s : Nat) : n <<< s = (n : Int) <<< s := rfl
|
||||
|
||||
@[simp, grind =]
|
||||
theorem zero_shiftLeft (n : Nat) : (0 : Int) <<< n = 0 := by
|
||||
change ((0 <<< n : Nat) : Int) = 0
|
||||
simp
|
||||
|
||||
@[simp, grind =]
|
||||
theorem shiftLeft_zero (n : Int) : n <<< 0 = n := by
|
||||
change Int.shiftLeft _ _ = _
|
||||
match n with
|
||||
| Int.ofNat n
|
||||
| Int.negSucc n => simp [Int.shiftLeft]
|
||||
|
||||
theorem shiftLeft_succ (m : Int) (n : Nat) : m <<< (n + 1) = (m <<< n) * 2 := by
|
||||
change Int.shiftLeft _ _ = Int.shiftLeft _ _ * 2
|
||||
match m with
|
||||
| (m : Nat) =>
|
||||
dsimp only [Int.shiftLeft, Int.ofNat_eq_coe]
|
||||
rw [Nat.shiftLeft_succ, Nat.mul_comm, natCast_mul, ofNat_two]
|
||||
| Int.negSucc m =>
|
||||
dsimp only [Int.shiftLeft]
|
||||
rw [Nat.shiftLeft_succ, Nat.mul_comm, Int.negSucc_eq]
|
||||
have := Nat.le_shiftLeft (a := m + 1) (b := n)
|
||||
omega
|
||||
|
||||
theorem shiftLeft_succ' (m : Int) (n : Nat) : m <<< (n + 1) = 2 * (m <<< n) := by
|
||||
rw [shiftLeft_succ, Int.mul_comm]
|
||||
|
||||
theorem shiftLeft_eq (a : Int) (b : Nat) : a <<< b = a * 2 ^ b := by
|
||||
induction b with
|
||||
| zero => simp
|
||||
| succ b ih =>
|
||||
rw [shiftLeft_succ, ih, Int.pow_succ, Int.mul_assoc]
|
||||
|
||||
theorem shiftLeft_eq' (a : Int) (b : Nat) : a <<< b = a * (2 ^ b : Nat) := by
|
||||
simp [shiftLeft_eq]
|
||||
|
||||
theorem shiftLeft_add (a : Int) (b c : Nat) : a <<< (b + c) = a <<< b <<< c := by
|
||||
simp [shiftLeft_eq, Int.pow_add, Int.mul_assoc]
|
||||
|
||||
@[simp]
|
||||
theorem shiftLeft_shiftRight_cancel (a : Int) (b : Nat) : a <<< b >>> b = a := by
|
||||
simp [shiftLeft_eq, shiftRight_eq_div_pow, mul_ediv_cancel _ (NeZero.ne _)]
|
||||
|
||||
theorem shiftLeft_shiftRight_eq_shiftLeft_of_le {b c : Nat} (h : c ≤ b) (a : Int) :
|
||||
a <<< b >>> c = a <<< (b - c) := by
|
||||
obtain ⟨b, rfl⟩ := h.dest
|
||||
simp [shiftLeft_eq, Int.pow_add, shiftRight_eq_div_pow, Int.mul_left_comm a,
|
||||
Int.mul_ediv_cancel_left _ (NeZero.ne _)]
|
||||
|
||||
theorem shiftLeft_shiftRight_eq_shiftRight_of_le {b c : Nat} (h : b ≤ c) (a : Int) :
|
||||
a <<< b >>> c = a >>> (c - b) := by
|
||||
obtain ⟨c, rfl⟩ := h.dest
|
||||
simp [shiftRight_add]
|
||||
|
||||
theorem shiftLeft_shiftRight_eq (a : Int) (b c : Nat) :
|
||||
a <<< b >>> c = a <<< (b - c) >>> (c - b) := by
|
||||
rcases Nat.le_total b c with h | h
|
||||
· simp [shiftLeft_shiftRight_eq_shiftRight_of_le h, Nat.sub_eq_zero_of_le h]
|
||||
· simp [shiftLeft_shiftRight_eq_shiftLeft_of_le h, Nat.sub_eq_zero_of_le h]
|
||||
|
||||
@[simp]
|
||||
theorem shiftRight_shiftLeft_cancel {a : Int} {b : Nat} (h : 2 ^ b ∣ a) : a >>> b <<< b = a := by
|
||||
simp [shiftLeft_eq, shiftRight_eq_div_pow, Int.ediv_mul_cancel h]
|
||||
|
||||
theorem add_shiftLeft (a b : Int) (n : Nat) : (a + b) <<< n = a <<< n + b <<< n := by
|
||||
simp [shiftLeft_eq, Int.add_mul]
|
||||
|
||||
theorem neg_shiftLeft (a : Int) (n : Nat) : (-a) <<< n = -a <<< n := by
|
||||
simp [Int.shiftLeft_eq, Int.neg_mul]
|
||||
|
||||
theorem shiftLeft_mul (a b : Int) (n : Nat) : a <<< n * b = (a * b) <<< n := by
|
||||
simp [shiftLeft_eq, Int.mul_right_comm]
|
||||
|
||||
theorem mul_shiftLeft (a b : Int) (n : Nat) : a * b <<< n = (a * b) <<< n := by
|
||||
simp [shiftLeft_eq, Int.mul_assoc]
|
||||
|
||||
theorem shiftLeft_mul_shiftLeft (a b : Int) (m n : Nat) :
|
||||
a <<< m * b <<< n = (a * b) <<< (m + n) := by
|
||||
simp [shiftLeft_mul, mul_shiftLeft, shiftLeft_add]
|
||||
|
||||
@[simp]
|
||||
theorem shiftLeft_eq_zero_iff {a : Int} {n : Nat} : a <<< n = 0 ↔ a = 0 := by
|
||||
simp [shiftLeft_eq, Int.mul_eq_zero, NeZero.ne]
|
||||
|
||||
instance {a : Int} {n : Nat} [NeZero a] : NeZero (a <<< n) :=
|
||||
⟨mt shiftLeft_eq_zero_iff.mp (NeZero.ne _)⟩
|
||||
|
||||
end Int
|
||||
|
||||
@@ -6,7 +6,8 @@ Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro, Paul Reichert
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Ord
|
||||
public import Init.Data.Ord.Basic
|
||||
import all Init.Data.Ord.Basic
|
||||
public import Init.Data.Int.Order
|
||||
|
||||
public section
|
||||
@@ -27,7 +28,7 @@ theorem compare_eq_ite_lt (a b : Int) :
|
||||
simp only [compare, compareOfLessAndEq]
|
||||
split
|
||||
· rfl
|
||||
· next h =>
|
||||
next h =>
|
||||
match Int.lt_or_eq_of_le (Int.not_lt.1 h) with
|
||||
| .inl h => simp [h, Int.ne_of_gt h]
|
||||
| .inr rfl => simp
|
||||
@@ -36,11 +37,11 @@ theorem compare_eq_ite_le (a b : Int) :
|
||||
compare a b = if a ≤ b then if b ≤ a then .eq else .lt else .gt := by
|
||||
rw [compare_eq_ite_lt]
|
||||
split
|
||||
· next hlt => simp [Int.le_of_lt hlt, Int.not_le.2 hlt]
|
||||
· next hge =>
|
||||
next hlt => simp [Int.le_of_lt hlt, Int.not_le.2 hlt]
|
||||
next hge =>
|
||||
split
|
||||
· next hgt => simp [Int.not_le.2 hgt]
|
||||
· next hle => simp [Int.not_lt.1 hge, Int.not_lt.1 hle]
|
||||
next hgt => simp [Int.not_le.2 hgt]
|
||||
next hle => simp [Int.not_lt.1 hge, Int.not_lt.1 hle]
|
||||
|
||||
protected theorem compare_swap (a b : Int) : (compare a b).swap = compare b a := by
|
||||
simp only [compare_eq_ite_le]; (repeat' split) <;> try rfl
|
||||
|
||||
@@ -26,6 +26,10 @@ namespace Int
|
||||
|
||||
@[simp high] theorem natCast_eq_zero {n : Nat} : (n : Int) = 0 ↔ n = 0 := by omega
|
||||
|
||||
instance {n : Nat} [NeZero n] : NeZero (n : Int) := ⟨mt Int.natCast_eq_zero.mp (NeZero.ne _)⟩
|
||||
instance {n : Nat} [NeZero n] : NeZero (no_index (OfNat.ofNat n) : Int) :=
|
||||
⟨mt Int.natCast_eq_zero.mp (NeZero.ne _)⟩
|
||||
|
||||
protected theorem exists_add_of_le {a b : Int} (h : a ≤ b) : ∃ (c : Nat), b = a + c :=
|
||||
⟨(b - a).toNat, by omega⟩
|
||||
|
||||
@@ -956,6 +960,12 @@ theorem neg_mul_ediv_cancel_left (a b : Int) (h : a ≠ 0) : -(a * b) / a = -b :
|
||||
@[simp] theorem emod_one (a : Int) : a % 1 = 0 := by
|
||||
simp [emod_def, Int.one_mul, Int.sub_self]
|
||||
|
||||
theorem ediv_minus_one (a : Int) : a / (-1) = -a := by
|
||||
simp
|
||||
|
||||
theorem emod_minus_one (a : Int) : a % (-1) = 0 := by
|
||||
simp
|
||||
|
||||
@[deprecated sub_emod_right (since := "2025-04-11")]
|
||||
theorem emod_sub_cancel (x y : Int) : (x - y) % y = x % y :=
|
||||
sub_emod_right ..
|
||||
@@ -1212,6 +1222,26 @@ theorem not_dvd_iff_lt_mul_succ (m : Int) (hn : 0 < n) :
|
||||
rw [Int.lt_add_one_iff, ← Int.not_lt] at h2k
|
||||
exact h2k h1k
|
||||
|
||||
private theorem ediv_ediv_of_pos {x y z : Int} (hy : 0 < y) (hz : 0 < z) :
|
||||
x / y / z = x / (y * z) := by
|
||||
rw [eq_comm, Int.ediv_eq_iff_of_pos (Int.mul_pos hy hz)]
|
||||
constructor
|
||||
· rw [Int.mul_comm y, ← Int.mul_assoc]
|
||||
exact Int.le_trans
|
||||
(Int.mul_le_mul_of_nonneg_right (Int.ediv_mul_le _ (Int.ne_of_gt hz)) (Int.le_of_lt hy))
|
||||
(Int.ediv_mul_le x (Int.ne_of_gt hy))
|
||||
· rw [Int.mul_comm y, ← Int.mul_assoc, ← Int.add_mul, Int.mul_comm _ z]
|
||||
exact Int.lt_mul_of_ediv_lt hy (Int.lt_mul_ediv_self_add hz)
|
||||
|
||||
theorem ediv_ediv {x y z : Int} (hy : 0 ≤ y) : x / y / z = x / (y * z) := by
|
||||
rcases y with (_ | a) | a
|
||||
· simp
|
||||
· rcases z with (_ | b) | b
|
||||
· simp
|
||||
· simp [ediv_ediv_of_pos]
|
||||
· simp [Int.negSucc_eq, Int.mul_neg, ediv_ediv_of_pos]
|
||||
· simp at hy
|
||||
|
||||
/-! ### tdiv -/
|
||||
|
||||
-- `tdiv` analogues of `ediv` lemmas from `Bootstrap.lean`
|
||||
|
||||
@@ -86,6 +86,17 @@ theorem negSucc_coe (n : Nat) : -[n+1] = -↑(n + 1) := rfl
|
||||
@[simp, norm_cast] theorem cast_ofNat_Int :
|
||||
(Nat.cast (no_index (OfNat.ofNat n)) : Int) = OfNat.ofNat n := rfl
|
||||
|
||||
@[simp] theorem beq'_eq (a b : Int) : Int.beq' a b = (a = b) := by
|
||||
cases a <;> cases b <;> simp [Int.beq', ofNat_inj]
|
||||
|
||||
@[simp] theorem beq'_ne (a b : Int) : (Int.beq' a b = false) = (a ≠ b) := by
|
||||
rw [Ne, ← beq'_eq, Bool.not_eq_true]
|
||||
|
||||
theorem beq'_eq_beq (a b : Int) : (Int.beq' a b) = (a == b) := by
|
||||
have h : (Int.beq' a b = true) = (a == b) := by simp
|
||||
have : ∀ {a b : Bool}, (a = true) = (b = true) → a = b := by intro a b; cases a <;> cases b <;> simp
|
||||
exact this h
|
||||
|
||||
/- ## neg -/
|
||||
|
||||
@[simp] protected theorem neg_neg : ∀ a : Int, -(-a) = a
|
||||
@@ -350,10 +361,10 @@ theorem negSucc_coe' (n : Nat) : -[n+1] = -↑n - 1 := by
|
||||
|
||||
protected theorem subNatNat_eq_coe {m n : Nat} : subNatNat m n = ↑m - ↑n := by
|
||||
apply subNatNat_elim m n fun m n i => i = m - n
|
||||
· intros i n
|
||||
· intro i n
|
||||
rw [Int.natCast_add, Int.sub_eq_add_neg, Int.add_assoc, Int.add_left_comm,
|
||||
Int.add_right_neg, Int.add_zero]
|
||||
· intros i n
|
||||
· intro i n
|
||||
simp only [negSucc_eq, natCast_add, ofNat_one, Int.sub_eq_add_neg, Int.neg_add, ← Int.add_assoc]
|
||||
rw [Int.add_neg_eq_sub (a := n), ← ofNat_sub, Nat.sub_self, ofNat_zero, Int.zero_add]
|
||||
apply Nat.le_refl
|
||||
@@ -555,6 +566,9 @@ protected theorem mul_eq_zero {a b : Int} : a * b = 0 ↔ a = 0 ∨ b = 0 := by
|
||||
protected theorem mul_ne_zero {a b : Int} (a0 : a ≠ 0) (b0 : b ≠ 0) : a * b ≠ 0 :=
|
||||
Or.rec a0 b0 ∘ Int.mul_eq_zero.mp
|
||||
|
||||
instance {a b : Int} [NeZero a] [NeZero b] : NeZero (a * b) :=
|
||||
⟨Int.mul_ne_zero (NeZero.ne _) (NeZero.ne _)⟩
|
||||
|
||||
@[simp] protected theorem mul_ne_zero_iff {a b : Int} : a * b ≠ 0 ↔ a ≠ 0 ∧ b ≠ 0 := by
|
||||
rw [ne_eq, Int.mul_eq_zero, not_or, ne_eq]
|
||||
|
||||
|
||||
@@ -69,6 +69,18 @@ theorem natCast_succ_pos (n : Nat) : 0 < (n.succ : Int) := natCast_pos.2 n.succ_
|
||||
|
||||
@[simp, norm_cast] theorem cast_id {n : Int} : Int.cast n = n := rfl
|
||||
|
||||
@[simp] theorem ble'_eq_true (a b : Int) : (Int.ble' a b = true) = (a ≤ b) := by
|
||||
cases a <;> cases b <;> simp [Int.ble'] <;> omega
|
||||
|
||||
@[simp] theorem blt'_eq_true (a b : Int) : (Int.blt' a b = true) = (a < b) := by
|
||||
cases a <;> cases b <;> simp [Int.blt'] <;> omega
|
||||
|
||||
@[simp] theorem ble'_eq_false (a b : Int) : (Int.ble' a b = false) = ¬(a ≤ b) := by
|
||||
simp [← Bool.not_eq_true]
|
||||
|
||||
@[simp] theorem blt'_eq_false (a b : Int) : (Int.blt' a b = false) = ¬ (a < b) := by
|
||||
simp [← Bool.not_eq_true]
|
||||
|
||||
/-! ### toNat -/
|
||||
|
||||
@[simp] theorem toNat_sub' (a : Int) (b : Nat) : (a - b).toNat = a.toNat - b := by
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,96 +9,100 @@ prelude
|
||||
public import Init.Data.Int.Lemmas
|
||||
public import Init.Data.Int.DivMod
|
||||
public import Init.Data.Int.Linear
|
||||
public import Init.GrindInstances.ToInt
|
||||
public import Init.Data.RArray
|
||||
|
||||
public section
|
||||
|
||||
namespace Int.OfNat
|
||||
/-!
|
||||
Helper definitions and theorems for converting `Nat` expressions into `Int` one.
|
||||
We use them to implement the arithmetic theories in `grind`
|
||||
-/
|
||||
namespace Nat.ToInt
|
||||
|
||||
abbrev Var := Nat
|
||||
abbrev Context := Lean.RArray Nat
|
||||
@[expose]
|
||||
def Var.denote (ctx : Context) (v : Var) : Nat :=
|
||||
ctx.get v
|
||||
theorem ofNat_toNat (a : Int) : (NatCast.natCast a.toNat : Int) = if a ≤ 0 then 0 else a := by simp [Int.max_def]
|
||||
|
||||
inductive Expr where
|
||||
| num (v : Nat)
|
||||
| var (i : Var)
|
||||
| add (a b : Expr)
|
||||
| mul (a b : Expr)
|
||||
| div (a b : Expr)
|
||||
| mod (a b : Expr)
|
||||
| pow (a : Expr) (k : Nat)
|
||||
deriving BEq
|
||||
theorem toNat_nonneg (x : Nat) : (-1:Int) * (NatCast.natCast x) ≤ 0 := by simp
|
||||
|
||||
@[expose]
|
||||
def Expr.denote (ctx : Context) : Expr → Nat
|
||||
| .num k => k
|
||||
| .var v => v.denote ctx
|
||||
| .add a b => Nat.add (denote ctx a) (denote ctx b)
|
||||
| .mul a b => Nat.mul (denote ctx a) (denote ctx b)
|
||||
| .div a b => Nat.div (denote ctx a) (denote ctx b)
|
||||
| .mod a b => Nat.mod (denote ctx a) (denote ctx b)
|
||||
| .pow a k => Nat.pow (denote ctx a) k
|
||||
theorem natCast_ofNat (n : Nat) : (NatCast.natCast (OfNat.ofNat n : Nat) : Int) = OfNat.ofNat n := by rfl
|
||||
|
||||
@[expose]
|
||||
def Expr.denoteAsInt (ctx : Context) : Expr → Int
|
||||
| .num k => Int.ofNat k
|
||||
| .var v => Int.ofNat (v.denote ctx)
|
||||
| .add a b => Int.add (denoteAsInt ctx a) (denoteAsInt ctx b)
|
||||
| .mul a b => Int.mul (denoteAsInt ctx a) (denoteAsInt ctx b)
|
||||
| .div a b => Int.ediv (denoteAsInt ctx a) (denoteAsInt ctx b)
|
||||
| .mod a b => Int.emod (denoteAsInt ctx a) (denoteAsInt ctx b)
|
||||
| .pow a k => Int.pow (denoteAsInt ctx a) k
|
||||
theorem of_eq {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : a = b → a' = b' := by
|
||||
intro h; replace h := congrArg (NatCast.natCast (R := Int)) h
|
||||
rw [h₁, h₂] at h; assumption
|
||||
|
||||
theorem Expr.denoteAsInt_eq (ctx : Context) (e : Expr) : e.denoteAsInt ctx = e.denote ctx := by
|
||||
induction e <;> simp [denote, denoteAsInt, *] <;> rfl
|
||||
theorem of_diseq {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : a ≠ b → a' ≠ b' := by
|
||||
intro hne h; rw [← h₁, ← h₂] at h
|
||||
replace h := Int.ofNat_inj.mp h; contradiction
|
||||
|
||||
theorem Expr.eq_denoteAsInt (ctx : Context) (e : Expr) : e.denote ctx = e.denoteAsInt ctx := by
|
||||
apply Eq.symm; apply denoteAsInt_eq
|
||||
theorem of_dvd (d a : Nat) (d' a' : Int)
|
||||
(h₁ : NatCast.natCast d = d') (h₂ : NatCast.natCast a = a') : d ∣ a → d' ∣ a' := by
|
||||
simp [← h₁, ←h₂, Int.ofNat_dvd]
|
||||
|
||||
theorem Expr.eq (ctx : Context) (lhs rhs : Expr)
|
||||
: (lhs.denote ctx = rhs.denote ctx) = (lhs.denoteAsInt ctx = rhs.denoteAsInt ctx) := by
|
||||
simp [denoteAsInt_eq, Int.ofNat_inj]
|
||||
theorem of_le {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : a ≤ b → a' ≤ b' := by
|
||||
intro h; replace h := Int.ofNat_le |>.mpr h
|
||||
rw [← h₁, ← h₂]; assumption
|
||||
|
||||
theorem Expr.le (ctx : Context) (lhs rhs : Expr)
|
||||
: (lhs.denote ctx ≤ rhs.denote ctx) = (lhs.denoteAsInt ctx ≤ rhs.denoteAsInt ctx) := by
|
||||
simp [denoteAsInt_eq, Int.ofNat_le]
|
||||
theorem of_not_le {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : ¬ (a ≤ b) → b' + 1 ≤ a' := by
|
||||
intro h; rw [← Int.ofNat_le] at h
|
||||
rw [← h₁, ← h₂]; show (↑b + 1 : Int) ≤ a; omega
|
||||
|
||||
theorem of_le (ctx : Context) (lhs rhs : Expr)
|
||||
: lhs.denote ctx ≤ rhs.denote ctx → lhs.denoteAsInt ctx ≤ rhs.denoteAsInt ctx := by
|
||||
rw [Expr.le ctx lhs rhs]; simp
|
||||
theorem add_congr {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a + b) = a' + b' := by
|
||||
simp_all [Int.natCast_add]
|
||||
|
||||
theorem of_not_le (ctx : Context) (lhs rhs : Expr)
|
||||
: ¬ lhs.denote ctx ≤ rhs.denote ctx → ¬ lhs.denoteAsInt ctx ≤ rhs.denoteAsInt ctx := by
|
||||
rw [Expr.le ctx lhs rhs]; simp
|
||||
theorem mul_congr {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a * b) = a' * b' := by
|
||||
simp_all [Int.natCast_mul]
|
||||
|
||||
theorem of_dvd (ctx : Context) (d : Nat) (e : Expr)
|
||||
: d ∣ e.denote ctx → Int.ofNat d ∣ e.denoteAsInt ctx := by
|
||||
simp [Expr.denoteAsInt_eq, Int.ofNat_dvd]
|
||||
|
||||
theorem of_eq (ctx : Context) (lhs rhs : Expr)
|
||||
: lhs.denote ctx = rhs.denote ctx → lhs.denoteAsInt ctx = rhs.denoteAsInt ctx := by
|
||||
rw [Expr.eq ctx lhs rhs]; simp
|
||||
|
||||
theorem of_not_eq (ctx : Context) (lhs rhs : Expr)
|
||||
: ¬ lhs.denote ctx = rhs.denote ctx → ¬ lhs.denoteAsInt ctx = rhs.denoteAsInt ctx := by
|
||||
rw [Expr.eq ctx lhs rhs]; simp
|
||||
|
||||
theorem ofNat_toNat (a : Int) : (NatCast.natCast a.toNat : Int) = if a ≤ 0 then 0 else a := by
|
||||
theorem sub_congr {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a - b) = if b' + (-1)*a' ≤ 0 then a' - b' else 0 := by
|
||||
rw [Int.neg_mul, ← Int.sub_eq_add_neg, Int.one_mul]
|
||||
split
|
||||
next h =>
|
||||
rw [Int.toNat_of_nonpos h]; rfl
|
||||
have h := Int.le_of_sub_nonpos h
|
||||
simp [← h₁, ← h₂, Int.ofNat_le] at h
|
||||
simp [Int.ofNat_sub h]
|
||||
rw [← h₁, ← h₂]
|
||||
next h =>
|
||||
simp at h
|
||||
have := Int.toNat_of_nonneg (Int.le_of_lt h)
|
||||
assumption
|
||||
have : ¬ (↑b : Int) ≤ ↑a := by
|
||||
intro h
|
||||
replace h := Int.sub_nonpos_of_le h
|
||||
simp [h₁, h₂] at h
|
||||
contradiction
|
||||
rw [Int.ofNat_le] at this
|
||||
simp [Lean.Omega.Int.ofNat_sub_eq_zero this]
|
||||
|
||||
theorem Expr.denoteAsInt_nonneg (ctx : Context) (e : Expr) : 0 ≤ e.denoteAsInt ctx := by
|
||||
simp [Expr.denoteAsInt_eq]
|
||||
theorem pow_congr {a : Nat} (k : Nat) (a' : Int)
|
||||
(h₁ : NatCast.natCast a = a') : NatCast.natCast (a ^ k) = a' ^ k := by
|
||||
simp_all [Int.natCast_pow]
|
||||
|
||||
end Int.OfNat
|
||||
theorem div_congr {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a / b) = a' / b' := by
|
||||
simp_all [Int.natCast_ediv]
|
||||
|
||||
theorem mod_congr {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a % b) = a' % b' := by
|
||||
simp_all [Int.natCast_emod]
|
||||
|
||||
theorem finVal {n : Nat} {a : Fin n} {a' : Int}
|
||||
(h₁ : Lean.Grind.ToInt.toInt a = a') : NatCast.natCast (a.val) = a' := by
|
||||
rw [← h₁, Lean.Grind.ToInt.toInt, Lean.Grind.instToIntFinCoOfNatIntCast]
|
||||
|
||||
end Nat.ToInt
|
||||
|
||||
namespace Int.Nonneg
|
||||
|
||||
@[expose] def num_cert (a : Int) : Bool := a ≥ 0
|
||||
theorem num (a : Int) : num_cert a → a ≥ 0 := by simp [num_cert]
|
||||
theorem add (a b : Int) (h₁ : a ≥ 0) (h₂ : b ≥ 0) : a + b ≥ 0 := by exact Int.add_nonneg h₁ h₂
|
||||
theorem mul (a b : Int) (h₁ : a ≥ 0) (h₂ : b ≥ 0) : a * b ≥ 0 := by exact Int.mul_nonneg h₁ h₂
|
||||
theorem div (a b : Int) (h₁ : a ≥ 0) (h₂ : b ≥ 0) : a / b ≥ 0 := by exact Int.ediv_nonneg h₁ h₂
|
||||
theorem pow (a : Int) (k : Nat) (h₁ : a ≥ 0) : a ^ k ≥ 0 := by exact Int.pow_nonneg h₁
|
||||
theorem mod (a b : Int) (h₁ : a ≥ 0) : a % b ≥ 0 := by
|
||||
by_cases b = 0
|
||||
next => simp [*]
|
||||
next h => exact emod_nonneg a h
|
||||
theorem natCast (a : Nat) : (NatCast.natCast a : Int) ≥ 0 := by simp
|
||||
theorem toPoly (e : Int) : e ≥ 0 → -1 * e ≤ 0 := by omega
|
||||
|
||||
end Int.Nonneg
|
||||
|
||||
@@ -8,9 +8,13 @@ module
|
||||
prelude
|
||||
public import Init.Data.Int.Lemmas
|
||||
public import Init.ByCases
|
||||
public import Init.Data.Order.Factories
|
||||
import Init.Data.Order.Lemmas
|
||||
|
||||
public section
|
||||
|
||||
open Std
|
||||
|
||||
/-!
|
||||
# Results about the order properties of the integers, and the integers as an ordered ring.
|
||||
-/
|
||||
@@ -1117,11 +1121,11 @@ protected theorem add_le_zero_iff_le_neg {a b : Int} : a + b ≤ 0 ↔ a ≤ -b
|
||||
protected theorem add_le_zero_iff_le_neg' {a b : Int} : a + b ≤ 0 ↔ b ≤ -a := by
|
||||
rw [Int.add_comm, Int.add_le_zero_iff_le_neg]
|
||||
|
||||
protected theorem add_nonnneg_iff_neg_le {a b : Int} : 0 ≤ a + b ↔ -b ≤ a := by
|
||||
protected theorem add_nonneg_iff_neg_le {a b : Int} : 0 ≤ a + b ↔ -b ≤ a := by
|
||||
rw [Int.le_add_iff_sub_le, Int.zero_sub]
|
||||
|
||||
protected theorem add_nonnneg_iff_neg_le' {a b : Int} : 0 ≤ a + b ↔ -a ≤ b := by
|
||||
rw [Int.add_comm, Int.add_nonnneg_iff_neg_le]
|
||||
protected theorem add_nonneg_iff_neg_le' {a b : Int} : 0 ≤ a + b ↔ -a ≤ b := by
|
||||
rw [Int.add_comm, Int.add_nonneg_iff_neg_le]
|
||||
|
||||
/- ### Order properties and multiplication -/
|
||||
|
||||
@@ -1415,4 +1419,14 @@ theorem natAbs_eq_iff_mul_eq_zero : natAbs a = n ↔ (a - n) * (a + n) = 0 := by
|
||||
@[deprecated natAbs_eq_iff_mul_eq_zero (since := "2025-03-11")]
|
||||
abbrev eq_natAbs_iff_mul_eq_zero := @natAbs_eq_iff_mul_eq_zero
|
||||
|
||||
instance instIsLinearOrder : IsLinearOrder Int := by
|
||||
apply IsLinearOrder.of_le
|
||||
case le_antisymm => constructor; apply Int.le_antisymm
|
||||
case le_total => constructor; apply Int.le_total
|
||||
case le_trans => constructor; apply Int.le_trans
|
||||
|
||||
instance : LawfulOrderLT Int where
|
||||
lt_iff := by
|
||||
simp [← Int.not_le, Decidable.imp_iff_not_or, Std.Total.total]
|
||||
|
||||
end Int
|
||||
|
||||
@@ -21,6 +21,11 @@ protected theorem pow_succ (b : Int) (e : Nat) : b ^ (e+1) = (b ^ e) * b := rfl
|
||||
protected theorem pow_succ' (b : Int) (e : Nat) : b ^ (e+1) = b * (b ^ e) := by
|
||||
rw [Int.mul_comm, Int.pow_succ]
|
||||
|
||||
protected theorem pow_add (a : Int) (m n : Nat) : a ^ (m + n) = a ^ m * a ^ n := by
|
||||
induction n with
|
||||
| zero => rw [Nat.add_zero, Int.pow_zero, Int.mul_one]
|
||||
| succ _ ih => rw [Nat.add_succ, Int.pow_succ, Int.pow_succ, ih, Int.mul_assoc]
|
||||
|
||||
protected theorem zero_pow {n : Nat} (h : n ≠ 0) : (0 : Int) ^ n = 0 := by
|
||||
match n, h with
|
||||
| n + 1, _ => simp [Int.pow_succ]
|
||||
@@ -43,6 +48,8 @@ protected theorem pow_ne_zero {n : Int} {m : Nat} : n ≠ 0 → n ^ m ≠ 0 := b
|
||||
| zero => simp
|
||||
| succ m ih => exact fun h => Int.mul_ne_zero (ih h) h
|
||||
|
||||
instance {n : Int} {m : Nat} [NeZero n] : NeZero (n ^ m) := ⟨Int.pow_ne_zero (NeZero.ne _)⟩
|
||||
|
||||
@[deprecated Nat.pow_le_pow_left (since := "2025-02-17")]
|
||||
abbrev pow_le_pow_of_le_left := @Nat.pow_le_pow_left
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ public import Init.Data.Iterators.Consumers.Partial
|
||||
public import Init.Data.Iterators.Consumers.Loop
|
||||
public import Init.Data.Iterators.Consumers.Monadic.Access
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
namespace Std.Iterators
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user