Update crypto code from Catacomb 2.3.0.1-45-g9c14.
authorMark Wooding <mdw@distorted.org.uk>
Wed, 25 Sep 2019 10:44:59 +0000 (11:44 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 25 Sep 2019 22:05:14 +0000 (23:05 +0100)
  * Imported new `test-import/f25519-tests.in', from upstream
    `math/t/f25519'.
  * Imported new `test-import/f25519.c', from upstream `math/f25519.c'.
  * Imported new `test-import/f25519.h', from upstream `math/f25519.h'.
  * Imported new `test-import/fgoldi-tests.in', from upstream
    `math/t/fgoldi'.
  * Imported new `test-import/fgoldi.c', from upstream `math/fgoldi.c'.
  * Imported new `test-import/fgoldi.h', from upstream `math/fgoldi.h'.
  * Imported new `test-import/montladder.h', from upstream
    `math/montladder.h'.
  * Imported new `test-import/qfarith.h', from upstream `math/qfarith.h'.
  * Imported new `test-import/x25519-tests.in', from upstream
    `pub/t/x25519'.
  * Imported new `test-import/x25519.c', from upstream `pub/x25519.c'.
  * Imported new `test-import/x25519.h', from upstream `pub/x25519.h'.
  * Imported new `test-import/x448-tests.in', from upstream `pub/t/x448'.
  * Imported new `test-import/x448.c', from upstream `pub/x448.c'.
  * Imported new `test-import/x448.h', from upstream `pub/x448.h'.

Upstream-Revision: 9c1437f372e62f0b3b3a7162aabee73bdc96ce4b

14 files changed:
f25519-tests.in [new file with mode: 0644]
f25519.c [new file with mode: 0644]
f25519.h [new file with mode: 0644]
fgoldi-tests.in [new file with mode: 0644]
fgoldi.c [new file with mode: 0644]
fgoldi.h [new file with mode: 0644]
montladder.h [new file with mode: 0644]
qfarith.h [new file with mode: 0644]
x25519-tests.in [new file with mode: 0644]
x25519.c [new file with mode: 0644]
x25519.h [new file with mode: 0644]
x448-tests.in [new file with mode: 0644]
x448.c [new file with mode: 0644]
x448.h [new file with mode: 0644]

diff --git a/f25519-tests.in b/f25519-tests.in
new file mode 100644 (file)
index 0000000..09ef4c7
--- /dev/null
@@ -0,0 +1,1537 @@
+### Test cases for arithmetic mod 2^255 - 19.                  -*-conf-*-
+### Extracted from Catacomb.
+
+###--------------------------------------------------------------------------
+test add
+
+## Some load and store tests.
+x 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+y 0000000000000000000000000000000000000000000000000000000000000000
+z 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+
+x ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
+y 0000000000000000000000000000000000000000000000000000000000000000
+z ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
+
+x edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f
+y 00000000000000000000000000000000000000000000000000000000000000
+z 00
+
+## Random tests.
+x bb8cd45b6185ee8ca34c4d7560425fd5c2fc22871113c6427198e8f9439a8523
+y 98f16cc5e44b7228b7f3b6ed91930d68bba5071157d19259c48034d2817e30d5
+z 667e412146d160b55a400463f2d56c3d7ea22a9868e4589c35191dccc518b678
+
+x 8ef938a7b07a668c234c2c5bb65115b8e2e22a3703cda51c70e7a56a075d4f34
+y 1f3cd4bf4f768058c4de1aa5aeb90e227338e308c7a0a199050ca1c38d1e034c
+z c0350d6700f1e6e4e72a4700650b24da551b0e40ca6d47b675f3462e957b5200
+
+x 8b2c4678fd4f8b7254eea925e4da8d472db7f97d349d1b2134ced884b747ea7d
+y 58dca7954f843b7e4dc56b048903e7728df66ef6824f29932b2f568c995ddf2c
+z f608ee0d4dd4c6f0a1b3152a6dde74babaad6874b7ec44b45ffd2e1151a5c92a
+
+x 9cd64f0cf439bccd224f7a789396b9f888998d1ba9759c93a5d6a27f45db0e67
+y 12f724a127052612081e27e3915db9a540de9b64c566edc313914ad94424464e
+z c1cd74ad1b3fe2df2a6da15b25f4729ec97729806edc8957b967ed588aff5435
+
+x 82e59fa9703b2557303665fe24e3d46259da974d78155f05c6b8891f92fc808d
+y 98a073ec62baf1354b681a3c78d62df1698ed5077dbe2bd68ba4a6e0233e3447
+z 2d861396d3f5168d7b9e7f3a9db90254c3686d55f5d38adb515d3000b63ab554
+
+x 686ceca221d0f4c6d98287e97c506085064e7b172672b88ee555dd0308bfd309
+y 60adc3675be5e6c2921a74b5b8b24b0a26341a19567dae713a720786bc72df16
+z c819b00a7db5db896c9dfb9e3503ac8f2c8295307cef660020c8e489c431b320
+
+x a50a5b82d2451ed9a5844585712202a6dc0e0230501d57b8c00f4bd4771aed9e
+y 98d71b8b140aea02ad47d9b19e47d2a03257adc1d5c47611adc667652b78c87c
+z 63e2760de74f08dc52cc1e37106ad4460f66aff125e2cdc96dd6b239a392b51b
+
+x 1637e3eb4c5d173b8cba29bdb13b930f48ae0599e354819f8ae0cf70f0f7b61b
+y ffeef1767df70de7a4a75864c03935d7934c6cf5228b9c3000813ed0e55447e2
+z 2826d562ca542522316282217275c8e6dbfa718e06e01dd08a610e41d64cfe7d
+
+x 9e8bf571c45bc5f37c9126e70498698978903b94d9c6712baef91894ab924fda
+y 480f68f8ee644bfb64e3fa514eaf16aea6368da6813802c4c3e6ce8f6540dfa3
+z 0c9b5d6ab3c010efe1742139534780371fc7c83a5bff73ef71e0e72311d32e7e
+
+x df9bdbd478bd1ec1ff078cdc76f2a5fcdc52f0198ba412e0b5a10e664b175dad
+y 080bc47bd2fb2ba3be6a07a02162f76020479f2cc6469c6766df23acf9517896
+z 0da79f504bb94a64be72937c98549d5dfd998f4651ebae471c8132124569d543
+
+x b6dd223f5d8a3dc5dd6f7a0679173ff656303017a17f17f4086fd4ecd3a23020
+y 560d827aad23c26fddbfd16c3514a9b518a4586d6e3c5739860743662b14f4b4
+z 1feba4b90aaeff34bb2f4c73ae2be8ab6fd488840fbc6e2d8f761753ffb62455
+
+x 1d59691a670c40143ca7f7e693389ab64a911b17a2fe4368fba9097b40864162
+y cb42d3ba12a8b90ef1622ea09241d3157c515043040914356d6d99b95089fa07
+z e89b3cd579b4f9222d0a2687267a6dccc6e26b5aa607589d6817a334910f3c6a
+
+x 82b48877e9c8c18edb52db3e1417d894e572a8edd84335d93c642158f2a926e0
+y 93c6a39c1ef97f318c3b13bf8e77bea653b2eb130bdf43b00a0e0e40a362e819
+z 287b2c1408c241c0678eeefda28e963b39259401e422798947722f98950c0f7a
+
+x a6137481c5b9b8bcb3c87f3868c5f812da71aeb21c5ce18a508773120ea4f659
+y 812eacdc5a8eb2e8fde0c23a19c2e33466d754ab3109d28ff48fb41dab8066e2
+z 4d42205e20486ba5b1a942738187dc474049035e4e65b31a45172830b9245d3c
+
+x 598fb4096a7054e317e66bc9633d56dfcaeabc31a7bbc9da13074b242edeca09
+y 929b1bddd55c99b06b99a3ffbac5adc1d28823cb8354adcfea60b7a87fe32039
+z eb2ad0e63fcded93837f0fc91e0304a19d73e0fc2a1077aafe6702cdadc1eb42
+
+x c42183d915267e655409326b1b77a042d8918feefd75dd3d18551f398ef426e7
+y e3729a6110686ffa57d1c69284a60fb36173148a89b1810d04614f03c8f90084
+z cd941d3b268eed5facdaf8fd9f1db0f53905a47887275f4b1cb66e3c56ee276b
+
+x 67b8b7ea7e7f9f52d686f906589c919b293bff6d3127e7ac581dc1630af7bcc1
+y 99d18d2190ef0da148b843c014fea3efea59f9adbb28fa38407191fcc24e029c
+z 268a450c0f6fadf31e3f3dc76c9a358b1495f81bed4fe1e5988e5260cd45bf5d
+
+x bc3422b79e01234fefd3637a19bfb2dd0a83bf2071b27bf5389918a50e579294
+y b665dffe064aceffaabba94697cf27054d016427ebaf68858c5250cc5c1b770f
+z 859a01b6a54bf14e9a8f0dc1b08edae2578423485c62e47ac5eb68716b720924
+
+x d419cbfd5514d9cffa1765b9f273fd7492000a3d110586ed0b8137760a2e808e
+y bcb52f423917c074464b2078d1c3f883fb793b02411b8b13c08266d17658a499
+z b6cffa3f8f2b994441638531c437f6f88d7a453f52201101cc039e4781862428
+
+x 2f7eb8051d16a52b797e2618881bd0857eb205bf97e581e09680f86308f7e082
+y 9ceda63b29c3bfedbb6f3f0be2f3f2bd285bb9d21620c3edde69629b00b1c3cd
+z f16b5f4146d9641935ee65236a0fc343a70dbf91ae0545ce75ea5aff08a8a450
+
+###--------------------------------------------------------------------------
+test sub
+
+x dfb53b4ff67c742728c564d50ae20e3e3617804478a95e511d37ff4dcf04fa3f
+y 9bc2006bb07dcf7bf0b461e7599e3c3cbfcdf6b6f41fc1db2219767ce9c43bcd
+z 1ef33ae445ffa4ab371003eeb043d2017749898d83899d75fa1d89d1e53fbe72
+
+x 432ec65076c94af41e054a43f64fe4eecb23f50a303fd38e0172e4e846e67394
+y 3642c84c5f5fcd5a0f3f2e37114beb8e7b614c39d354f1b32fe7e9cc918da5c8
+z faebfd03176a7d990fc61b0ce504f95f50c2a8d15ceae1dad18afa1bb558ce4b
+
+x 1725a986c03d9d53346ab2064545ba90ab38191e19ded9ecc2f44d422ab04150
+y 11a20caef0239e4ffb5ab2f7d3576633a0d4a08c78a02f35765fafff5398c48b
+z f3829cd8cf19ff03390f000f71ed535d0b647891a03daab74c959e42d6177d44
+
+x ec5d5cdfc8183f9aa3d47634d16427c3a399e2166bfa4ddfecbc911e5f33ceba
+y 649f8e29c483765c4232c369fd0e50a0026eac306eb4bd6924e7b4d7d3f73e26
+z 9bbecdb50495c83d61a2b3cad355d722a12b36e6fc459075c8d5dc468b3b8f14
+
+x cc9927c331884612d8fab9a2262ad0db38f55e0cc587e45b972ea8b1f504450d
+y 30c5c9f8d5491a350051bbc6bb78e568d98061b43cb1797cd3d7454e8a7aa1bf
+z 76d45dca5b3e2cddd7a9fedb6ab1ea725f74fd5788d66adfc35662636b8aa34d
+
+x 662bc96da214e50f13e07a15b8e0b78f512c744a66975b2170ba28079ca7d03b
+y 84b072295dca0abef806ec5c1e594179dc5e9eb172c178af1902a42ea7a3728e
+z cf7a5644454ada511ad98eb89987761675cdd598f3d5e27156b884d8f4035e2d
+
+x ed6f947157492eccc5fb1d0542593d58a47e2d87355dc0378e65376163fcf457
+y cb27e06c5ebf42a61caadd4fb222799772aaef31487bf61ac84c15f58af265d3
+z 0f48b404f989eb25a95140b58f36c4c031d43d55ede1c91cc618226cd8098f04
+
+x 33c2fc57d8ffc29e6d670cfc4e25b695320055cf443ade53f49f6c23c452f644
+y 3814860ccbb4391894c107961170d3af1594988a7972b97d0fb2169631b216fa
+z d5ad764b0d4b8986d9a504663db5e2e51c6cbc44cbc724d6e4ed558d92a0df4a
+
+x d0fd0d5e73be5c534aa37645aecc49b202fadb30733f16d0de719a70bec2c751
+y 910c7b4d317397cff70c91e5bf8ec42ba1700b0866adbbfe99b7fbb2c46c7093
+z 2cf19210424bc5835296e55fee3d85866189d0280d925ad144ba9ebdf955573e
+
+x e0f8130d6b0125e824b254ed57edc59455a8a4704a3f14a4ae8dbf8721595468
+y 4e4f69af6f85742068ad70225e8850c85aef3d3fb3ba3b52c2be979db4eb979d
+z 7fa9aa5dfb7bb0c7bc04e4caf96475ccfab866319784d851ecce27ea6c6dbc4a
+
+x 204d5f69ebab4597d2aa9295ecc2959480a2ab0b225674cc8a147cf7c1e59717
+y 3abdd29c94819ec7507673bd5cc4fb267fcb17c1509abd5e462b46b012f815a8
+z c08f8ccc562aa7cf81341fd88ffe996d01d7934ad1bbb66d44e93547afed816f
+
+x e2d75c74060aee615b6cfc815c8618f826b07c4987e10f20d27ff74eab3ac7d0
+y 7a06b32d284b5faedb91dac8e94cb7f76c678bad81ed78ac4e75eb9edd8d11e9
+z 55d1a946debe8eb37fda21b972396100ba48f19b05f49673830a0cb0cdacb567
+
+x 8d50b0573b0bb945bf128e1a9a37c151e991581673cf6295db5a6223d428ac9d
+y 47ca477794fdf378f3486355b5348960ee957470b8c74d62199ac48b4478c4ca
+z 338668e0a60dc5cccbc92ac5e40238f1fafbe3a5ba071533c2c09d978fb0e752
+
+x b66b49190a99456aaac5c33beaec423a3fa79a84df0f00122aed29151185ceef
+y 13c06f7941743bfa261845d99772fd0d5f1a8258aeda53b161505ed8bdca1bc8
+z a3abd99fc8240a7083ad7e62527a452ce08c182c3135ac60c89ccb3c53bab227
+
+x 44ac89bb8d4de1a8756b00401236ea4e316a2fe637f6e5f052576da70c29c4ea
+y 05dd39ac32768d899b80ed10279aa10d6316d60ab2d061e877dc5f21ce8e1140
+z 52cf4f0f5bd7531fdaea122feb9b4841ce5359db85258408db7a0d863e9ab22a
+
+x ef0f6c7f56ff22260c66d583f79c7f581181d3a0f3167c93786bb6c89de4372c
+y be934afeffaf5e6755a92e6606ffd054627dbe1b18ad6ae543363a01da605512
+z 317c2181564fc4beb6bca61df19dae03af031585db6911ae34357cc7c383e219
+
+x 773e0db8f86c5182b5f51d10376f42cde275dac6a646ab1cab065760e045107e
+y 3f92ddafdfe67d357b4f9b61807bcb8b0f1f6c2dacba27902f48fc15a31db606
+z 38ac2f081986d34c3aa682aeb6f37641d3566e99fa8b838c7bbe5a4a3d285a77
+
+x 34860a848d0afb20e43f4a36b3c8941f5821864216da9cb3ce1a11f056565a3d
+y 9dfed86048acd45ec0009c1ba3b20a1ba645ec141070fd8ae41d25e159bbce9f
+z 84873123455e26c2233fae1a10168a04b2db992d066a9f28eafceb0efd9a8b1d
+
+x 854ba91672ae1b8f6c29395dcfa4f3514ed97dc2c9e1e419f926825619fac55b
+y 7a700653ad355caf17f89045ecfb3ee821194b54048e55d8eed41fea2b0a22ab
+z f8daa2c3c478bfdf5431a817e3a8b4692cc0326ec5538f410a52626cedefa330
+
+x 0c66b3d8c3916940b70d381d232ba8aecfe27e3ae63fa6cbb287216708f224f0
+y 477186656245c4083dff93a95c6e5deb707916e52cd74abbd522743c24c53088
+z c5f42c73614ca5377a0ea473c6bc4ac35e696855b9685b10dd64ad2ae42cf467
+
+###--------------------------------------------------------------------------
+test neg
+
+x 0000000000000000000000000000000000000000000000000000000000000000
+z 0000000000000000000000000000000000000000000000000000000000000000
+
+x 23d767107e23d5ce14189cce939c4b5334d6736da3da40a715236b9d8319efc1
+z b72898ef81dc2a31ebe763316c63b4accb298c925c25bf58eadc94627ce6103e
+
+x 9bb944cfb58b186cc551e0a0eca74528c7618ff47485bf6a723f43d990f69f6e
+z 5246bb304a74e7933aae1f5f1358bad7389e700b8b7a40958dc0bc266f096011
+
+x bff36d2aa923d5a9af5398e2cfcba4acdf3c3181a8ff00b8a1099cd97a4e8542
+z 2e0c92d556dc2a5650ac671d30345b5320c3ce7e5700ff475ef6632685b17a3d
+
+x 1b65a51746eabb7c0d8d9844dda03bde7128407e94661db2d5fd9c0f3790d120
+z d29a5ae8b9154483f27267bb225fc4218ed7bf816b99e24d2a0263f0c86f2e5f
+
+x 88f4cf29a610c4465f63a272fde2f19a4874a70a0829885014379b637ab0e82d
+z 650b30d659ef3bb9a09c5d8d021d0e65b78b58f5f7d677afebc8649c854f1752
+
+x 94ca4d567efcf088e6bf1cb3698f6b8bf2164db4f523e28781aebfcbb501ec63
+z 5935b2a981030f771940e34c967094740de9b24b0adc1d787e5140344afe131c
+
+x 3f8d7ae4f1698921524e49ccb2ce4459e4c048f76f04c5e60179f5417d2d52db
+z 9b72851b0e9676deadb1b6334d31bba61b3fb70890fb3a19fe860abe82d2ad24
+
+x 1eaa0c45af0d8f85d865cc66ff3d0dc3355f1ac36821cdd95a6b9232a27f9044
+z cf55f3ba50f2707a279a339900c2f23ccaa0e53c97de3226a5946dcd5d806f3b
+
+x 33e142c78ee87a7980ade6c796e7ff949cee6d3af0415bf5b6901f84c2db910a
+z ba1ebd38711785867f5219386918006b631192c50fbea40a496fe07b3d246e75
+
+x 24a0c185c47787caf1a666a62002a503f2a3e591e5f2946e148a47b9b114a884
+z b65f3e7a3b8878350e599959dffd5afc0d5c1a6e1a0d6b91eb75b8464eeb577b
+
+x a8bd0c1c3f219a97de87b22e8cb3eb5daea33b5646589b6925ec4ec83ca37455
+z 4542f3e3c0de656821784dd1734c14a2515cc4a9b9a76496da13b137c35c8b2a
+
+x 1a340d2679ca205f6b198cff4bffadcde1afeeed124ef0c574655dbe8732b681
+z c0cbf2d98635dfa094e67300b40052321e501112edb10f3a8b9aa24178cd497e
+
+x da43c139a1f92ba1b5fc996befe5218368eac3c46b42e98a9cca8b8f6f1540f5
+z 00bc3ec65e06d45e4a036694101ade7c97153c3b94bd16756335747090eabf0a
+
+x 81aad864a31e5f4afa32c29eb97f22c103dfe5b1323db05fc9b1545312aa6c0d
+z 6c55279b5ce1a0b505cd3d614680dd3efc201a4ecdc24fa0364eabaced559372
+
+x 28231ad38d214f1421df7005eddb4f4c12e522b10d1cbcd10ee26dfcc222a62c
+z c5dce52c72deb0ebde208ffa1224b0b3ed1add4ef2e3432ef11d92033ddd5953
+
+x c1facefef35c1ed00db767ed0281ebfad1f3c915c6649f5e1c26a6f3f9478b43
+z 2c0531010ca3e12ff2489812fd7e14052e0c36ea399b60a1e3d9590c06b8743c
+
+x c2e4046e7200386ca2afea8ecc9c98c105fbf6e31b598e21e482796a69956040
+z 2b1bfb918dffc7935d5015713363673efa04091ce4a671de1b7d8695966a9f3f
+
+x a42fedea4eac90580a0bbcb0491a7e8cc82de7a99aa74ed35f705c536afa0236
+z 49d01215b1536fa7f5f4434fb6e5817337d218566558b12ca08fa3ac9505fd49
+
+x d1ab8c50d54279ceac870d0ce4a2af56bf8c03e87482dcb7775183a4908ac739
+z 1c5473af2abd86315378f2f31b5d50a94073fc178b7d234888ae7c5b6f753846
+
+x 1ffd85fa5ead53ff509756fc28051ef65eca040303b65f7b5b7e1d1a8508e030
+z ce027a05a152ac00af68a903d7fae109a135fbfcfc49a084a481e2e57af71f4f
+
+###--------------------------------------------------------------------------
+test condneg
+
+x 5330763b29dff20501a1d6c64025c36279083473721f5cacf89168189ff9810d
+m 0x00000000
+z 5330763b29dff20501a1d6c64025c36279083473721f5cacf89168189ff9810d
+
+x 9d9c36e2126d911a503e1cc1a8489ee74949ae2a8408dc7d72ed0d75e4350545
+m 0x00000000
+z 9d9c36e2126d911a503e1cc1a8489ee74949ae2a8408dc7d72ed0d75e4350545
+
+x 47da10abec2cb54c5890e5945999deb1d89ffd268bbbe2eafc86f1acc8bf5f7e
+m 0x00000000
+z 47da10abec2cb54c5890e5945999deb1d89ffd268bbbe2eafc86f1acc8bf5f7e
+
+x 3e6ec07de86be6ffab2dfa1deb9ed67844645be92bdbb22b7ba91379babcdfed
+m 0x00000000
+z 516ec07de86be6ffab2dfa1deb9ed67844645be92bdbb22b7ba91379babcdf6d
+
+x 5f5c0730649586b5c0b60a14d3b669b3649eb6725d71d834e78ff2aa0e5450e5
+m 0xffffffff
+z 7ba3f8cf9b6a794a3f49f5eb2c49964c9b61498da28e27cb18700d55f1abaf1a
+
+x c357befcc6836d89387915e368e5e6162252b433eb58d94eb3cc4b783e98c226
+m 0xffffffff
+z 2aa84103397c9276c786ea1c971a19e9ddad4bcc14a726b14c33b487c1673d59
+
+x 713ad0f656a8fcd75fdee2c4ac248ee7ad09a5f357c565daa94ae46d8590d2c8
+m 0x00000000
+z 843ad0f656a8fcd75fdee2c4ac248ee7ad09a5f357c565daa94ae46d8590d248
+
+x 909d669185e98b4a88a6531b830193b23035d64665929e34e86d53c4a9eef30a
+m 0xffffffff
+z 5d62996e7a1674b57759ace47cfe6c4dcfca29b99a6d61cb1792ac3b56110c75
+
+x 8f23ec139f93258e6d57fa278339f1cb5da193c5d1ad7183fb2b151111262285
+m 0x00000000
+z a223ec139f93258e6d57fa278339f1cb5da193c5d1ad7183fb2b151111262205
+
+x a9a5480c72157f389be80ae7ad63502434c380ccd1cef813dc9bd2e9a85e2f22
+m 0xffffffff
+z 445ab7f38dea80c76417f518529cafdbcb3c7f332e3107ec23642d1657a1d05d
+
+x 316f98b6697e7daa8775d3aa91dee8fbbae4e935a2f62cd2975e2d552f0c9846
+m 0xffffffff
+z bc90674996818255788a2c556e211704451b16ca5d09d32d68a1d2aad0f36739
+
+x 70128d6dd5fb42f287fba3533c71cb5dc2361b6d91c3d9626c58849e27f7d349
+m 0xffffffff
+z 7ded72922a04bd0d78045cacc38e34a23dc9e4926e3c269d93a77b61d8082c36
+
+x 66a6f3dc6274e4122dc401ef23529175d71d96b660a52cdcd64556073b5430b2
+m 0x00000000
+z 79a6f3dc6274e4122dc401ef23529175d71d96b660a52cdcd64556073b543032
+
+x 3909505812b228e6ca5cc6c0b17824ef765923eded6105e6eb0f176781624c5a
+m 0xffffffff
+z b4f6afa7ed4dd71935a3393f4e87db1089a6dc12129efa1914f0e8987e9db325
+
+x b7febd7d63efae3bcc60c1c344f2f6166b272eed785a9e541d3ff4f12e82a5f3
+m 0xffffffff
+z 230142829c1051c4339f3e3cbb0d09e994d8d11287a561abe2c00b0ed17d5a0c
+
+x d1cacc1db40de13351224046975319d7546ae9e88e1909c2a8f46792a140d279
+m 0xffffffff
+z 1c3533e24bf21eccaeddbfb968ace628ab95161771e6f63d570b986d5ebf2d06
+
+x 4c449a50fc1e145be1463e4c171b3c51c9683c41c45005d8aeca607911c9b3be
+m 0xffffffff
+z 8ebb65af03e1eba41eb9c1b3e8e4c3ae3697c3be3baffa2751359f86ee364c41
+
+x c929c50eedbad6ceacdefb00bd58a32820c874c906741e9d93cd0f668819edcc
+m 0x00000000
+z dc29c50eedbad6ceacdefb00bd58a32820c874c906741e9d93cd0f668819ed4c
+
+x 1c57449dcfc7e8f9fab77d226d4b50d7dee06c29d08d3d4f4ae7c8ad238a0a82
+m 0xffffffff
+z bea8bb6230381706054882dd92b4af28211f93d62f72c2b0b5183752dc75f57d
+
+x 396a2ddc48f158e73c95dc289da3f0d3b2128875e20c401cb50fd6cc7a28dd18
+m 0xffffffff
+z b495d223b70ea718c36a23d7625c0f2c4ded778a1df3bfe34af0293385d72267
+
+###--------------------------------------------------------------------------
+test pick2
+
+x e6f52222f35081896f3d9ecc0ffb27fa3e75c8ad1c98e161878d2c3cffd72c78
+y a24cd71f7acb653466b7d67bb41efb5a29503d2627d2ce28fe19680ccd939be5
+i 0x00000000
+z b54cd71f7acb653466b7d67bb41efb5a29503d2627d2ce28fe19680ccd939b65
+
+x 4e51fe2dac96a664d0675962116b7af4e605194a1c9fb774c621a3107994c9ed
+y 508934be10ce5e11e6940d56e84b148e20f48369e748536846763c80bab9af49
+i 0x00000000
+z 508934be10ce5e11e6940d56e84b148e20f48369e748536846763c80bab9af49
+
+x 530175217081c3fb3ecd17702ad334ad48f05affd5ab3754ef10be5b0eb5375d
+y 8aebc7e01e2bb2829f21311462175948d85cd3e65d676eec893e3df13f639d07
+i 0xffffffff
+z 530175217081c3fb3ecd17702ad334ad48f05affd5ab3754ef10be5b0eb5375d
+
+x 0e53c5141d72c8c81d80b1a1283b0267b278f98e28ce08ccac7b010022e5adae
+y 2215cc15e950d6abfffa26113f269628f50f9ac37ad3260ae9189958d75080b6
+i 0xffffffff
+z 2153c5141d72c8c81d80b1a1283b0267b278f98e28ce08ccac7b010022e5ad2e
+
+x 3dc16434679d30686d5023fda4cc574563841caf1d588e965fe1ec1c4ba54398
+y 4ca50330751d33ebba981277926a3fb801d216474cb183f90947680f5ea383a2
+i 0xffffffff
+z 50c16434679d30686d5023fda4cc574563841caf1d588e965fe1ec1c4ba54318
+
+x 09e68cb66b5ae2f3160a71738d1e9a042b9b76335eddc4b9466d0c6b8100eeb6
+y 270eb833ae635bed17df9218a53a91b7afeb74f0df3bfffb8334c04773cf716d
+i 0xffffffff
+z 1ce68cb66b5ae2f3160a71738d1e9a042b9b76335eddc4b9466d0c6b8100ee36
+
+x 831b8a99e3b44bf21cdd4f3c06da7c16a95e98f3dc42cf2ac282edec67d9b2ca
+y 482840e31c7620de6d290d747afc63ca199c60169f8eb62d28ca1142c5336990
+i 0xffffffff
+z 961b8a99e3b44bf21cdd4f3c06da7c16a95e98f3dc42cf2ac282edec67d9b24a
+
+x a022ace6772d82d30832328c7cbfedb622b710d1fe9313a77dc4cc5ca577a7bb
+y 39c86c57bf581c16d8c03b4ef0fe813815b5da1281f03bb3f2cdb0ddf19868d0
+i 0xffffffff
+z b322ace6772d82d30832328c7cbfedb622b710d1fe9313a77dc4cc5ca577a73b
+
+x 719d3f13c38b915873bcb14308bfd9bb6f4a6cfd249a745bceb55787ce480caa
+y c72de6e206ed24555d091763644d4405f2ee5dbd846a036d6a21442a6c40e0c6
+i 0x00000000
+z da2de6e206ed24555d091763644d4405f2ee5dbd846a036d6a21442a6c40e046
+
+x 07cdd3cd677a3c1783bcf7855bf1dbb453809b66c66c7bbbb67690cea33ca581
+y c9d889281ac117390875739e4b62df6dc3cca6c65439c46bb907c81d3a961fa3
+i 0x00000000
+z dcd889281ac117390875739e4b62df6dc3cca6c65439c46bb907c81d3a961f23
+
+x a69a728035cc69d5d3f96dd4a8081864333e53e434820dd569deb9e58393d4b7
+y 3f4ef71dfa1eccd817d3192dbe2e08466e4a66b4d836b0892b3636dc523098ed
+i 0x00000000
+z 524ef71dfa1eccd817d3192dbe2e08466e4a66b4d836b0892b3636dc5230986d
+
+x d249414415ac4960e934d29e08c75ff1b18431a6e18f7404e638293d3d8e81d5
+y 33cd02e07762f74976834d1b6dd3b8eb7e2ad7a5d04ba90bbe747476071f10cb
+i 0x00000000
+z 46cd02e07762f74976834d1b6dd3b8eb7e2ad7a5d04ba90bbe747476071f104b
+
+x efb782aba4dca351a5c9279b370073840b977b2458c6c84c9c9046dc92cc5507
+y 6d9f50eb56b84989aab77c54987f05c715b74185417863f2c275635d2d6f2eeb
+i 0x00000000
+z 809f50eb56b84989aab77c54987f05c715b74185417863f2c275635d2d6f2e6b
+
+x 10c4381ed467e27d756ff7a260a6ffd282ad757b10c9956c518a43117699ee91
+y 9b9a70c67be3296ef9d65fdd8014c4b263c28fd31f3299f4461c688c469ff704
+i 0x00000000
+z 9b9a70c67be3296ef9d65fdd8014c4b263c28fd31f3299f4461c688c469ff704
+
+x 5a30428bee407ee673ec7d2cb4854efd80b9761df5dec906463f888f60be7152
+y fc2e139be53203eb73041e9335253534c420208164682c2e02f31f084f5582f0
+i 0xffffffff
+z 5a30428bee407ee673ec7d2cb4854efd80b9761df5dec906463f888f60be7152
+
+x 43c7cd903c7dd7cdab85c6b5585955163e0da7dd0c5b5882ac620246619af342
+y 0eb52162c69425ad75b778c39746014789f7929119d4e122d4b98bf64784fcde
+i 0xffffffff
+z 43c7cd903c7dd7cdab85c6b5585955163e0da7dd0c5b5882ac620246619af342
+
+x f37f3707e4609d389096c1fea551b572a6b4644fd6af2e9e7a0fa93a91ae38e5
+y d10dd4d911346a5952e3123d4f156a7e40807d142c4afb4bc314ac6f9346dfa8
+i 0xffffffff
+z 06803707e4609d389096c1fea551b572a6b4644fd6af2e9e7a0fa93a91ae3865
+
+x a4f4c203cb892691a6d6e9dff8a10ac1a8d9470b13ba24e1bddac05d6d7f9c0e
+y b88145fabdeaa9fa108bb04a4d283ac034b4c8d8ffe1b2174de9a80254762c54
+i 0xffffffff
+z a4f4c203cb892691a6d6e9dff8a10ac1a8d9470b13ba24e1bddac05d6d7f9c0e
+
+x 649d8ce64f623228553de99b823c5f5c5ef37f00e2ddf658fc9bc2405afde715
+y 0f24ace92223d2db75e2d82e8a5bc8b0e7981478216b999d2bdde9c72732d58f
+i 0xffffffff
+z 649d8ce64f623228553de99b823c5f5c5ef37f00e2ddf658fc9bc2405afde715
+
+x 3f466e24ed4169ca3df624d747f054f97422d5eee3fade2fa3c4eba488694a6c
+y 37e3171c9aa56d07ffcde4f1fd0fdcc41e2086ecf93c9e53f3f6a4c3e4db587c
+i 0xffffffff
+z 3f466e24ed4169ca3df624d747f054f97422d5eee3fade2fa3c4eba488694a6c
+
+###--------------------------------------------------------------------------
+test pickn
+
+v[0] 91aaaaf3ff9e58f299c0f6d0a4a3851d100423e4b7380d5a32a86cde6cb19562
+v[1] e586b4ab140cd20bfc70aa5ae1c389941a8c631ce033f54793d77c91b5e3d50b
+v[2] 911122291921aced748e1346261ce8dc0e50704bf59495c3d7c1a9806ae58b5e
+v[3] dac7c42fc0253029c78310ea1508b2464db2c44689fa7d485fb5863b7c136f15
+i 0
+z 91aaaaf3ff9e58f299c0f6d0a4a3851d100423e4b7380d5a32a86cde6cb19562
+
+v[0] e8864778a3aecd6f35f8afa097072e94c4e50680baf91a6036f4f24fb0dcf111
+v[1] 5dec44933a517f5a8bf6d858920e1200c74e65132baf0d08ca033e36e15a1c46
+v[2] 4fca88e6d122c0a460b5dd502281d80616edd30bede891226b4b3c4b3eb9eea0
+v[3] 5fbf4e034d45326d89ffe92bf4738a7120c63ea42568c25acacf4dd7915b9e8f
+v[4] 343001277d416dd31dc770232fc47c7d02884fef3fc10eaddf6f8b42fbb00b26
+i 1
+z 5dec44933a517f5a8bf6d858920e1200c74e65132baf0d08ca033e36e15a1c46
+
+v[0] f0cfc16fe0cb8910c26f6f46e69954dd34277d171044140c2dc448b6f63e053c
+v[1] d54feccab8d55297eb24f622818aaa2ac5b7fcafee5efe872bb600cbdce85a3a
+v[2] 5f1cb6c6b4e8eedb566150a99a7c92228e7f737efa1810b9d40f9a4ea020e56d
+v[3] c762a32a3f3a6f8cd956412eacdaa75ee56b347b952a7c18dd19c0ee2e50b8fc
+v[4] b6e76d1d2cdf04692036f26515ca6b92d57b1bba625f07553d2d4adf89de9611
+v[5] 874c9e94d425fe9590aa1cde396ec56531342207a0e3b42ef0ae710bc9b68418
+v[6] 872ebc0bbd45d07727887aa8116a5743880093c73b3048c3b46920c04e0f64e2
+v[7] 9cde037629d20a4481ba7050546eca2dfd293b0953aa708764531bd8d0fba387
+v[8] e9f7cb8ed4af14ac61722de66406e97ee9a87d9362dfa87e489a9c98f8b891b6
+v[9] 6c5bb4410d83505ad34d10409d02fc005a47ef802b5d9130f3b5d385ff78957e
+v[10] ff40983b47e7263665a03e4396421fc34209afaf52d7d69012833b4a228e6c40
+v[11] 4588ed141f6401c460ff6ad4888172c9d19f15f214d96bedd59f818d7c03b720
+v[12] 99ede977304bc4e8f5edc44463b48fc13c001f5c584f2b100c791ae472fdddba
+v[13] 8ba76d6aa98a062e1091ca60e05ecf21208657bf287f20c6cacaaeff41a537ff
+v[14] a18760b118187f5b392637dd5c5f97ccce583b5b84b69f8e37d8caf77c616db0
+v[15] 7e921cc5caa3b3884358cb0ffd2d9d160ed54256049fa1540d861dbb6dd1631d
+v[16] aa8102188fbba89c45259c52080b3969c234d070411bc4b91870a8b482eedfbf
+v[17] d98da58b248507edf310beb9fb522dd23d88bc0412ef3b5bd7a13b7a15070647
+v[18] 0626183221836da09c9bb5a1dd07df570883af17a9a8fed1c4bc7e8770e348fe
+v[19] 16b01a5593b3eaf0902d0ade7e00da7b7a57556c2e7169e8b6ba5df5c5fb02a5
+v[20] e40715b07034e109d79a95a8b031eebc6c59dd0bb77de6cb960fe65a6d1be59e
+i 20
+z f70715b07034e109d79a95a8b031eebc6c59dd0bb77de6cb960fe65a6d1be51e
+
+v[0] e30f85631b4ea4aadb9487c76cbec40ab63101a482e5aa2e3ee329fc21071bf4
+v[1] 8bc9fdd41fe1ecf5c2cc2075c72e4ceab370b099ddc672ee16bbd7a7de19dbb4
+v[2] ede086a76fedddb463d9f0fb44b39ac7fb64665061eb96015d4ed39eb33cd772
+v[3] a7cd74dc0c94aa8bfa480a88396b7f293f1ac329e4ce79e04507be4edbf4fef1
+v[4] 45f5c114a46bf0b2c8be1ecb8fc7c81e7fef668a2e4e9769f2f2dfecf405af92
+v[5] 123d101a02348f81088beeb6fafb7f720b49631736829d2f19e95b8d833684a3
+v[6] ba936ae1b5555b05601c2e59bf9585846ac01b5b7f6fe4bbd45e0653e961deaf
+v[7] 51c0c307d99e34a617ead92dd37e1a0f36ebe2e45ef5b3690fd114099d483dc6
+v[8] af94cee7979c057995680c3a5adfe26e7dea759e2640b0b09aff383fa355d289
+v[9] 6ddb6908532c513f463473e449747f88d47766460ad316734c2cca87963b3060
+v[10] 88192953b60710667d47633be71d87214d2dc8be882ceb6928daf311499d2e83
+v[11] 37da1b76c2c16025f0644b6451027c8bc9768379c3aa7ab8410d34d8c8222706
+v[12] 1a46c0531cc13f546e001a67721931f4f6bf8eeeadaaab667ee651db0b272509
+i 7
+z 64c0c307d99e34a617ead92dd37e1a0f36ebe2e45ef5b3690fd114099d483d46
+
+v[0] 9929839bce983fe53c4f8f9d07a462f82e8eebabba2c0daee1378abf585bb53d
+v[1] 4e47d3997d6562c7b0347acc96925bd1907bf3a9c57d51b099c4a574d7bf8fc7
+v[2] a0de02656ba18dd1cfdb2938fbb864f9f59001110391ee1818f5c1dfee64f61a
+v[3] 9c4153154f5b827bb847edfa04ce754e442f2e96ea001fc27f6d94ea8b06fc00
+v[4] 7ba90562980966abd857be3a84c1bffeabbb589415e722e51225f8317e829777
+v[5] ac4657b264ccfad4f5ba3f7a470458101d5c6025c45d00191ddd4bf85ca48705
+v[6] 8b11cfc6ceb02c5d4b3e19c19f1ae745fd0cdfd9da1a80e9df1be8f7bb99ace3
+v[7] 1202bae1f86d05ed8fca09965bb1cfa3fb696a3f2b7089ee10589394639da2bd
+v[8] 143f799fc9ebec77aa444eb5ec95f64029cf61b875a2f94e228323844cb8eff9
+v[9] dcf99568b397db79bd2e8ae49778e1e49865e91525f932a1813d1c395420a43c
+v[10] 84fdfee8137558f0b9f2441c375fce466e3212c0d0de3179919fb130e61b711a
+v[11] 602454ffaf59610f76863a7456146f866539740d6dae63a3628d408e34db8e76
+v[12] 86ae4475d41ea312a97c821ac78b815e459dc6bb4d52c236a39e5e53ff17f5fb
+v[13] 0fd56e878b74a2daebc2acc30c31c279f3dab146d748e7aa9b17eda7ac039c8f
+v[14] e559e8bbd51113f84ebbe35ab16bfd46cf610a5c61307b986111ddbee3037f7a
+v[15] bac90f3afdf4f4828368090958aef5e49aa83d25fc5dc15d9b8a354a30961e75
+v[16] 253eee8f614306e59a31d9fab5423ea269b67babd54c52243b86b8af1372f3ab
+v[17] 69828b787af1831f772a3bb9a410dac8bc47909ac6bddc94a5c600a3167ce780
+v[18] 1903e9ca239847045875b0bd4e1575a724d9f729e3cbfc377de17ad29839a121
+v[19] 57bc65c0fd8495014f31e3be740967f3fd1884bee743b20b947339923530d63d
+v[20] cf7427ebf6088e6f3385275f993b5c06ee14f738b59d49ecc327521ddced2a4a
+v[21] 74c2a4122225e97b646d6a38584626a6ed811506ee7cd00b48ba563b7a776380
+v[22] 604f163d7d7f4987c8aaf2e7a946cec1597ebeb59aaeaad0dbd0737527b9350a
+v[23] 30e7ae69cd5fb42ec00ca840988a59bf5688aa0b810bb2e9ea24fb5b322891a0
+v[24] 68caff542deb61b055bf65127a94d8ab107f5d2496764f97351dbbfbf34928e4
+v[25] c0d307ece7f18150d958bd88bf11912dc818fac7cae06ca9ec3fafd15d452af8
+v[26] 731b9ae286f29660fd0814568351bd6da114f3ee8b87c217cfe531746faa8c90
+i 8
+z 273f799fc9ebec77aa444eb5ec95f64029cf61b875a2f94e228323844cb8ef79
+
+v[0] 85b3448d0292edc0b14cfae9225989a16a61ee8441166d5b97faf876b0ab6c7d
+v[1] 88b0f7c78f8390b6cc1de0afda111326dbb41e7603b82033902eb56ea542c2dc
+v[2] daf45d38b24294648a7b203758ff0654d42507e958bbd98c72229aae0a9e5757
+v[3] 98b44fbbf6e45c81c2473b626307506881a9fa609c546741b3637b731ff62adb
+v[4] c0779c0f0a35658998ee9cb6b0cb6b7e089b7f288ea171c18bd2664ca5c3fc1d
+v[5] 8da42494a2c1e2034d2009fd486cc230085fcc8af171e2bc2cf428bbf9b4bc86
+v[6] 6dfb99cec539941c9e7d26e5640641e4ef2c3f1a732f9c85759858a95c346ea1
+v[7] 471a369f8d1d3341ac707f1c41e5f0655cae51d8a170037ee349b3c14e01be2d
+v[8] c1b75b02941ae0c2e398a2c8871955c8306f6ab88cdc6d751e11b35605d10829
+v[9] ea508e41e33ca0b03b5d93a54ec359e01a5a00a98a80f7e6d998641a6cb7ef58
+v[10] bb009a72b5d5be344a3ba9509b6e8eafbafdab4b0ec9202c8d29983935c6937a
+v[11] fdce2ff0df8548fd7df3b8a087aa30c819af0eff3b8931e5ddedfdb0f4450919
+v[12] eea3990f7f4045a3b6cdae27e4dc8a8062049ac4423ce46108ab464d866b80f3
+v[13] a18000f37c8c4a30195e71864b14f170a3f5c427f4769c736fbdc18b3fe68887
+v[14] ba9aa19e99a69b34f357f92d95a6c409f1bb331d1d27b693164cd0dbb552c771
+v[15] b5863e0215351b2f9b6f661ab94c833016bdef73a34b100b6db79ea8d4b22ec3
+v[16] 983eb31be6cd1cd4cb53e489e4535683e21c00e6c52f685e84bd3cfc98f9ab2b
+v[17] c31c18c6c12feb3be4e51a1671fa6001c1dfadc0ebb35349766d9d07d5a70025
+v[18] 6f81695294071c711947499c2c3d96969a70948c29ea9506ff675d25052f0950
+v[19] 3b42ffd7fb054072e7fb93bfa63d24511e6c93455cdd5b9be3c8382a3cdbfba4
+v[20] 6d7463ce0227e29a2706b8ad6be0d6cefa173c261697520b23edb87a189d31eb
+v[21] f6cea0722a490515f48632f42f167a911ba00fd9883604e52d713210f3d9475c
+v[22] 6281bf17cc14876c75e9620d8bb9bfd6e4dceae1ad3cb675769f94623ab3a955
+v[23] 2c943465a6d4484c71b2c5ae26e1d738059667093450cff54e6b45f12a7588f4
+v[24] 3d9ba6aad36754c5c767a0f288b6dbfcd2f1e21bd14094f4ddfb7c4bb79ef882
+v[25] 052e95ca0672218808e36c18e1fdee412a945ad735ea883abd527dfe8343a51d
+v[26] 3f8ec0ccd82005e01ffd1fd7413a2a1dce1a177cf53474904cc46abdffd22a22
+v[27] 2030168387fa230e7a77eae5f051b4e0f1cbc53a78a5df640479c9fc373b9d78
+v[28] 3abd6a4fb5a585bb1b4609cebbbd1035392c7565654331a173092c098e1583a2
+v[29] 6bceb64086f3874854b4c89d31d20d8772b2f48be6a5fa1fe572be9927345103
+i 2
+z daf45d38b24294648a7b203758ff0654d42507e958bbd98c72229aae0a9e5757
+
+v[0] 8a9e76766b2eeda9b4de923344005a825bd2475bc4d529b033de3510cd405b73
+v[1] 5206880a0e1c282a10e03253c787e005bc9a18613b6e238f1eb72c604844a2ab
+v[2] acd4fe99d1df199ca20c743238a2bf9562ea4de7b82061d1a6861d77146bdfb8
+v[3] 6dccfdff241fd837508913d7e0b1ca3e7a426be578c2e82612f7d2b2491f08f1
+v[4] 76aa8f5fb4b3592ff58785ea27d287fa5f250fb84fc9838fad8d6a2cfc223dad
+v[5] 71019d81508491afb6a33d8c99aba13d59c63bb88a2ba1182c144f171ed5a815
+v[6] f6ab8f0b95fcaad29def12e05f348a9a35449c7ef5e2859748e69c517f4f3f65
+v[7] 237b33cbba9ebcae93f8a4fd863f62a03651be2e936ddb5a62dd3b6a68734b2a
+v[8] 4bbe3113be34a9f7fa26dd96258d1776797b8ea454a2f596ae076bdc0f5d0ff0
+v[9] 19ae0acbd7ba59869b51caa13e1041bcffed633235a858f39d0d583575a64123
+v[10] cc5e18fdfedf9a416727f81b24a227c0c0771565fff69fc3e19399a254d8c9c5
+v[11] 50765357fa421d9153c1f02adcc98f188d2aac6a39fc8d522c5e81fbb775bdbe
+v[12] 10e3e53b7605240cadc28c4d3aeb1afe40b7d1d547f4ad60c8d03006b42fb499
+v[13] aec6bfd729a6e2898890c9ee15338aec209c94141dad7b7884f7be481a2f0d6d
+v[14] 8f9620a5b985a3a1dc4825f1f4c683457a98f799118691bc57b17ab42713b593
+v[15] 92c24c6920edb4f37e73dd795ac9bbfcd8035dba28421fce290109c222bfbc86
+v[16] 45bdcd99b590e64aeb5173c7538e77a7cd10a9d786338c43e3a0946b33a9c822
+v[17] e0b86e6b4752ea2cae053b1bd897c6d749c7fa46308be876b8006c3ffa2d6479
+v[18] 6cb53b7769f0da52c697c8640c029099d84afb55c20c9ac84b959ff36c339e92
+v[19] a21436f9a4c876375d16c41bd3780f024b867f6fe6394c5c64b4ea5a6f306c7e
+v[20] 93b40e751d291e90ec3adf902935285a5746781bfc1c594d520dc5828ba53d3f
+v[21] 6dc080d82251557b9804deeaae90bb1a45d9895c5067f3b04dbfcbb5ab0be3e2
+v[22] 22783694c9ab9d652dc216306ea4fc09734e90bd08625e688b9bc1b8c73e3366
+v[23] 078b0d30cc5fbb248a5e84a416a3d849772ef6eadf20f73eeb82125f68a216e6
+v[24] 83dd79bd150e5f7bf7a357236ed41ca06b8c40bcce840e118f6cf457ff151654
+v[25] 72169420815aa9a38719072be9c824d68a0cc5d6b4251ff9180938def3dcb0ac
+v[26] 63f1febc1579b537b71e1fd12687ec49885dbcf93db68f44660bca4780ca9aa8
+v[27] dc337f8a3699ff549dfa26c1a5ddab43cdac7062d90fc2a779ff528c414035f7
+i 16
+z 45bdcd99b590e64aeb5173c7538e77a7cd10a9d786338c43e3a0946b33a9c822
+
+v[0] aa199ae7d7c298e11aa74e5bcff2f206fe6b53962f3bb39767ad6df19c58d93d
+v[1] 4b95d1e296609760e06e7e476af7182db41712d73be94a3533b7332a7dbb780d
+v[2] b72f91cbf1117db1982b035f0e76e51bf4cd8e968b932606450bdae0d588906b
+v[3] a1de9fc4d0e579aad319de0280fb45b5fed6c9d38dab5216ff8401376fce0230
+v[4] fc216489a815b0c98969118c9ada3f7152c4eb07217abe54fae4fd4d63e96811
+v[5] b660cb7ac499821dc872c3400fb2590527659ecd72df16c7ec5376075fca7d7e
+v[6] 3bbbd9dbbc9263d289de49b1648fd64751d8b0e6d5d506a356fee0ed6452ce89
+v[7] d17efdc8cff826d28ab55b51211209a27054f2d33f108f34ce7bdc5c71b918e1
+v[8] 21da90e37be817920404ff5015346dd05ef32e018632e09b7cea35d42eb1de1d
+v[9] 66da40ef6fae8df49b5aca9a2400ea4fba527a9513c821e00985625615e71416
+v[10] 61e5b60766ca457b36aeca26a62e6f4831691ef79bdc72158c2a2b85fe3b5cb2
+v[11] 9a0917795f936a5384c4a504b2ba3d7056906ea4e34474c310b873f88890bd37
+v[12] af65ade7e8f0022420932d50d0a8587c43ac4436bc511248358886e2c7072c1f
+v[13] fadd2a9fa72f438f147964180ffba490beaa55baf6275d8ca347ce5f5f94fd05
+v[14] debd9beec2527f284790a9ca8fbc074ec359f4a89974c2ff49780fcb21c5ea91
+v[15] f6a57794ba1265d9974e52f856acd3dddd0f6a50844172466c82f0d49eef676d
+v[16] 97cbe03e723431b6c14bf1681e845d530e083ddaa26f055d3e162615f57c113f
+v[17] b89054ac8b7135c1e6d215e4e5dcf679298fdcf6ef35301002be560389f8cd08
+v[18] 8ba6a9d5ee4bf15d87170e7c050699e858c6316bc92d5f4e19eeb3ed82e012b0
+v[19] bf0f272aabf63cd98397f4da2fd3c5742373529c91ab455fdf394fb6d0b8272d
+v[20] 7a2a4980dec077abbd6a06f8b90219b818d4990b8f62b9dfc50bc4feec31eaf6
+v[21] f1d55b4e207cf5b7bdff5f59a63b55fbce6704b5ace5c5183f6be8e4770c567c
+v[22] d55b23bebc2f16fc9adddf06ece363add71c4cfd73ab228461cfb926addee0cd
+v[23] 76ac92ee62c2bb928bb5ec11673b51c2f1fec44ca27741a647cadfe55733eb41
+v[24] 1544a9b6c6cf77fec3e83bb08056bf18f3eb440611249f60cc97b58b5a93d364
+v[25] 702a0023d8ff6a108a2eadb777569f54df2c3b85634bb872611ccd8cf74e2807
+v[26] 8dc8889dae004e88a94f3c3beb4d39da7c074a038ff8899c5798f7a26fd17ec9
+i 19
+z bf0f272aabf63cd98397f4da2fd3c5742373529c91ab455fdf394fb6d0b8272d
+
+v[0] 63eca008f74f57babb34dde1fbaa5264656007f7479d8df3ba5cccadbe83925f
+v[1] 001a67bf61d077528bf9b386694a99d7293d6b49f368ad54767a2829643621b0
+v[2] 4c124850c332a4e2a6a335e5f5676f803ede7958719b083f648137cfccb82f50
+v[3] 39f293fdd5b28c882b824d1cfef38a327334776139bc2d814834a86d6b2d93bf
+v[4] 114df0c93aebb6a764740e43a67c6b582b49f6d0c393a23db42611023c044d9a
+v[5] cd9e11bd49d7ee82e52f89d7100fd64c4474695054cd22442ed2bf17991cebe8
+v[6] 56931f05328bd38dea431af6537fe4a4f1e419a24c5181974e61b64367a65a5b
+v[7] 2bec95a108b7a500937b5a3f3c54ae9b2cc7b11629ac581f7d8663b9c910af96
+v[8] 380777fd3ab97d140a142d3d37c7786264ea00b63083219652376d7fd56ea846
+v[9] f0fb2846d9cb0b88751db963f9360ff2bda25052eba9edd2ec561807c1f0fc27
+v[10] 34294c58ff5ff91f1472dc3d7b3099c81ef434126c58de3751c788a71f2a78de
+v[11] 05c5a1c0bf29c1bef5da9298450b8ce6c5856b3f7e2037133734a03959573927
+v[12] 7fd9db5b2418267e94db49ea0534ec8d397f32f90981448c944a4ff3cb6d9c3f
+v[13] 7015d096ddd557e669fcedd9b3b2624b910505f756e8ea160c5436bab604669b
+v[14] 46858fe7612b43ba805a6c7999a3be02b1e635963792d228f1414fbdf13e175b
+v[15] 70422706d36540ece562d1c36bfc5b178d1cf47c1ed87bea38be5a9f95010521
+v[16] 250e48d385aefbc10776582e71e4139148c99d6f9ea8c46a8e57194986eb2ef8
+v[17] 44accaac045de3183f7a45f89d4bdb5534594c90296ea664061f3f8a142f2d7e
+i 9
+z f0fb2846d9cb0b88751db963f9360ff2bda25052eba9edd2ec561807c1f0fc27
+
+v[0] 3fca772e14531611cf82782ecff97358f710763698b73e84479056a97d7d352f
+i 0
+z 3fca772e14531611cf82782ecff97358f710763698b73e84479056a97d7d352f
+
+v[0] fd8d6560ef50712fb5f0707c342f618cbbe5697d261d249ad4887dc5ebac4f07
+v[1] 89c98bc89a81402e218e377257bd1532d524dd33a3b8c0458b2e5211d4d7b305
+v[2] e48938f9271a8861d46fa6063563b92c0a6fd59634151b075316faad9c87008e
+v[3] 332fb871bf280cb18dc5d444a565ab1e505d274e52c231808af7d52cc28990de
+v[4] 9073abe824ac2d30ec9562a5a67836af5cf9c038aee85ae1f7d387da64f558d5
+v[5] 04c3ffe8e6ed014162fbe6f3b8467114afdb6d5d51ad878c4462d8a926d9966a
+v[6] 5864d08abd45dd3d4b6e59762a8feb76cdbcbab01a66e512d40bc070e2754ce9
+v[7] 0a780e6ecd9b4ed16cb4fd1b4b060c74d97a4268733855102b036f89cb4d5bac
+v[8] 34bddd4d2ac8a920864e6b9cff04ab70f9978a16d0ceb06aee33aaa78e49328e
+v[9] b65e8424be6a9247ad08f01a28e887bca33b3f5c28ef3adebf37798972eb99fc
+v[10] ebd2aa397fc49104dc1c3f82f275bf625984c8c84a6f699e801b736c667a8cb8
+v[11] 8a704e508538e1d8a64c4c9052f46a07151c79dcf95e6359a8e5f41370ba40e2
+i 4
+z a373abe824ac2d30ec9562a5a67836af5cf9c038aee85ae1f7d387da64f55855
+
+v[0] fb1b4c61b9b2fbe2faa5c0e3227e3c2fd4c8277aa629fc88fc18a4a29df3d6f0
+v[1] 3431d240f65ae76dcca41df165a4eb4c5af155027844d80a0c7f0d07ca4b5761
+v[2] 67e879347f3adcd41cac36e8c80a0f4c2ea80eb08ae9ee2b21e528769eb4c7bb
+v[3] ce843b0190451928f2e637449b5ed95580645a0e0440ab017026631c619d2bcb
+v[4] cc85641974b86dfa780e3edeafc0d6730da6f579826ba8f9bb8ab065b1e149b7
+v[5] 2f0c812e2c9114bef4810a01d108ff001fe328d575cff750e30133b464e2648b
+v[6] 407a5a8964f840ca90aa4cf79a18f5760f7a8ff23bd6bf2d6dfc88c980728aaf
+v[7] 26c2b3f4075ede77023b2de230edf8ce5e75a0cb9f1d81a0d154ba5d79de83f6
+v[8] cd98878185983eebc6f188559d9bbf8dc422eca6598a7df35449d0b39106c706
+v[9] 42aea74be96565c44c08df95a6aa58603085152d4f7fcf38375283859d17a46c
+v[10] 31383c1609e8be3dc7279916eb5bb5d3e95e745a96f55ed3d69f296bfda19a28
+v[11] dc140f380ac16ab63124f9f7a02aa458ceeffbed4a9b8e31f45c67ce6ce1c394
+v[12] 81bb67da90b02b5b19ce9863902f12f33a85795994d7d22b914f0e82a44a4f11
+v[13] fd76e39b1d68f07e538353c0ffeb0c1225f5de64166ccd419c10134329f954de
+v[14] e9f40437c324cacfc6974bee082cdb82c432a86d8465a0229a1e05fb19dec82d
+i 0
+z 0e1c4c61b9b2fbe2faa5c0e3227e3c2fd4c8277aa629fc88fc18a4a29df3d670
+
+v[0] c2b1fe3853bbed5be05536475b2f1bb818eb5ed0111f3be6c6b3bb8ede2d0beb
+v[1] a692dee2a40878814b9ded7ba7ba47a391585ac93af04a0addec3904ed912ec6
+v[2] 015e98f69b98f157f559f8282bfbd20e07cc4a9e2929feab5a8c246011d1098f
+v[3] 76761cf13e45886da2b747f0de3a238be8aaf5868eca88c4de6b614ff3902e12
+v[4] b6b06a046fa5f2e43e698fc96818cc7bf888d5c4f4f2f0bda86cc35c1b48679c
+v[5] d7ecabc614122bb6908ebabcf7bcfa9a4fae88bb8450d559297c778dd35279f8
+v[6] cdd96bbd24cc00b4fa5c8b20efa66a3db1d62e76f001dbd87800fc59f4a29a1d
+v[7] 9c16ca817b43101672fd1cb3583a6b44bfe2ab5956794280a3a32bd2aa651656
+v[8] 4d7ba5f8240527b3c9de386b00dafc163314b3f1311bc30b8434993b50e08d67
+v[9] c4ab9766eee58337a92412440f12083a0205c39ba27e0877613b4288dfce9899
+v[10] 71ca275f3f7df242b5770d37c92425bde86184ab23c06c6b6bec799c47651433
+v[11] 49da5429ec1ade01eba828ad21d230cced84c8a28f239a69194cc0b5de9a0f20
+v[12] fc17ee1656b6f0de36158fe2db82ad3f63c196c54002728bde4c5e27e6c0d7db
+v[13] ece944bcc82f520e8171aefe728863b99a9772cc48b714d82426224b302b7be2
+v[14] d2ea262ae062bc1167e79a7bd8abc2b6c7cbbdc03622495d1ff3a56e23c03f72
+v[15] 9be5176e8e873f9c320cff256e7b8801cdc1cee0b32ddd715d71abeaf909e0bd
+v[16] 0e666632a0ea9c9c5cc3fa519a42c34313ed2f64057106e38dddec87d68146b0
+v[17] dc48385d46bcedbdf17f43e7b2de274556b411a0ac4b7e89a2f5f71a1d1ea5ba
+v[18] 76919d83ecc757cfcd916e23e5cadbdda21793a322c0fadad4e581819ebc0b18
+v[19] 84830e7a1b4b50e6ba90fd5f8b1198aa60b0c8987c962e9eb12adc2cc389ee1d
+i 11
+z 49da5429ec1ade01eba828ad21d230cced84c8a28f239a69194cc0b5de9a0f20
+
+v[0] 99f065bb53134babd50f3f46adb63c64f7600acb39487718bc0a39fd3a5f4ebd
+v[1] f70702612b9b45f7833232a7267492299c23caeffdc4f8a494653cde777861ab
+v[2] 16c9b6b125cb9cbb201cd0a558fd58cc29f2d197b9b160a0cff88ac890b9e429
+v[3] ff87c5e3356c8fb8dbeb739aaedd0df3da2ec3072e5a806569a5847fcbcb4267
+v[4] 01d23260fa58bc7c077e05cac9e1359a9f4f2c9f2bc8312e0832376e3c3cc554
+v[5] b7b5071166d68c704410d4e9123a261631822060c336b8cf0f5685a7df6ae6ea
+v[6] 621633e25b1ba392baaa31fc2d6a57e8286f6bf6e5edd5a0268a895af91d61c8
+v[7] a29ab1d52fde5e7026124c3cec2be1fa674d37692165f46d1d91bb9f41156a55
+v[8] 26d8eb53078f2e515bdee3adc377a16b54ae575343888c27c6d72e07dd7ded04
+v[9] ba5d57dae01659afb41b3b4712f0ccfa3b6b2a0d8a99fa5f1078203925897618
+v[10] 8cf51cab05199e2154a5bf655e6a9e9498c20cd08b564936b164b0a7f49a1e30
+v[11] c5b3977228539a7f573c88800633f1da39a3f1bff9e1018af48f94f211a812b3
+v[12] 149a93a1ded07e398fe248962a7656f9b0f15ce62c4aa0bba4a3c6f00cc362f7
+v[13] 234974b4054622b0672626f111ea5b44afd81dcb15f29974585c9b77476d9290
+v[14] 4be4b2338d92909e6a138d4d2e53e72707a4af62acc8cf2a121c8105ec4ebf32
+v[15] 1e6192c030263e3847898afaf5003000552b9ccba7caf6361c1f34fa0890b086
+v[16] ba698e634085f7dd38da012c8c97efb97a9b3c08c829d660e72e46d12eba79ea
+v[17] 712198efd6734fb564278f1bd0dde082482078548dcf4681e65e6dce39328c1e
+v[18] 8cff8caee2ed08e384331fc0509c1ab44b291d840d19ee991c9978bb7642b4c7
+v[19] 98a539cf588938c8ee31d80ff0254e13460f50d7907885f2debf7b68be91edf0
+v[20] f0cc67c038324ed37948dfd94ab50dc6fd07ea8b441009ea2c4e185f0d800b85
+v[21] 09ae723e872da1687e02c883a254e033e8c67e784ed33e3a28eb8cc92be37d32
+i 6
+z 751633e25b1ba392baaa31fc2d6a57e8286f6bf6e5edd5a0268a895af91d6148
+
+v[0] 97379391993ac07a0b019c4b6d2d08d4555e5761b4faa7bea8eac269844c6106
+v[1] a2aff4f6141eedf254a8f7122ee37a1403b97fddc2805ce4ad010829aee1575e
+v[2] a54665a1ac19c8ab83dad06bb5ce855b45246a9ad338516c5d67948f86eb1aa7
+v[3] b8fa1fa064f6bd0af94d427686a09472b6a841576754500464ac3310cc147d40
+v[4] dbb4cd734b211f5ad48452a193489fa25b0c82a594105a96ad627c5cd5328596
+v[5] 5396b8de36ade038e4424344fb2083226410f771c8ec979e916f37710b56cffe
+v[6] 039b59e759c9a380200b129e08d77ef53d703689b60ba5f117111ddd27f1674a
+v[7] b3456d7bfa566b925ef014c6538c89251b7c0fa9fea89fd1806f97bcbfc3cdb7
+v[8] 4ab7a386cbc720b5676de0e76d584d6fa538a0015debe30c37e1839165763d5c
+v[9] f7f55c12c67c1ca28b3947fb7bd7c4ed9a5240f962425b9b4810191d448af7c5
+v[10] 8dc0a95877c2ea17052b55c9f93440319ec38bbf80b375177e84ad14bab558dd
+v[11] 246d97123750b41e5bf2d96f10b3c9e66e92759373999bd94191a65f25a864f3
+v[12] 5bfa2905cb0b0aef125fb39deb2cd392b3cfe3f3ec58f8361e8cd5f12bd2db98
+v[13] 192413efd53bb958417f65a818d48d6bbf94dcc77210d9623adbca15633bd7ad
+v[14] ee95faf7a7f31c7afd13d393ff2ff4e448799c87c62092e9e646efa4c635d1f4
+v[15] 77c00984400bbdcc81aeb42085c44be70137db5a0464f6081aa9c8e646e96e1c
+v[16] 743cd93d6f6a48161881d2224b7d7c0ce96d56d54adff0b719955cde417b35a6
+v[17] 92b99335dcf6b33de126d05329d8884802cc3afd0f93e9dea7db5f6dbdc6c623
+v[18] 584ccd19fe7395f9f2dc53f2a9da292e0cccfabe82bc46aa64c29581fc570deb
+v[19] f9321c751abb9df278fbc2054e3fa368734cc852589891b49580332a52b6bf72
+v[20] debc2bf3cedb7c897924936aac0b485bc05eb89530c886299e8d1ccad277355a
+v[21] 472d49f8ccc249b8271fd0630ab575721852e98015ea27732915ed06775b444e
+v[22] 7b29b054a2347baeda4dbd1b739072e6d144aae3547adc8287c3af84285057d1
+v[23] d7a79b1f1ca757e17729436fe744ea7d99a64d13bf85737b6a71d41ab13343e4
+v[24] a957b6345193173a231d9db8acb3a6c09bb411d210e0e52c94e75a4d68602aba
+v[25] 6277d818cbecae95f1aea85481ee631ff1e7c77c6693e6349d1804db784238f2
+v[26] 27e1d5a11dd9025508168d9d11cce0b8f0768b6846105161eca53abfa4aeeff6
+v[27] 1823372e2c7cb9fdcdc97ca64ffa06564907b09015472cfa73bf0a45d7c90bec
+v[28] 08cfef24b9eb875598779315de4fcfc918931e05f49b374113c25cb5b23a4944
+v[29] 3a5d9db56bac2f413a3d33b6d7a2f54053aa3a641d6554d6f008779939f2682f
+v[30] 22d0256cb1a53aaefd5d2fde14b63e5adce607ee5a22e8498f29982f88088938
+i 18
+z 6b4ccd19fe7395f9f2dc53f2a9da292e0cccfabe82bc46aa64c29581fc570d6b
+
+v[0] 91a76b64122a404fbf873d65089a7613bd3d93c4227a4b05817223640ec20ee9
+v[1] ab46f7649122de1d73278608e02d44a1367f4f5a7c01d1c17f2a50fb3148dfcf
+i 0
+z a4a76b64122a404fbf873d65089a7613bd3d93c4227a4b05817223640ec20e69
+
+v[0] 1c12d157172079be7ecc31716fac8946f5517a3da6612bf4a0db65707e72764b
+v[1] 9d9ec126bd404e82448a16c187152307ab6319fdd5d4280f070275cedf1cced2
+v[2] 25be86a2abbf7619f7b92855cc50572af4fcf6ee071078d24baa24d623ebe4e5
+v[3] 9b3a13dd1b67a284a9ed869de2663d82035342bc0cad65484da1c7b60b82a55b
+v[4] fb82840bfd348ccaa0d3d362c1123096a5103a09f979e2f4acdf7aa600e55a84
+v[5] c64642a4946ed50924eb1a4c6ab73b53942c5a17cc868f8c6c5ef92ce5986830
+v[6] 8e7aaf58bc15be92a31af4f0b092969a250222e7ccbdb638aa846f8253c33d50
+v[7] 375bb009118659c831591bd6861e9c9eaec85c0fd9a1facd5f2767ff27e3d36f
+v[8] f5b4b72840ef438fb8f7fd1419aa5248dc38126cfc29099cffe68aa94b215b31
+v[9] 3b0cf55a0dc7856788375bfa1390fe4c628c271c99ea76ac78517ad5f36f61ac
+v[10] 82cf74084903490f30152c730970f8b622de5414e1a60e1efafc6aa57ff2fba3
+v[11] 9d476226e3c4f844f392e7efea7726b02bea64c9aa1e78513efb28a000cf9624
+i 11
+z 9d476226e3c4f844f392e7efea7726b02bea64c9aa1e78513efb28a000cf9624
+
+v[0] 4f8b3919461d4408a4d4375688f8985332745cb5253671dd7fea3c58b8e33e5b
+v[1] ecd4f6bf71be54fa88e51fd9d98f60c009fa1b4f15ccacdfa7b26a5ba52b1794
+v[2] b0bc276ac01ed6b25fb569ec8c614f4a9299faadcb93bdee4dc637c888381d29
+v[3] 2fbc1564ecd906f5d56838c9ceb3ba5b5f13925cadd653008f1ee9f54c18ea37
+v[4] 66e9f3ed35f45675f9601181ddcff688229371c6428c1d9dc67699821e3130b6
+v[5] 6b08a213ca51403db7e08bf6945b23ccb62465f582248661b901b6e550345516
+v[6] abdb83672459dad5b11c3cf9e4d21235ff92c01ab00b2d44aa6f10bfe9b274d0
+v[7] f609191b4efb288359af7170acd0904c57d45c7c658c0d670e0fb22f9ebc0044
+v[8] e4056ab4b8afad5e6951c8168477f15ee3e11fe3f236a1d19ea201f78b8898a5
+v[9] f3b253fd18515ee3dcfd4a14409838a3d993a5274bd77a1e5a7088d20ba6c592
+v[10] 710b8819a202ab80bcf308aa94d3305944dc739e33648df045bba215160f8ee9
+v[11] 1b63314e9fbd605ac063546ee4249bf9f37da0b6b78d99848f487c6880f70c3e
+v[12] fb04f3e49a44c4eea104c213446b0e6b81da047a0862604f488e0c6128238d3c
+v[13] 43b1624809a253f46b12d97aa08dc3f16b25613022483b8044cb01b6d23cfb28
+v[14] 0796291d8916b0b70ebdab0f42b8cc55c14734cf7a398d48f94b48d9871ff0c2
+v[15] c55cc772bb71392f13258339eaa1d8b01c402e8f6c9b6061f0e1c564feb98234
+v[16] 882ad3994d999ac7243ebe9955468a52b2242564a295a9740af8980043f9ef0a
+v[17] 201f86fc5826d74580c3bd3fe04cda2a823c2a4d1ace3e862a9bf6873ba25055
+v[18] 5c39347c213f6e1b5ded1de9f92ed21d99721c4e4216d5abe207321caa426971
+v[19] 38ba53a577809f2d2c3cc33016e6141f4a87b6f57b75be70b9cd3d287f07ab00
+v[20] 7b9e12c5293fd99ed3fb50a2eac4587bca4aa8bb97c147626dcb9688593ad2e9
+v[21] 4852c30283c1ffa109aade1353d11e9712d8c4e6d416926f231a2b89b78fbdbd
+v[22] 80d25270ef8002232cd0e35433ecefc135cbcaa06511ba3ac14484b6e41c953a
+v[23] 6159366a1aee4692a9986a12234728c685cf766ad3e2c4cc842f1142c0fb856e
+v[24] 95d34152d18b9942bb13c6bec8e533c259adfd69dbeb06da63c351997463cee9
+v[25] dd5890be52cd0207fecd0f93dbd3a6819aa2c5a592ca0975a419104e7ff4c284
+v[26] d9c3f02b7644b3580d190f03bfc9accc8abf9546463a2171d9cb19b3783e0c92
+v[27] e59449e7a9d07631450d85d108f3cfec2d67d63ad65a7311b310bb10137fcdbc
+i 27
+z f89449e7a9d07631450d85d108f3cfec2d67d63ad65a7311b310bb10137fcd3c
+
+v[0] e5d98efcc2879f32793efa8f96dda9c87b70834fc9d468dc464b0940a7dc160b
+v[1] 04d4bc5cd4690a0c6561feae82c6be57195c7553276f12aa16fb930ac47e315f
+i 0
+z e5d98efcc2879f32793efa8f96dda9c87b70834fc9d468dc464b0940a7dc160b
+
+v[0] bfbed3f0a31b886bd96a817e0b65be1b1e374fddb237514e89fee7ce34a08c45
+v[1] eedd85cd817fc74938e60c366445e6bd5383dedd290db3633d5ed2ff320139a2
+v[2] 006b1e62b3aa1830de71c0ae063fbf090e536304d601e6c851800ff1d501d249
+v[3] a4a63dcc680646b69c8e651dd9c3e043bad07eb9bd6b55bc5bc854d82bbc6b00
+v[4] ffa2e97c95ef5efb87b78e89f35e95f89c1c1b2591673fd2166fcc9765abb4b8
+v[5] 030984d84d3d9667e436996578a3ae58853d44e111990221cd15795167475426
+v[6] da8350e83ac6d67029c24a8d386c6352a27bd22fd6a207474a952742790e4be9
+v[7] 0618b6f82b936b5eca87e9ab8dcd9a2e3744586bae01a75cfabb23b1b64f7aab
+v[8] 5a3e077d0d0d28ba3b6d6fefecc6c2f7ca530fa63bf414976ac8b26ed6596a3b
+v[9] 381e56750672340b18b60612bd462ade52d3b0d5b487f1af8438140740df484a
+v[10] 65275cc865fc4b5d94023fdcb929dd27dcd64870773c79f015d4a5f30751ef2f
+v[11] 724f96fe61888b5a885713d0c52e759726b877031b3f4f80ad24bcf417a3dbba
+v[12] 17f55299b7cd1d851091052401612078978bf2b09fca8c9e2189474e9d24b81f
+v[13] 14b82eebd7325586c1ed8be9353fe5ad9375290a92e76d13947c6405febb2f52
+v[14] eb5a5c7771ccf698a2e803a3a4e6db056ceb0da4d808db5758f2cb28ccc44bee
+v[15] 96db7bfd64b7d41430ca6fd0714487926d02dc71571161f8deea0f6a3b52ba80
+i 6
+z ed8350e83ac6d67029c24a8d386c6352a27bd22fd6a207474a952742790e4b69
+
+###--------------------------------------------------------------------------
+test condswap
+
+x 14e55571df646a69a8280bf8dbf8e9afc15bf5558bb8b8236ebcaa19a96053bd
+y 8bef5021598a8175565e1f2b522ed1c4306fef4e0e973b50d3a03db1fcf11a43
+m 0xffffffff
+xx 8bef5021598a8175565e1f2b522ed1c4306fef4e0e973b50d3a03db1fcf11a43
+yy 27e55571df646a69a8280bf8dbf8e9afc15bf5558bb8b8236ebcaa19a960533d
+
+x 53d8c54864e18f8fc742b2cb996f1d7595122ca9c90de9f49485cf5a5ef05058
+y 9aa95be655b6704a3dd482e8424f82d17443ae26ab41092fad95df9cac678787
+m 0x00000000
+xx 53d8c54864e18f8fc742b2cb996f1d7595122ca9c90de9f49485cf5a5ef05058
+yy ada95be655b6704a3dd482e8424f82d17443ae26ab41092fad95df9cac678707
+
+x 8c7b4ffbf50edf7edcf8d69b67796de38b56a5d4e3a9fb2201354cca0b1b7c57
+y 856e707988c37e59fc6689d024b98bc01b71034484ba194ec7f45106267cb7f6
+m 0xffffffff
+xx 986e707988c37e59fc6689d024b98bc01b71034484ba194ec7f45106267cb776
+yy 8c7b4ffbf50edf7edcf8d69b67796de38b56a5d4e3a9fb2201354cca0b1b7c57
+
+x c8cb24a636f6d8f2c045c8441b21314884a71d55c73d4ef7ad65620ac0d86616
+y 02b47be53df7c8521d57589256e69b8bbeb1e838d84c090287c04a25d5c08e1a
+m 0x00000000
+xx c8cb24a636f6d8f2c045c8441b21314884a71d55c73d4ef7ad65620ac0d86616
+yy 02b47be53df7c8521d57589256e69b8bbeb1e838d84c090287c04a25d5c08e1a
+
+x 7d96f47612fb7135edfa71dd4526d8b4c944d74ddf004e1653d3af52485168b4
+y a4e83162602d20cf71a279c1071038ecf94f38be11ad1191927b3f480d393e1d
+m 0x00000000
+xx 9096f47612fb7135edfa71dd4526d8b4c944d74ddf004e1653d3af5248516834
+yy a4e83162602d20cf71a279c1071038ecf94f38be11ad1191927b3f480d393e1d
+
+x c3a3d4462091b36bd6fd494e70c3166478be0a65bca7f7361246c52dda402981
+y 62d0ae1abbe5cb909328f59e71330269e4f2b1d3c664e7f1f0780e0a4774c262
+m 0xffffffff
+xx 62d0ae1abbe5cb909328f59e71330269e4f2b1d3c664e7f1f0780e0a4774c262
+yy d6a3d4462091b36bd6fd494e70c3166478be0a65bca7f7361246c52dda402901
+
+x 38c9b0d92be50270e29cc3181952e745cbf21c8d145ae0c0a6e59f25394ea59c
+y caf4896a2d3666200741d817ee1dac661652b9a1741ea966d5ed7cbc4c76217a
+m 0x00000000
+xx 4bc9b0d92be50270e29cc3181952e745cbf21c8d145ae0c0a6e59f25394ea51c
+yy caf4896a2d3666200741d817ee1dac661652b9a1741ea966d5ed7cbc4c76217a
+
+x d637a72affa4112bbccd2878208ce34fae442e97175e1b39f43c00b14d312a2b
+y 76209f8b1f152ba7e1e6294f707831021eb2ac03872ed3774ab8fc5e6a0e864f
+m 0x00000000
+xx d637a72affa4112bbccd2878208ce34fae442e97175e1b39f43c00b14d312a2b
+yy 76209f8b1f152ba7e1e6294f707831021eb2ac03872ed3774ab8fc5e6a0e864f
+
+x 12f3bd417fb3860b2a4fd04eb1c51c558a4c5a3dcc1ac457654a45a3cd45b0d4
+y 46f802836c7bde099775f3fb4f5f6345364a7e158bae9e16c4c99aee0cfa5e42
+m 0xffffffff
+xx 46f802836c7bde099775f3fb4f5f6345364a7e158bae9e16c4c99aee0cfa5e42
+yy 25f3bd417fb3860b2a4fd04eb1c51c558a4c5a3dcc1ac457654a45a3cd45b054
+
+x bf1809201f83a34cb07aa2e2372516631ba0513e600956e6702903e9084770c4
+y 414bbc77d13d7b4e706acc07406e8d624f2485463f9948d81b72268c1e086a14
+m 0xffffffff
+xx 414bbc77d13d7b4e706acc07406e8d624f2485463f9948d81b72268c1e086a14
+yy d21809201f83a34cb07aa2e2372516631ba0513e600956e6702903e908477044
+
+x bb8703f2ddaaaaa6ad19219684b1bde576b38bbe9065178b24c1bc55563fe525
+y 1cb3ca7846a3c584b1bc05b25ee91d4779ab9ac64ecef0fcbaea8d311b55d618
+m 0xffffffff
+xx 1cb3ca7846a3c584b1bc05b25ee91d4779ab9ac64ecef0fcbaea8d311b55d618
+yy bb8703f2ddaaaaa6ad19219684b1bde576b38bbe9065178b24c1bc55563fe525
+
+x a07c7110c32e362864a42cd2f371ff420bfd442d291cc15ec079d642b5c85bdf
+y 497fa7867fcd0617c4cd765aa6f46b89390744b5b57d11ab732153e075fcb607
+m 0xffffffff
+xx 497fa7867fcd0617c4cd765aa6f46b89390744b5b57d11ab732153e075fcb607
+yy b37c7110c32e362864a42cd2f371ff420bfd442d291cc15ec079d642b5c85b5f
+
+x 10fddb7f48015b394512257da026938b67f65dd0a84dace51417d68da003a913
+y ebd6706b7cd2ee2d97848ee1adaa990d8ddbfad48e43f51d7ef843fa7597410c
+m 0xffffffff
+xx ebd6706b7cd2ee2d97848ee1adaa990d8ddbfad48e43f51d7ef843fa7597410c
+yy 10fddb7f48015b394512257da026938b67f65dd0a84dace51417d68da003a913
+
+x 1dd835e2173b936a91da37b3aa11e848e4497964a9a78ea929a19105eb981a24
+y 3e6f1ab7d5c460dfb7ad1926c60b64a8dd48ed0115b0655a6d8619666b8c8dde
+m 0xffffffff
+xx 516f1ab7d5c460dfb7ad1926c60b64a8dd48ed0115b0655a6d8619666b8c8d5e
+yy 1dd835e2173b936a91da37b3aa11e848e4497964a9a78ea929a19105eb981a24
+
+x c4541b1380e796a333d88affdccb4d2bc68bc5a1b3890ef2fc1a2c38dbcac725
+y 6f6338ad8dc0562bc02e307743b81013ffff6c135fdf8603f9956b7f94eb55fa
+m 0xffffffff
+xx 826338ad8dc0562bc02e307743b81013ffff6c135fdf8603f9956b7f94eb557a
+yy c4541b1380e796a333d88affdccb4d2bc68bc5a1b3890ef2fc1a2c38dbcac725
+
+x d71f16494f041d1547e5dd9ed539e6b9c1506cebb66f6424e6c7aaf6d0ace080
+y 78c1e6cc0b6f64e161def3b2ede7465f21f6afe61299e9a3c52b1a7a080b9b26
+m 0x00000000
+xx ea1f16494f041d1547e5dd9ed539e6b9c1506cebb66f6424e6c7aaf6d0ace000
+yy 78c1e6cc0b6f64e161def3b2ede7465f21f6afe61299e9a3c52b1a7a080b9b26
+
+x 4d90838ab9cc0a79f4e2aa6a860bf8cfbce5f834aab428d4a06f8ef4a2da582a
+y 53124b302e7675ea5784e2e7d9fdecb38d9c8be158312dd81c51757bafb79b42
+m 0x00000000
+xx 4d90838ab9cc0a79f4e2aa6a860bf8cfbce5f834aab428d4a06f8ef4a2da582a
+yy 53124b302e7675ea5784e2e7d9fdecb38d9c8be158312dd81c51757bafb79b42
+
+x c8e764092ea695b0dd8f0ecbca5a4e02096c821b0f5cd57de8e3e50d8b2a40db
+y db7fb38dfede5259a584dbcc697f259ce380110636e301acb308bf687449110e
+m 0x00000000
+xx dbe764092ea695b0dd8f0ecbca5a4e02096c821b0f5cd57de8e3e50d8b2a405b
+yy db7fb38dfede5259a584dbcc697f259ce380110636e301acb308bf687449110e
+
+x 34cf8e55b3d2494362a87a24907fbdab61cb4f452ef5a889a1aa40a22be6d976
+y 679c6d6f6dca1b71bb098e3854c63ffb8ddb76f1a1cb246ce956fd71d6477c20
+m 0x00000000
+xx 34cf8e55b3d2494362a87a24907fbdab61cb4f452ef5a889a1aa40a22be6d976
+yy 679c6d6f6dca1b71bb098e3854c63ffb8ddb76f1a1cb246ce956fd71d6477c20
+
+x 9638ab322ced065068f98597cc61fc2bd846b5849dc39a881209b8efcbc95eec
+y 32922ff2b62e968417225b765f2787387c8a42fcab1dbec3815298f53813a8cd
+m 0xffffffff
+xx 45922ff2b62e968417225b765f2787387c8a42fcab1dbec3815298f53813a84d
+yy a938ab322ced065068f98597cc61fc2bd846b5849dc39a881209b8efcbc95e6c
+
+###--------------------------------------------------------------------------
+test mulconst
+
+x 8d517a8804d934ae93388e1d59748c3c22866d7be6cec58a357ec43f6dd029db
+a -319312
+z 3f2fea85c9195f2246f4f6fd2e8d5de95c5065edbea45a174bc0d1ef3db4aa54
+
+x 1b5d6a6c9cdd0dabd126e5f5ee2513f3d27c56dd3aad89c882fe9fd2d38a93b9
+a 499342
+z dd310555966ebe7f409dcce2933f91af8e14c8909f78e4f113606789dd7f504b
+
+x 9e03b44e93743e0cf5768f65bd3c0f255e001de330d5e1a863d6e4dbb11748a9
+a -284189
+z 6e8c7f8d0f1476cf2603f5702fe8e8bba5c01e86b6e008ac72987fdd6721183c
+
+x 9cc65e302736aab9bf02dd451c216ac3dd2066af299d7f6bb361eb3b36777f74
+a -15738
+z 8c067e5dccdafaf56301050be17b8895c07e7f13572bbc5ce1af8b5be043d91b
+
+x 7f36ff91ed165c6ee44aca261dc09e3e124c2ed8167064c20d9b84fa226e2555
+a 423857
+z dc7415db1ab5e5a5658d089ced49bf97718bccc55e2f15b83a28157cbe47e559
+
+x e8852c80db69c7e55d476ed00ca7c0735052f7f72f81198a57236feb89a5903c
+a -140934
+z 4923ee40bb01314c2fe9f2f87d0743823311b2d9265219eb7a6de5fdfd09a308
+
+x 505ef65d294b77e260757bc867199c4b0922b5022dfd6a1fe7478ea27ec102c5
+a -307893
+z b14d72c991a0bfc22b1b95934bbe589b6a4a1f9c76a89d7012f8cb03379a8844
+
+x e410c260dc8c1838f3e9658ae586425039b373ee2ab88c750a51853b012af0af
+a 471420
+z 42ae337a920ee1b83768cbf0750f524cf1f9e98b99f195e869785f90a2356756
+
+x e2d181914b54175190462d11402717f42efa37967b2fe0bc4433fd4c862fd646
+a 492178
+z 4c6e1ba6896d2d661fbf99b77f63e3095d3341f04bf258dc3e4f51e39c68f576
+
+x 9cdda0d7da106ef5cfb34774f48308b64953e92869dab0ba804927080509d8a2
+a -312149
+z 4e75e56793563268480efaf6232ad702bc5aef6246bd44e3499ff437810b523b
+
+x 9dac4442858b8dcc324464911e6f23ed046e42612e8105dc3aa2b9eccea15dc8
+a -88818
+z ce52a0897600a05383df0a0b99a451f0d5568146b4323392fc164153715ecb0a
+
+x c9f92ceffa7027ffa71e64b714c36b28a6a18c3608f8170d11d51acbee3c62ba
+a -259755
+z 89582517069925572219b2eec2a25029e8e1c78772ca8c50bf23220d02740763
+
+x 8f8bcf28f4920465680c8e15befba4ebd23c1e27b71c224c98461f69caf76eb1
+a -430350
+z e96b93f0aab6ca70f7d2c1121110efc320aff34e1ec693d7bf17bce1a756d622
+
+x 6f4d413a27388fe84a2585e809927bd470ba1b0dc749ae6e2dfa100617a5a7db
+a 11486
+z 1cf1f5bd0770d949ee36df858e5842805d121722de30d2ef6bc2b82d021fc14b
+
+x e1d05a072d1ab70d895969271f44b7c9d1654171836cf234724d2f90434c04e6
+a 8057
+z e32b3c792cd3b6a770eaa2627ff8de8895873d73d734b961646fbce0643a443d
+
+x d8564ee3ff02c80f0bf3e9cdfce42cd8ac1012ad8ea74f8c0f5754b5775a8de5
+a -304373
+z 884266ea43a6a9b72d113b437dae63c664ef53884c893212fd864412f4e5e457
+
+x bf66769ee0cf873764524e760ee654e8d5090aa774f2e96144d945f8da37af19
+a -159091
+z d7438999b3bdb99a46e2f3dc8492cbaf52b0a19c651cc382c384940861bccb6b
+
+x 72b7d02b1fe23adea87696864c0a9f0466db85e39db397f0eb428a50e277aa2a
+a -521654
+z a611bd153336e178a7f3d912adc2fb39b342132458faeedbdb0a35973efae23e
+
+x ff5c39d4b7fff86810a7a3b14a58bc01e6ecf062116adaa78dac0d1bd3f6039b
+a -140759
+z eb9e32bf7d027cda198048da50aa79a11bc99f3b37a219a2104c78f4affb584f
+
+x a6f1f7f30e3f9e5467f180f92d2c94165fd9427d0c7d383b9077ca9a7e50dac5
+a -317637
+z 56a32847c50bc9609db9796e1650fbe97524aacea746d3cf285f0f2fced01a49
+
+###--------------------------------------------------------------------------
+test mul
+
+## Easy multiplication.
+x 0500000c00003800006000004000000009000006000048000090000040000000
+y 070000180000200000e00000800200000400000c000030000090000080020000
+z de200094610090df0020fe0180270700650d00dc2a00f84100e0340040570000
+
+## Random tests.
+x adcc6f10734dae2273304a6aa493ee8f96e05f2402341c0d997dce58ea57ff6f
+y df3c8d5bb6380fa278d4ff2994c7865bcc146596d3c3126242f0dc3509b57449
+z 5ee2615b75a40367ced4ed4bf1578d13e7afa4d415f38f802b7e7b374365b627
+
+x 054bc4d5e9b78b068fd20645eeb1f03aef2e89a1f56cb50e5f1170a86529526a
+y f976ffa1d1b4a33d0fd866528897cea3eaffdc75e31aa65450a62ff765fe7985
+z 0210280745f6c29a04433f07f880bfd2eddd758d82996e79c65de817c30e7309
+
+x e361c6fedbbe081b7cd683d23a2bf0ac889806be7230b56d9398959713a300ec
+y c8121e53d78c2e9ba2ba7f51b7cb15cec970a63b4a642ac470aa1f2145f07bd0
+z b48bb1c7ddd26cd9e5a2cb73bb3885dbe4a47e03886d4dfd59e5729d544d566a
+
+x 463158a2077f931567d45e19deb4454a2ae77045db70a2c078e160ebdb74fd94
+y 3f311e3f8d225016448fbce3fbfbe84002736e3b0d5a90f57d705ede8706008f
+z 44cd97e25c20ae2fe2ef4f2630981a1fe54c79ebd904bc40e39d9fa615ffa76c
+
+x 1c73fca52556e01204d4b957a01d1049f2247c8666d90c1d3703cff16a38c8bf
+y e9afa0cc85577ec7eb1ac66d87260d5f3659936ff88cde8bd1c3fa1d499e8bcb
+z 0979a8baf734c86a4f57ae400b7790c4985fba3088cb1b265dfc7a66c794121b
+
+x 6e2bab74e427b1a44f0cb181f9dedd6fed43cfd395d3708c4ae8fd2137215eb6
+y ef400834f2dad8763a1a5a58a37d1b36a78873860e4dac808d3166f13724942c
+z 0d481adbce7bd82ebc5a3e5ed7a492e78a032ebf211a5bd2371c528c77954936
+
+x cb3575b41d9521da5c85c6438af14903a8d6d9c3857aa8e101e5295fb277de7b
+y 9f76715d2ae3c8ca182406553d3481fc36d67727ca2d51f5db37940aa3208d8d
+z 0b2fa619265bd424b9e20d38bf4552ad63de8ab552166080d099edea5fbadf7f
+
+x abd66cf3b20dc4c5a866f1a3b965f794a726f96dd00f576d16ead66eea3a1177
+y 97f70fc92e0cda0e010f2a9d7608c33db954af18bc18ad55bf66e7d91ae31abd
+z dcbb2cf34274971ef030827865b093a00761de3da90e46f00e18d0fd934a2b7f
+
+x 3b3c96ff9be8e17e0a0d3979ea5e5623fff5fa18914151abf79fe66639beef06
+y 1d29c361677805f1dd2b839e025e56208a10c0b8d9f2a8c490b0a892c0e27080
+z 0050873016bc67023d0c479fffa56a5a70512f9864d00b0a3e951f1e85c8b412
+
+x b263d4a71b6d963e0a972819e5e5805b9522f142d3c0ff2738c51cce31e9f0d5
+y 64f3fbcff2195c297292df3e1cf900aae457e09864c5a6248ea21ef8efd557d9
+z 7e6f6f511cbf2743c0fc1c6431243908606cb257d20f8a8a0885e6ecd000e811
+
+x 0df0497e1e01dbcc4a48d4865127d9cc31a9a0a56e90cc31619e65c1521b2369
+y 9277f0c6a5bcd7c7ed8dcf7182795f67a12e856b126d09966689834c43aada47
+z 798d270ae34aa2452694b4ff74049a6a5169d71c85bd1a9ac59625e9298cdf1b
+
+x 1dc64bef2189eb5349f5a8983c1854a40141a5390ea4bf8535a15aa71d0289b7
+y fb59dc9b08f9163881b10020ce040da296ed8c1a9a935c27ca0047a4d7f6342b
+z 9fc23104cefd3014a469e6d3a0631338eaf91e24994ecd50bfc0b4547317317e
+
+x 975b108909e87803af98af9425d2a982865b6cc9c144985b32fe5bb842702e24
+y a69e9130dc40be50e827dc50dac05bf900946cf67ec35f1bb1705001314e4fcb
+z 12d042e50d0cff7b43a5ede61ce827a99619bf84995d488fe9eb56a8de769164
+
+x 39c0db5a4b161c368b0f71c7e8ef97dddc444e4a33181e0743519f2a879ae04f
+y d3cc45ff509ed45998bd5f218408ad51f7457b35e8ad69d5431f174047d7c6e5
+z 96b877604f52782ff2a5b1a12d7db642371ca993b648c4971cbf593213503219
+
+x f8c6715e4a327cbbdbb08d74121619abc73dc421d7267029e39b50c1510d2045
+y 63870a83cad4c1c64195ae7b92f3b19c830f35f1a3186815565d846c787c7ffc
+z 286a0b8c6681a7b79a5f85426fb60819b7bd349e93c1e11943c41c8dfd57d00f
+
+x 49c9bcaf5434b8205a348df290a96da27df084f34047efbf91cf544057a50bde
+y 54269f8b23c05b94c9c1cd74eae88d9227af12a6fb337548eb93c2a88a75a8a5
+z 1e3dcab5d7361f00e70198b52e8fb6d1fba74abd79d99480527f6711b21b833b
+
+x c7212b43ff0d10fc52d3a2a7e15bb9cf53856f7ce33b79df89e1d13f95a94511
+y 5213ec20bd054491a5485f665075835da609ad4f3dc005744f061480862ee602
+z e136339fa01067c6c0823a7ebe2f84d917600e244a9883191900bb95a3b59764
+
+x a15d62c6308448f1f70602f43be1825696d228eb170bed55322a21d2b1afa915
+y 58afe65bc8adbe22807026aa1b0d68af330bca268fdc054406aa41c820960e71
+z 996c597e0a024c2ff0ffe289d8c7270e4ea1d38e294d7210eddeb2c0725a1305
+
+x ea233ae033ca93034bc8fd8ea3c0625bbb15b00265264fdd61f62cc808b505fe
+y 09e12ef9b3426991f7119c2e8349278342ed0072317c4ec7ab24561b61396b39
+z 1fd72191fe9f00b0cca6a635d14904bd0c1e0ccd1275e84ad0b7bde134866e2a
+
+x fe1fd3da05524af4ccd538f1d2ede09582101fc2a47c2e63758a546bed6cc5ec
+y 523346406ef3df6ac9a455d0d2e7f732ad01c88245b07a888cc21c40fce11a76
+z de6cac8fdc878d9c4eda6b78f8b629ecf776980e49fed56bab936fc03924f44e
+
+###--------------------------------------------------------------------------
+test sqr
+
+x 4dc87ad85abe8938634492ce2ea10bf48dc4aa2fa37a6a0fde3e5a01e90dde2b
+z 346297c756d77b8ea312ddc455223f4577aea2a2e8d944cb24adb487de143b46
+
+x a33aed91165d7fd13a543760d3915c1b5d411a21895cde81b2f3640b87550cc9
+z f923e49da9d5f45e23a782f911fac1a6c2e67cbbc7b03ee4675a0c5fbec03641
+
+x a1406e453db6c92ef808295d1919c5bb2491c0ce6d5326d276c57e57943e0acc
+z 18425bbd92149991c4545e65495af0e6372289e9a32649c127122243204bdd73
+
+x 70a56b8484234ed002a68c8d535a4e527a61c360f7d4ee5b4970c8ace1e12de0
+z bed1c435139f151d0650577e03c32428f63cdb7bc1920110b5fdbb27f08cb200
+
+x 86c3236a6194f1585b4dbeb09d0247fb7d3ae08063ccf9fc4fde70fc23735710
+z 9b6509acadd5d31c4c843e91cec78be00aec4fdf7d86132965bd6f62f078f711
+
+x 0e5e83c51a8c091673425c38785e0aa1d74c7261a035a891bf734cca8c8a3db3
+z 4efe5029e99438835a8a45d0180b8de357eac82ba9dd8e127baac0d758dfca1d
+
+x 31c39a5afc33f8a8d3c570b9dc5389bea6fdaaeeb44cd7524f6c445b9583a34c
+z 359b7c8791cc87aa8b3c799c9d4d7e1f4062a4f64436d8c01071597e8c262127
+
+x 5a06203c15d6c1db6ea0fcf468a1e3f09d68c4a0f64c3d7e30e70290545e708e
+z 07f8b435ea322bedf613458b1eb420f1d6bc96741d69695899bd40f7eca6f72a
+
+x b1973433646474167b791b326827641260fb33d6a2c96d4e963a6b091f824505
+z 52a62396dbbceead62912f8adfed2707fc25edb51aac19b2a274c246f1209f26
+
+x 96b157d71e107168fac206dd63007f10f4ae1225b0761c470ee18ecdb4fff20b
+z 84ba2a84b156437cdcc39ecc8b1ad01bba934d8dfb7d504b9f2442db0ad01167
+
+x 6167d77675e19785960c28df551b458e41dfd0dfe5e56e785b7367997d5eb0a6
+z 79a558436af4310d3eaee93f9a7cab72bd817fdf59d267e2c530ba8d667a005c
+
+x fb4b2ab08db932ce10dd62639aabbb266f9ce775fb5a5e0875864f18a3ee506c
+z a6013661f2f0ab875739836039bff6bff4c993aefdda43dccecf4c404b9a612a
+
+x ea26bcf0bfc3e15d4df7ddbcac8b5b9e9a7215d74196d77c9e0524e861c6aeb4
+z 113e06861e3d338618695f4713464cea536c8019da77ff0dd9946f3b860df062
+
+x b67b1ffffec757ef147e86cf60898c5dac515f080f43f4e120017caab4eee5ee
+z 7d9748a1ff6ca9cdebeb3dd6668522767afb9ebf1c680fe7fb3f5848f7222036
+
+x c122016f17f12e53f9ac031719fe428c826217b2b757ae44f2f33d1b8b1bb553
+z dc068d032b97c98eea6dd6c8bc42e9a0a6250c81a36a8f64615489e191287c72
+
+x 1266ff0654c08e6183cd6c3cc760cc5c88d1f49b918f2f8f587b3edd4adea513
+z f07f17fadb2e2dbd282d296fe5a15cc5c2baf6b45f5fd5dc4692f252039bc862
+
+x 4c4dd9c6e46fb2c096388583f2a0c969245452b23f16ea43e15064c45357ccef
+z 5127fd4415a84115997b8b3ebe88a590efde9f8b53a43e86b1a4d60782c91025
+
+x 095d149c2616212e5f770f133e719d285a8bc888414271296684e732feb5473f
+z d8038bee551cac14d1c610bbc0960d943b01526072c589bc913ab51fd47bc848
+
+x ad55f9f916d62bb13ceb1461b99e82d76b860c084ca408dd4a18f154b907754a
+z e5c86ee6350c9ab736229f3f53e2ab852641bb8a62fdda609444df377e9ca04a
+
+x 2e4976f45acc671e38add93aa6a89669cdc9874975879b3134dd37c633c9eb14
+z c6513f1a11346d33b05ad65eca13f11125cf70bdcdd6e666a8a7b9c5b6098429
+
+###--------------------------------------------------------------------------
+test inv
+
+x 344ff33a2bc801f861bd13575797da35352c8164808d27f51ea7ca46931b2b1f
+z 07f678dfeef071b038d692bf825cb4e75bc1934bd3a6e3dfea99e78bdaeecf3a
+
+x 670097e2fbbecf6516e949d98f6d722d3f732c33bfb4e62512f9d28d94546b64
+z b2f5cbcd7d8c996ed33a813b1aa39c36f5826b436867bd89b4ce43a156c1e96b
+
+x 234f3bd8760cdc8ae7fac9457da418cd082e42906ffe59a13e52185a7845e61c
+z 7488ff9231e4819684148e16ebc25440732ffe7d211eb3d3263db1af9f1d0513
+
+x 22a39a35b1cabc6dfecd1b898593070f0c81bbd04b4b20f43a9c7c14b5dfe967
+z 892024fdbc8937b9b3aef794f57b8ed8517510b6de3f6088987b1310c1dc7932
+
+x d850c118c69198268826d05650958c6bed55b181090cf1c96493ecc4635a913f
+z 7aeae1b0dc5211f374872e78da8f225325f3f33f9c42bfdeff25d425dff7710f
+
+x 33ccdc0e39f7cd0a61782c87ac089eb7bbcabce4dd222f05088d3d6332efe959
+z 668f87e23239e965c80740d4daa9c913609388f291c11f950684f45e689a061d
+
+x 7c06f93b2f66001c74073b8ba7536049738e89b0a0d859a8a73710de3fadcf79
+z 52df0aa24bb4a7474e6ed9852ba542c1f4c5219372a7b5d60988890e2955491e
+
+x 9a0ce9ff4026bd58abcf8a128dbc55a19c446005834a143634452821d5f9f0ee
+z 79eaa93b6287705c0ba564c31bab1854c7f4354845be065c4bf94d38a7a8b421
+
+x a13a127490bd3443fdba99baf61d113f3aadd6966c9732cd16348f9fbed32e0e
+z 67290b25e6bd7328dd804309a6203c02a75657f593c7e66e48c9192524e5b87b
+
+x 35f7ac3eaa36c4ed338388fe7eda61cf237eff6ddc0847cb0c95255bbaef8ddc
+z 4950601d2cfe75eb9c4524e2f40f404fe82d0014c916dc43d9416cd2e274992d
+
+x 8a058593035986da3a19e63dacaf40fb3db4cf382205fc4e4802e0ff0c61c8d6
+z 6a23b743dc2fa4a4132780cf6edfed4c219760f3b31343b08710ea18d2c0fc43
+
+x a10d03234e700ec92270b6105fdb787d8edd3f960fdd78ea2e169f49dc708d45
+z 101dad1720604d0b093831baaa97fd0701ce773b9c1be1db0403533ad4376c0a
+
+x 52d3b9e030a5ed574f7f9489c47e73f78ef88a39b570045f9ef73c9a3e65f425
+z 83da3e088dbc9a3cbe06496c5a52edc8d7abcbb8a0f839361762137b119d961a
+
+x 9928b5f14ec80a036479d7b08c128e601db880daebef36adde6fbd1f50f82629
+z 8dcaa9a2439b77cbe44928ac2877e09755c505f58df4d0ffb9b23fc256b12779
+
+x 5a956523956f8ace6166ea6cb3c7421f8d1142d26084a81d615f00d578e03448
+z 658a3ee24ec5b5f1d2d12614e535247c9f2f259131b00f654e09b4517c63ea09
+
+x 157492cd38a07802351ca0d1a5615d5c5f254692acce930fb6be351e9a52f088
+z 32fec1eab85ddf8d27a437876e7f5a07f012b02e7971869811c3c31230204164
+
+x 2d07c109c332847567621ef4338e149b99c5bc3bf6e50943695da7fed5d8141e
+z a81472d28a8235bff43ad5cc012d52e95ece3dbc5ba2962dc54cf9e7f81bee04
+
+x 7e172f6c03415e83d4671e0191151d49e5257651ba73848254e68fad0a095c50
+z 1a8efdc57ae9d39ffa64afbc5d2dc1f25a29d365ac3dee0d8529977c14aa4415
+
+x 1934546e37b0bac80319fa7f2f86c18e83de8da830b9d0b5019c26768974eda4
+z ffe55479771f20518d8fc6491055368b5dcce9b4e193d19897f1e116b9cdf946
+
+x 90324ccfe0e34e9b08db1862be3bc17798a8581ee097be76545e3bf9d586a2e6
+z 0f5ccf4920d617c9b4f7fe6e2c9e95e89b5516555d5e3f5f9900485451d7425f
+
+###--------------------------------------------------------------------------
+test quosqrt
+
+x 18798551568191dbfe6bcacf95bf4bf00290de4c773a1d4233d1eae272b3085b
+y 2ee52110807ab6e31e0ed7b4de818d6474b514c63c99206e58a6df38e149123f
+z0 3819accb91d97a3f4dbca732f19723fc772a19b3eb4d307acad706cc7c7e1c1f
+z1 b5e653346e2685c0b24358cd0e68dc0388d5e64c14b2cf853528f9338381e360
+
+x 8671a0ecb7344f2e44fc9066aeb42661e848417e8c51b353680573830857d90f
+y 9c4cfb1aa650924ceaf3e23b260d02b7d8b7dd4445360cad0bd4270428f55292
+z0 
+z1 
+
+x bb0d27e1743f444e2f612c2ff575c6c6663f01869eaa8666774b8baa59b2a714
+y 2fecb156c393d27d7b9a5e4cc2b57cb5524d5b945e92c5b4bdccdd6d00e684c6
+z0 
+z1 
+
+x 59af963f7245901807a46a59d4e49bab5b1fdf3001f63ef4e600ef8150d0e13a
+y b5ac3372ca5435577c416ba46a57879b0ca1df29057c540cac4edacc507b5e23
+z0 
+z1 
+
+x a7b8659775a53e1fa315066be6a37a3f645d782cb69ec6b4f27fcf4daed3d82e
+y 4550c4697a5d29d1a97b50ea65e98ec839567a3fc556ec3790b016c24b867d89
+z0 a190875f536f94ae2af8aae90bf0afabed437b36cf640d85529b150155eed53e
+z1 4c6f78a0ac906b51d5075516f40f505412bc84c9309bf27aad64eafeaa112a41
+
+x 7163512100699c32d5fadbe3583f2f6f314c347f1e66c434b15ac06a5733f3ed
+y 2806d76598a43c24820daaf87afa5a9a4d414e5d8f51993f1b01166bb5479c27
+z0 01d5d023a6c5f7ec1d5df3179bb240e3003a9e3be8ad4e154c6e8f7cb7af6536
+z1 ec2a2fdc593a0813e2a20ce8644dbf1cffc561c41752b1eab391708348509a49
+
+x e950533666a4a1edc3dae30637d6b005e34b614fe75555be0e1759def06a2aee
+y ac5a603347a585ca19eba141b1dd1b8833855e9807776627e8c9f92001a4b9b0
+z0 
+z1 
+
+x d3c5ccb02442548901b3ffa2ed5564735b0b041386fd38e6c40844dc9183006e
+y 5e6f23ccef94660e569bc42093d2b862ca605b81d64bb3589331d015082b4996
+z0 d7d578a72f1ea2dcacd0a96be285e9635230dc297fa7f6e1f2b9754e2d29190c
+z1 162a8758d0e15d23532f56941d7a169cadcf23d68058091e0d468ab1d2d6e673
+
+x 37cad075017c111f99135be6a0f553535d56153cef8839eee1e70614d65df1c2
+y e5f9944a377be3ab64daccfc9e711f4aa522c68a80efd0a70c72cdd4507014b7
+z0 
+z1 
+
+x 85dedba748f478537d016f20b9871e830e513514fbd27141aa54ca77b2a673be
+y 950bc6fb51f6d8c36b7ddc8cb28d9efd498690a46c57888b279de0e549e84c52
+z0 fb7871031556b171a25dfd0483f0e2ed8d24a8acc2d9fc201f42f0b892fd541a
+z1 f2868efceaa94e8e5da202fb7c0f1d1272db57533d2603dfe0bd0f476d02ab65
+
+x d70f399a983c6ad48acca796d9106c5e7681f34bdf34248f6dc54620282bb327
+y cad23bcd1fb96331bc8139f2a8f21d24492e56a7b80e343a7002acc96a739454
+z0 ff70c5bffe08911fb5522b21beecfd80fb018f0afef24fe85cfb7e4a5024960a
+z1 ee8e3a4001f76ee04aadd4de4113027f04fe70f5010db017a30481b5afdb6975
+
+x 71ee96ced0b50bc560f2477a88ea2447573490f71850f084ae0b318cafd8a75f
+y 15c61eefd2c05d72fb07e44a006dfe314d8797f978bab1fe9f9276bcc82b542a
+z0 
+z1 
+
+x c27a9f169b8096308f313ab5a521886084f03ec6d9e8b30e4773d0a3ab1a7c67
+y a7ca0e7fc5566dfc3790a3de164ef26d6452715db428994d438e79f65034d174
+z0 129427bd4c2195fac5a0da4c52ff634c697f18c3b02d0e7aad45a64d03b6e922
+z1 db6bd842b3de6a053a5f25b3ad009cb39680e73c4fd2f18552ba59b2fc49165d
+
+x dd73476aeab865af0775723ebd2128ca71621b1d95231813c3d3cb32b805f418
+y dc6621f2ba82deb8272243baa5d2e177a60b1b780daa3ba081040e05b1d1b2f9
+z0 32ae54f7a7dfa101bad00f723898d29a7307454f86cd1197c44b07d1b997fa1f
+z1 bb51ab0858205efe452ff08dc7672d658cf8bab07932ee683bb4f82e46680560
+
+x 3a3ee482bf7075fa38780616603133ecea7b56acab59d96ebf7192e21c49a806
+y b7e6d647792961137dadce55ce69634379338bbda45fbef9d56be52620738d06
+z0 122b696683c2d1f3feedaf6166037ddbd7281e0c4c875724177f240b54e0dc22
+z1 dbd496997c3d2e0c0112509e99fc822428d7e1f3b378a8dbe880dbf4ab1f235d
+
+x 71f31797a8a36123e4a0b173ee4bc5a04d7799d1eba246df51cf943aeba0270c
+y 7340069440d6c72b4536018eec373f50a1142c9e79de8a5396f994e53c64ab18
+z0 
+z1 
+
+x 0d2a6a9de4d52289cc724840670abcc5a4ee04f1197bd1d230689431b01afce0
+y 21457f6784da81822df90f09b44782bd50a12c4fb378091cd33b177c734e0728
+z0 2b272304b3cca59e26431d91118a95c965bd542191c7cef760b085673e96a432
+z1 c2d8dcfb4c335a61d9bce26eee756a369a42abde6e3831089f4f7a98c1695b4d
+
+x 288b09090258a71747c1a08a51b0894a0c096f5b88ee38ea56a3aaefc1afa0f5
+y a7f6391e06b8972b18e899753bf3853270cae7971774041fa9bf09a55349f950
+z0 
+z1 
+
+x e912e39e2199c3980c5fe3cac6d8bed394367f28213524f006a9b2c0cce4a6dc
+y e6b4a592e37fb5d3af73c486cc211a57d4077c093a161276dcb6eb44303d3ec6
+z0 
+z1 
+
+x ec6785be59b890e07176c09195430b7f5daee0b0898ee744e578ac25873012b6
+y b3cd2df2c2531beeca882607d73f38403d8ff384f99be1ce582536bc3d4bfcd1
+z0 
+z1 
+
+###--------------------------------------------------------------------------
+test sub-mulc-add-sub-mul
+
+## A very basic smoke-test.
+u 03
+v 01
+a 5
+w 01
+x 07
+y 02
+z 37
+
+## Stress the bounds.
+u 000000feffff030000f0ffffdfffff7f000000ffffff03000008ffff1f000040
+v 00
+a 0xfffff
+w 000000feffff030000f0ffffdfffff7f000000ffffff03000008ffff1f000040
+x 000000feffff030000f0ffffdfffff7f000000ffffff03000008ffff1f000040
+y 00
+z 00000cf2ffdf4400a09a000079fdffea040098edffa73b024072ffbfe0feff65
+
+## Random tests.
+u 6f0dc2547ad77f7b3da324876e63c724c1f69cb2bc70ff960f1594f90202e17f
+v 23a2d45c26880166516e6831ab5070dd2247992418ad7cc41155a9362744f763
+a 4783
+w e145b5f91b683918d1efe6193de27909bf9051b0157acfa458bc3f63e5272de5
+x e694fc475a442bd72cbbf11206474e3169fa74ad453aec3034c1dcc1f1dfbce0
+y f9b4f1ac9369241a302f874305cd2d2fba362b5735d36d3e072c7198d7dd4005
+z 08518c9f52236272202869bf7cb549c667f6a27d1c4f18ab58605d63821a6c61
+
+u f1b3d663fb9458ba8e4521e8e2c976fafc8936433b62e316c6dcff794b1ac8d0
+v 2185dd6948ef2339c9a43518dd02eac6518852d1c35858dbdf5c1acf1d995884
+a -128133
+w d7a628aa59d409b755a1ff0d76f37ae8e4a73d47375940c61351074f3c42ad2a
+x 4a353e9e7e9a0700ab2c043cc05f9795cc267e001b64799ca1849f024a42dfd7
+y dbef6513fba5ca19c545b162718eeba960b0930b8ce99c3edac5facf5fddf4f2
+z 9dbfe69897a273171ab4a697f88a0d4b420a3ada7a7f9e67d0ba871e2097026d
+
+u e8624dbe04a1b19102019d7fd9e06fe502764afb92330d03693279e872e84f81
+v 8da8b04024ff708a8b5fa31a6a654fc31d3748f74a897898aa42c2bb65494586
+a -118148
+w 83f63df59ce4b3161427b932ecbd7796bd162b553b70bbfef8a990ba6f20c23e
+x 9d896d69ec478456fb6cad67774c6e3e0e313aadc0564d759380981fb12dc3b8
+y 0e8799aa8de1b1ac4aeae4d1e8cd5936c66b8a0a60c8d17ec23bc9c9f94421ea
+z 2221a87687c127b352e077bf7e975c83c667c8ce603e9d9fa5e02b195c7ad873
+
+u 2527a8ab98898038e9e132a1bc8349a33e2c2f6ec8b6c15b06410177297d30fb
+v 71cdbe058a0357295dd5134fb95a630055f39d9bd8fa0c759b1b70fbef6147d0
+a -14780
+w 0fe111e19ddf5d11d40b584a31888aea4a388540b86d14b962a1a7135114d5b3
+x a6386eeff2764007a570ba7e82a214667c2949a793fa0a52b7665c09285c6661
+y a7557aaa000c8840e08163b7eec08bf24ba275a35d85bfd7813aaafcc22715c8
+z 867491333fc048b229ddb4740b1fe6dca1feebf1d40660814feeb1fce97fca12
+
+u fe07ffcd6b14f75efd74ff983e8e5c20f379b0c78907f0e453753b457fb53159
+v 617f2f7c1153eaea3ccae7dfb07fbe804b2cb5c8205d657c3106b5a60100cafc
+a -128312
+w a0af624a3f54278e2f7cc77f5d0f10750179bb18e07da059feb0bc98fb1d688f
+x ce432859e6d7e691ba9b44d467e8a5f1a97979facd2d3c7deec46e121193133b
+y d60050fad0f5c4b2e042141e4f7a418d3e8a8a308acc96651728f363ee793628
+z b9e4e8873e006d41104b1cd6a32282fa2b94ade000dd57dee6dd506cceb34c34
+
+u b46e84be433f9e4f43ffa2f1f5200013953d820d292e3af978c54401a252111c
+v cb7cec0c48efa4e0e54f05ac18574d5f67bf1a1193d6d58f42183abc9f5bdd49
+a -3288
+w 18603c0562c4d893a699fa6258e2de57e1cafd3e8ad756806d09db0c1ac9f86c
+x 0854368c6b459ba6fcaa95db92605c9d791bf4dcc57bfda2ef318b48f7521d73
+y 0c83d0b2d331ccc62bbcd2d2771b18bc0b909a3bbebcdcb99020952672f050d4
+z d54073b190601f1cc36c25109a5b44f04b6c2240c268bc71cb983d3dfb25cd64
+
+u 1f490365c3b82416fd3866a42a03f3bd643844e0d0cbebb66af54aa35de3efa4
+v dc805758c7e714a2acbc1e467520ecc3b9d23ce5133fe79e377e6d4520cd5196
+a -129141
+w 1a53a3728ef3587085d0b530be8ae95e367927f9ac3b7126445d32b46f3abfad
+x 0af6ce5107ca06fdfe732d11161b197830a963ec667065c5293bbdf843e23672
+y 5bbfb655a175dcf7a4f4fc886a03e3d99cddbd34524c3cd2fb13b793bb2132be
+z 7e5576020e7bac35c7f5b3dc6b60b2c1cca55f6c98141682efb4737963d0307e
+
+u 09e03f5d67a92cf076740e4261833f244b60da6d02cb42278e2ed9183b6eba3a
+v 5a8b665434e91158559cfecf1d43d562c307518a3ce889165b406b1aae38a674
+a -13299
+w 16e0d405bc40f2075f5dd901769def19f15759faef9a5fb6356b94c5c48be3e0
+x 101da726c0dfd102c8eb2178640054248225a6fcfac1bab28a09b59cf38703d6
+y f268d102402d31a33e52a941a06c64a30a721ed55184edfcfcd85db6fe3db676
+z 24fc9112ce6d3d70e8c245f9e2c883290384462065a5a1ab5821b9cf9d61953b
+
+u f86ba345a367c676d99450d4893ef4033201c8ddbb631c4658e4ed24ece98749
+v a3c51a17107327742f44cc2e265482522cf39b6bcbff919bcf99fc033d76348f
+a -88039
+w 5dcbe0be5f9f80b46d2e651504b10a3e481257a4bfacf40d8ccacea9d73dc2ea
+x 2ac88350fbffcbc743d36fe45c80a70a8cbe88be36759943c8e124163e432dec
+y f54685e704df0e499e495b3b77e64aa0ec0c9fc0bb18ed456a412ac6079fe9d2
+z 3e7c00ea9ee49825f5fbb9b704dc720b062d8e08ee8dd410f3d34d255602b56b
+
+u 1cd810875f48ef4c71ecb0997acfa31249ebcc9280e7c2f741038a0529f653d3
+v ba2e564cae8cdc2bea40d64b5598493ac2b11902d91b5aec7a0e4a8649aa7ab2
+a -77488
+w ca4929fb0fed99fd9dca7a21275dbd97185900d4eb362eb09bcb5ce7098aaaa2
+x 89b395b440fab27d3b32e0740caac3ce38affbd80b2f8f7b6709294d6770873e
+y d2cd5ac1ea7b0e1f45bd3cc64b651518dcdf9f25078de7cc4970bf54976a0c8d
+z 06ea5e15853bb29db5cfccd62db2e64067c90a97eab43039cacf4ee639ffe979
+
+u 9960c3131e513fba3241b1f9bdf44fdbe06c43d9cda9e05fdb451eda3e8df394
+v 4c5f72392dddd1b8e84db5bfc2db04985fe3d1226a470c851a489f98d954e6ec
+a -33449
+w 04eacb794c87c19087b793a0e2d187cc7e0b07d265fd6cc46946780d2ab83810
+x 414db559bd22f12717b431310c1063534de5e627e983f4967b2fb38f2c5f87b0
+y 599bee129778596ba77c27a896020fa55123b8635ff3d9efd56fe406de878146
+z 26c7d591e0028dd611d6e84969da716eb740207e49f5ea02f17a3224612def12
+
+u 2cfc4c9cb8ca259bd4ffcbbd498510f8a65cca584303a28ed475584bd1eed111
+v 3223cab1344be86c0af9995a769276cddbf70eaf55caee24dd4ec0d06c2f4309
+a -53728
+w 3a48f8bd8a229fa9f5b9d7c4135ef6c3a251b0ce451f482471f017e963839405
+x bec0e71a657e85e024d91c41b3a2f75f478528d8ae1afb70bdc5da255d20de06
+y 53dc48614937bd5ea1bce51b166bc9947e248a98cd0fac55f632cded216e9cfd
+z 2999f607e716f0c769e9fdeff636568674f3601166d6b7f566a369b5d4e2797a
+
+u c37946f39bde051e4a6f91a18fda21ec2bfcc375b703bbb81fdcc7ff15cfedf4
+v f37e2f1bb6b71763263e742cfd1ce8a9e004a5e06faf0afc52cf49ea89ad9244
+a -69223
+w 0592777a8c77c1713a72b2ce18fa318fa93e9c6e6b870e54723a43408b502b74
+x cf575224b26f636b4b4f28c90995b87d900f6ca5ec9de6c24e65b747d303d221
+y 8ab7d691dd76d7cd63d3456c677987a9e53904a4895f053e3de08786d564c837
+z 1d667ed7c9b93f2972de23f4d633bcb5f2e56e446cba103c3cf2cf0931687b13
+
+u 2afb15ae6438b8eef9d07f2491e43e32a2b9287381c7bf036dce2a1b0a3542e5
+v 18c9bb7c91d5e5ed96e6effc6609fe40e72c5634cac2cf6fb55b083c3339f40a
+a -33255
+w c0c870e0ee2116aa1182b2b4ee4bfde446f721fa6f1bba3a2ed4fb703855c673
+x 91fd148ae6d53a419983999020d845503cc923e012e6869201615fbb8e460360
+y 5d02294b16e04ca4a7fa4fa5dc9f12c7156e2a68c02495ea171a8cf13d35af99
+z f1f90c61c85c137e2e9d5ca7a6b388afd954f6c93548e5fc3b82e02fe875923e
+
+u a7a7193315006fd85c97226f44708d61ecddad2e184d69b0db62f9fb2bc678bb
+v 87a64ef3c67f464441927c08fd1b57d17bd644a422b96f151aa2d7920989e4ac
+a 67151
+w 6b31a270025004a878f214f100a764165033e170ea5e4c52832673cf88f9f0b3
+x 0c0af67c56e0b2336ba06f447ea4f9cbf052147e35f16216b306ef1211ce4142
+y 54fec5270095dfc21f44805ba17565386bc50d45bd1f797ebfa04da5040ad08c
+z 92fdbcabd91ab43baa827594672dede4f0c71d8302b4cc8cd79270aa0c96d915
+
+u 5d72825031c526d9e1efe34fcbbbd81b91460112f9f950e78e12c777a2994a59
+v 4334ab5246765e241435c6faac0a00add3a5adcdafe017121d03b9561d0d3516
+a -66199
+w ef3211bb4e1bac43430e48594577d1d271f76b46ea7e44542c23524b3d6236bc
+x 1bfb4fb8d8429f0dd7a6cbc23dc2357ce9c1c72be3acf0a49abc331ac751e68a
+y 7cf2ea00463d76152e230cb5465ab55d30f09afbd007d2b55393cfe8e348cf9a
+z c0a66f24e5800bec2b9ff65207afd4b29326525b910381d233bd91d51530d046
+
+u 01a66900161a4ad98f028a8da8f10142b4855712a7eb8ffbd699b13b7cc1a471
+v c6f8a0b42c3f2a1109201c7a97e3307f6cb56a1a27f13e4567456d9eac2a2f4e
+a -71473
+w e2eef0e19682ebb44cfdf84c71cb556311432fd948951a661d4240e16bc68d1c
+x f69b44aaff31db04fa4e8f14f51051d353e50110b1562b27d4493ac5e44a5b07
+y 29039f65da48a24be024cf8f1af95ea9b09a08a54eec810e97018add81eec1df
+z a827fcc698403d01f8c2597a582ac8ddd612e5c2a520b0a2428e8dd35c58002d
+
+u bc607923665e36ea0f8206b358fb3a327ef9a70ddcadb2edc49660891e932726
+v 33e905cd1b262eba320c61428704c1d7c354361043ea7233c69f1f691f7c7175
+a -101999
+w e1b804b366c155d0f1a09fdbede434c669bf7f188daa96b8542dcbc9bbe66b6b
+x 413d410937fbf0575bf34c0b70ee6cd5737e17b6058e774f889104b2f6cacc7b
+y 0784aeb89be679694477cf399b605473c2c48887b687a980d7d333632e060e6c
+z 16edc745e1596492fadffd303c31ce5827c3971c591c68f9e2b4f62c967aaa6f
+
+u 904e1b99ee3f860409a2db3aa4e539b2b50cebc57359f23fca21b5bb1306dc50
+v 133d76a1f768d77a6801d73a570b35f6dbbd98aabfa4258445684143cd30a39f
+a -50858
+w 547270fdf41f753a4189d2a9630ab17b4c6034829770a40fd8346e75e92610cf
+x 076c4e34375857b9e6289287e03c744fd60d76c377a772f6edef3ad30e4afafb
+y f2e8a830fe203901f5f34ae6e606aa8f6cffb504b166cba4cdd84d011b783b90
+z 659233daf8ebd47c77b9d46ac65237e1bfdeebbcc552c7db5cf8dd2d4bd1aa2d
+
+u a6f4bce9adbe5a68585c205d20b05c6662748f5f1dd2458defbc126792837a63
+v 8f1110929626587241fd403c8332b2ebbc398d4dd7042b993fc24a18b53e3847
+a 81985
+w 012aaf1e00a521e8e0639ed116e15476f0f8f1c6dff47d860ed60e0bb7c156f7
+x 13aaf4f9f20d64110beef21bde5c7262c4bff80a85a08db1e098d45ec3d69457
+y eb3230fdacce04518359bfa7cff0c9d6d015966545e40e1c1da18b760031b2aa
+z 607f7b77fc8d3ca15cdf6e2abba71853fa74739f83589a4458854ae2db0a4727
diff --git a/f25519.c b/f25519.c
new file mode 100644 (file)
index 0000000..d16943c
--- /dev/null
+++ b/f25519.c
@@ -0,0 +1,876 @@
+/* -*-c-*-
+ *
+ * Arithmetic modulo 2^255 - 19
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of secnet.
+ * See README for full list of copyright holders.
+ *
+ * secnet is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version d of the License, or
+ * (at your option) any later version.
+ *
+ * secnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with secnet; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ *
+ * This file was originally part of Catacomb, but has been automatically
+ * modified for incorporation into secnet: see `import-catacomb-crypto'
+ * for details.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "f25519.h"
+
+/*----- Basic setup -------------------------------------------------------*/
+
+/* Elements x of GF(2^255 - 19) are represented by ten signed integers x_i: x
+ * = SUM_{0<=i<10} x_i 2^ceil(51i/2), mostly following Bernstein's original
+ * paper.
+ */
+
+typedef  int32  piece;  typedef  int64  dblpiece;
+typedef uint32 upiece;  typedef uint64 udblpiece;
+#define P p26
+#define PIECEWD(i) ((i)%2 ? 25 : 26)
+#define NPIECE 10
+
+#define M26 0x03ffffffu
+#define M25 0x01ffffffu
+#define B26 0x04000000u
+#define B25 0x02000000u
+#define B24 0x01000000u
+
+#define PIECES(v) v##0, v##1, v##2, v##3, v##4, v##5, v##6, v##7, v##8, v##9
+#define FETCH(v, w) do {                                               \
+  v##0 = (w)->P[0]; v##1 = (w)->P[1];                                  \
+  v##2 = (w)->P[2]; v##3 = (w)->P[3];                                  \
+  v##4 = (w)->P[4]; v##5 = (w)->P[5];                                  \
+  v##6 = (w)->P[6]; v##7 = (w)->P[7];                                  \
+  v##8 = (w)->P[8]; v##9 = (w)->P[9];                                  \
+} while (0)
+#define STASH(w, v) do {                                               \
+  (w)->P[0] = v##0; (w)->P[1] = v##1;                                  \
+  (w)->P[2] = v##2; (w)->P[3] = v##3;                                  \
+  (w)->P[4] = v##4; (w)->P[5] = v##5;                                  \
+  (w)->P[6] = v##6; (w)->P[7] = v##7;                                  \
+  (w)->P[8] = v##8; (w)->P[9] = v##9;                                  \
+} while (0)
+
+/*----- Debugging machinery -----------------------------------------------*/
+
+#if defined(F25519_DEBUG)
+
+#include <stdio.h>
+
+#include "mp.h"
+#include "mptext.h"
+
+static mp *get_2p255m91(void)
+{
+  mpw w19 = 19;
+  mp *p = MP_NEW, m19;
+
+  p = mp_setbit(p, MP_ZERO, 255);
+  mp_build(&m19, &w19, &w19 + 1);
+  p = mp_sub(p, p, &m19);
+  return (p);
+}
+
+DEF_FDUMP(fdump, piece, PIECEWD, NPIECE, 32, get_2p255m91())
+
+#endif
+
+/*----- Loading and storing -----------------------------------------------*/
+
+/* --- @f25519_load@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to store the result
+ *             @const octet xv[32]@ = source to read
+ *
+ * Returns:    ---
+ *
+ * Use:                Reads an element of %$\gf{2^{255} - 19}$% in external
+ *             representation from @xv@ and stores it in @z@.
+ *
+ *             External representation is little-endian base-256.  Some
+ *             elements have multiple encodings, which are not produced by
+ *             correct software; use of noncanonical encodings is not an
+ *             error, and toleration of them is considered a performance
+ *             feature.
+ */
+
+void f25519_load(f25519 *z, const octet xv[32])
+{
+
+  uint32 xw0 = LOAD32_L(xv +  0), xw1 = LOAD32_L(xv +  4),
+        xw2 = LOAD32_L(xv +  8), xw3 = LOAD32_L(xv + 12),
+        xw4 = LOAD32_L(xv + 16), xw5 = LOAD32_L(xv + 20),
+        xw6 = LOAD32_L(xv + 24), xw7 = LOAD32_L(xv + 28);
+  piece PIECES(x), b, c;
+
+  /* First, split the 32-bit words into the irregularly-sized pieces we need
+   * for the field representation.  These pieces are all positive.  We'll do
+   * the sign correction afterwards.
+   *
+   * It may be that the top bit of the input is set.  Avoid trouble by
+   * folding that back round into the bottom piece of the representation.
+   *
+   * Here, we briefly have 0 <= x_0 < 2^26 + 19, but will resolve this later.
+   * Otherwise, we have 0 <= x_{2i} < 2^26, and 0 <= x_{2i+1} < 2^25.
+   */
+  x0 = ((xw0 <<  0)&0x03ffffff) + 19*((xw7 >> 31)&0x00000001);
+  x1 = ((xw1 <<  6)&0x01ffffc0) |    ((xw0 >> 26)&0x0000003f);
+  x2 = ((xw2 << 13)&0x03ffe000) |    ((xw1 >> 19)&0x00001fff);
+  x3 = ((xw3 << 19)&0x01f80000) |    ((xw2 >> 13)&0x0007ffff);
+  x4 =                              ((xw3 >>  6)&0x03ffffff);
+  x5 =  (xw4 <<  0)&0x01ffffff;
+  x6 = ((xw5 <<  7)&0x03ffff80) |    ((xw4 >> 25)&0x0000007f);
+  x7 = ((xw6 << 13)&0x01ffe000) |    ((xw5 >> 19)&0x00001fff);
+  x8 = ((xw7 << 20)&0x03f00000) |    ((xw6 >> 12)&0x000fffff);
+  x9 =                              ((xw7 >>  6)&0x01ffffff);
+
+  /* Next, we convert these pieces into a roughly balanced signed
+   * representation.  For each piece, check to see if its top bit is set.  If
+   * it is, then lend a bit to the next piece over.  For x_9, this needs to
+   * be carried around, which is a little fiddly.  In particular, we delay
+   * the carry until after all of the pieces have been balanced.  If we don't
+   * do this, then we have to do a more expensive test for nonzeroness to
+   * decide whether to lend a bit leftwards rather than just testing a single
+   * bit.
+   *
+   * This fixes up the anomalous size of x_0: the loan of a bit becomes an
+   * actual carry if x_0 >= 2^26.  By the end, then, we have:
+   *
+   *            { 2^25         if i even
+   *   |x_i| <= {
+   *            { 2^24         if i odd
+   *
+   * Note that we don't try for a canonical representation here: both upper
+   * and lower bounds are achievable.
+   *
+   * All of the x_i at this point are positive, so we don't need to do
+   * anything wierd when masking them.
+   */
+  b = x9&B24; c   = 19&((b >> 19) - (b >> 24)); x9 -= b << 1;
+  b = x8&B25; x9 +=      b >> 25;              x8 -= b << 1;
+  b = x7&B24; x8 +=     b >> 24;               x7 -= b << 1;
+  b = x6&B25; x7 +=     b >> 25;               x6 -= b << 1;
+  b = x5&B24; x6 +=     b >> 24;               x5 -= b << 1;
+  b = x4&B25; x5 +=     b >> 25;               x4 -= b << 1;
+  b = x3&B24; x4 +=     b >> 24;               x3 -= b << 1;
+  b = x2&B25; x3 +=     b >> 25;               x2 -= b << 1;
+  b = x1&B24; x2 +=     b >> 24;               x1 -= b << 1;
+  b = x0&B25; x1 +=     (b >> 25) + (x0 >> 26); x0 = (x0&M26) - (b << 1);
+             x0 +=      c;
+
+  /* And with that, we're done. */
+  STASH(z, x);
+}
+
+/* --- @f25519_store@ --- *
+ *
+ * Arguments:  @octet zv[32]@ = where to write the result
+ *             @const f25519 *x@ = the field element to write
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a field element in the given octet vector in external
+ *             representation.  A canonical encoding is always stored, so,
+ *             in particular, the top bit of @xv[31]@ is always left clear.
+ */
+
+void f25519_store(octet zv[32], const f25519 *x)
+{
+
+  piece PIECES(x), PIECES(y), c, d;
+  uint32 zw0, zw1, zw2, zw3, zw4, zw5, zw6, zw7;
+  mask32 m;
+
+  FETCH(x, x);
+
+  /* First, propagate the carries throughout the pieces.  By the end of this,
+   * we'll have all of the pieces canonically sized and positive, and maybe
+   * there'll be (signed) carry out.  The carry c is in { -1, 0, +1 }, and
+   * the remaining value will be in the half-open interval [0, 2^255).  The
+   * whole represented value is then x + 2^255 c.
+   *
+   * It's worth paying careful attention to the bounds.  We assume that we
+   * start out with |x_i| <= 2^30.  We start by cutting off and reducing the
+   * carry c_9 from the topmost piece, x_9.  This leaves 0 <= x_9 < 2^25; and
+   * we'll have |c_9| <= 2^5.  We multiply this by 19 and we'll add it onto
+   * x_0 and propagate the carries: but what bounds can we calculate on x
+   * before this?
+   *
+   * Let o_i = floor(51 i/2).  We have X_i = SUM_{0<=j<i} x_j 2^{o_i}, so
+   * x = X_10.  We see, inductively, that |X_i| < 2^{31+o_{i-1}}: X_0 = 0;
+   * |x_i| <= 2^30; and |X_{i+1}| = |X_i + x_i 2^{o_i}| <= |X_i| + 2^{30+o_i}
+   * < 2^{31+o_i}.  Then x = X_9 + 2^230 x_9, and we have better bounds for
+   * x_9, so
+   *
+   *   -2^235 < x + 19 c_9 < 2^255 + 2^235
+   *
+   * Here, the x_i are signed, so we must be cautious about bithacking them.
+   */
+             c = ASR(piece, x9, 25); x9 = (upiece)x9&M25;
+  x0 += 19*c; c = ASR(piece, x0, 26); x0 = (upiece)x0&M26;
+  x1 +=    c; c = ASR(piece, x1, 25); x1 = (upiece)x1&M25;
+  x2 +=    c; c = ASR(piece, x2, 26); x2 = (upiece)x2&M26;
+  x3 +=    c; c = ASR(piece, x3, 25); x3 = (upiece)x3&M25;
+  x4 +=    c; c = ASR(piece, x4, 26); x4 = (upiece)x4&M26;
+  x5 +=    c; c = ASR(piece, x5, 25); x5 = (upiece)x5&M25;
+  x6 +=    c; c = ASR(piece, x6, 26); x6 = (upiece)x6&M26;
+  x7 +=    c; c = ASR(piece, x7, 25); x7 = (upiece)x7&M25;
+  x8 +=    c; c = ASR(piece, x8, 26); x8 = (upiece)x8&M26;
+  x9 +=    c; c = ASR(piece, x9, 25); x9 = (upiece)x9&M25;
+
+  /* Now we have a slightly fiddly job to do.  If c = +1, or if c = 0 and
+   * x >= 2^255 - 19, then we should subtract 2^255 - 19 from the whole
+   * value; if c = -1 then we should add 2^255 - 19; and otherwise we should
+   * do nothing.
+   *
+   * But conditional behaviour is bad, m'kay.  So here's what we do instead.
+   *
+   * The first job is to sort out what we wanted to do.  If c = -1 then we
+   * want to (a) invert the constant addend and (b) feed in a carry-in;
+   * otherwise, we don't.
+   */
+  m = SIGN(c);
+  d = m&1;
+
+  /* Now do the addition/subtraction.  Remember that all of the x_i are
+   * nonnegative, so shifting and masking are safe and easy.
+   */
+  d += x0 + (19 ^ (M26&m)); y0 = d&M26; d >>= 26;
+  d += x1 +      (M25&m);  y1 = d&M25; d >>= 25;
+  d += x2 +      (M26&m);  y2 = d&M26; d >>= 26;
+  d += x3 +      (M25&m);  y3 = d&M25; d >>= 25;
+  d += x4 +      (M26&m);  y4 = d&M26; d >>= 26;
+  d += x5 +      (M25&m);  y5 = d&M25; d >>= 25;
+  d += x6 +      (M26&m);  y6 = d&M26; d >>= 26;
+  d += x7 +      (M25&m);  y7 = d&M25; d >>= 25;
+  d += x8 +      (M26&m);  y8 = d&M26; d >>= 26;
+  d += x9 +      (M25&m);  y9 = d&M25; d >>= 25;
+
+  /* The final carry-out is in d; since we only did addition, and the x_i are
+   * nonnegative, then d is in { 0, 1 }.  We want to keep y, rather than x,
+   * if (a) c /= 0 (in which case we know that the old value was
+   * unsatisfactory), or (b) if d = 1 (in which case, if c = 0, we know that
+   * the subtraction didn't cause a borrow, so we must be in the case where
+   * 2^255 - 19 <= x < 2^255).
+   */
+  m = NONZEROP(c) | ~NONZEROP(d - 1);
+  x0 = (y0&m) | (x0&~m); x1 = (y1&m) | (x1&~m);
+  x2 = (y2&m) | (x2&~m); x3 = (y3&m) | (x3&~m);
+  x4 = (y4&m) | (x4&~m); x5 = (y5&m) | (x5&~m);
+  x6 = (y6&m) | (x6&~m); x7 = (y7&m) | (x7&~m);
+  x8 = (y8&m) | (x8&~m); x9 = (y9&m) | (x9&~m);
+
+  /* Extract 32-bit words from the value. */
+  zw0 = ((x0 >>  0)&0x03ffffff) | (((uint32)x1 << 26)&0xfc000000);
+  zw1 = ((x1 >>  6)&0x0007ffff) | (((uint32)x2 << 19)&0xfff80000);
+  zw2 = ((x2 >> 13)&0x00001fff) | (((uint32)x3 << 13)&0xffffe000);
+  zw3 = ((x3 >> 19)&0x0000003f) | (((uint32)x4 <<  6)&0xffffffc0);
+  zw4 = ((x5 >>  0)&0x01ffffff) | (((uint32)x6 << 25)&0xfe000000);
+  zw5 = ((x6 >>  7)&0x0007ffff) | (((uint32)x7 << 19)&0xfff80000);
+  zw6 = ((x7 >> 13)&0x00000fff) | (((uint32)x8 << 12)&0xfffff000);
+  zw7 = ((x8 >> 20)&0x0000003f) | (((uint32)x9 <<  6)&0x7fffffc0);
+
+  /* Store the result as an octet string. */
+  STORE32_L(zv +  0, zw0); STORE32_L(zv +  4, zw1);
+  STORE32_L(zv +  8, zw2); STORE32_L(zv + 12, zw3);
+  STORE32_L(zv + 16, zw4); STORE32_L(zv + 20, zw5);
+  STORE32_L(zv + 24, zw6); STORE32_L(zv + 28, zw7);
+}
+
+/* --- @f25519_set@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to write the result
+ *             @int a@ = a small-ish constant
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets @z@ to equal @a@.
+ */
+
+void f25519_set(f25519 *x, int a)
+{
+  unsigned i;
+
+  x->P[0] = a;
+  for (i = 1; i < NPIECE; i++) x->P[i] = 0;
+}
+
+/*----- Basic arithmetic --------------------------------------------------*/
+
+/* --- @f25519_add@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the sum %$x + y$%.
+ */
+
+void f25519_add(f25519 *z, const f25519 *x, const f25519 *y)
+{
+  z->P[0] = x->P[0] + y->P[0]; z->P[1] = x->P[1] + y->P[1];
+  z->P[2] = x->P[2] + y->P[2]; z->P[3] = x->P[3] + y->P[3];
+  z->P[4] = x->P[4] + y->P[4]; z->P[5] = x->P[5] + y->P[5];
+  z->P[6] = x->P[6] + y->P[6]; z->P[7] = x->P[7] + y->P[7];
+  z->P[8] = x->P[8] + y->P[8]; z->P[9] = x->P[9] + y->P[9];
+}
+
+/* --- @f25519_sub@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the difference %$x - y$%.
+ */
+
+void f25519_sub(f25519 *z, const f25519 *x, const f25519 *y)
+{
+  z->P[0] = x->P[0] - y->P[0]; z->P[1] = x->P[1] - y->P[1];
+  z->P[2] = x->P[2] - y->P[2]; z->P[3] = x->P[3] - y->P[3];
+  z->P[4] = x->P[4] - y->P[4]; z->P[5] = x->P[5] - y->P[5];
+  z->P[6] = x->P[6] - y->P[6]; z->P[7] = x->P[7] - y->P[7];
+  z->P[8] = x->P[8] - y->P[8]; z->P[9] = x->P[9] - y->P[9];
+}
+
+/* --- @f25519_neg@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
+ *             @const f25519 *x@ = an operand
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z = -x@.
+ */
+
+void f25519_neg(f25519 *z, const f25519 *x)
+{
+  z->P[0] = -x->P[0]; z->P[1] = -x->P[1];
+  z->P[2] = -x->P[2]; z->P[3] = -x->P[3];
+  z->P[4] = -x->P[4]; z->P[5] = -x->P[5];
+  z->P[6] = -x->P[6]; z->P[7] = -x->P[7];
+  z->P[8] = -x->P[8]; z->P[9] = -x->P[9];
+}
+
+/*----- Constant-time utilities -------------------------------------------*/
+
+/* --- @f25519_pick2@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x, *y@ = two operands
+ *             @uint32 m@ = a mask
+ *
+ * Returns:    ---
+ *
+ * Use:                If @m@ is zero, set @z = y@; if @m@ is all-bits-set, then set
+ *             @z = x@.  If @m@ has some other value, then scramble @z@ in
+ *             an unhelpful way.
+ */
+
+void f25519_pick2(f25519 *z, const f25519 *x, const f25519 *y, uint32 m)
+{
+  mask32 mm = FIX_MASK32(m);
+
+  z->P[0] = PICK2(x->P[0], y->P[0], mm);
+  z->P[1] = PICK2(x->P[1], y->P[1], mm);
+  z->P[2] = PICK2(x->P[2], y->P[2], mm);
+  z->P[3] = PICK2(x->P[3], y->P[3], mm);
+  z->P[4] = PICK2(x->P[4], y->P[4], mm);
+  z->P[5] = PICK2(x->P[5], y->P[5], mm);
+  z->P[6] = PICK2(x->P[6], y->P[6], mm);
+  z->P[7] = PICK2(x->P[7], y->P[7], mm);
+  z->P[8] = PICK2(x->P[8], y->P[8], mm);
+  z->P[9] = PICK2(x->P[9], y->P[9], mm);
+}
+
+/* --- @f25519_pickn@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result
+ *             @const f25519 *v@ = a table of entries
+ *             @size_t n@ = the number of entries in @v@
+ *             @size_t i@ = an index
+ *
+ * Returns:    ---
+ *
+ * Use:                If @0 <= i < n < 32@ then set @z = v[i]@.  If @n >= 32@ then
+ *             do something unhelpful; otherwise, if @i >= n@ then set @z@
+ *             to zero.
+ */
+
+void f25519_pickn(f25519 *z, const f25519 *v, size_t n, size_t i)
+{
+  uint32 b = (uint32)1 << (31 - i);
+  mask32 m;
+
+  z->P[0] = z->P[1] = z->P[2] = z->P[3] = z->P[4] =
+    z->P[5] = z->P[6] = z->P[7] = z->P[8] = z->P[9] = 0;
+  while (n--) {
+    m = SIGN(b);
+    CONDPICK(z->P[0], v->P[0], m);
+    CONDPICK(z->P[1], v->P[1], m);
+    CONDPICK(z->P[2], v->P[2], m);
+    CONDPICK(z->P[3], v->P[3], m);
+    CONDPICK(z->P[4], v->P[4], m);
+    CONDPICK(z->P[5], v->P[5], m);
+    CONDPICK(z->P[6], v->P[6], m);
+    CONDPICK(z->P[7], v->P[7], m);
+    CONDPICK(z->P[8], v->P[8], m);
+    CONDPICK(z->P[9], v->P[9], m);
+    v++; b <<= 1;
+  }
+}
+
+/* --- @f25519_condswap@ --- *
+ *
+ * Arguments:  @f25519 *x, *y@ = two operands
+ *             @uint32 m@ = a mask
+ *
+ * Returns:    ---
+ *
+ * Use:                If @m@ is zero, do nothing; if @m@ is all-bits-set, then
+ *             exchange @x@ and @y@.  If @m@ has some other value, then
+ *             scramble @x@ and @y@ in an unhelpful way.
+ */
+
+void f25519_condswap(f25519 *x, f25519 *y, uint32 m)
+{
+  mask32 mm = FIX_MASK32(m);
+
+  CONDSWAP(x->P[0], y->P[0], mm);
+  CONDSWAP(x->P[1], y->P[1], mm);
+  CONDSWAP(x->P[2], y->P[2], mm);
+  CONDSWAP(x->P[3], y->P[3], mm);
+  CONDSWAP(x->P[4], y->P[4], mm);
+  CONDSWAP(x->P[5], y->P[5], mm);
+  CONDSWAP(x->P[6], y->P[6], mm);
+  CONDSWAP(x->P[7], y->P[7], mm);
+  CONDSWAP(x->P[8], y->P[8], mm);
+  CONDSWAP(x->P[9], y->P[9], mm);
+}
+
+/* --- @f25519_condneg@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
+ *             @const f25519 *x@ = an operand
+ *             @uint32 m@ = a mask
+ *
+ * Returns:    ---
+ *
+ * Use:                If @m@ is zero, set @z = x@; if @m@ is all-bits-set, then set
+ *             @z = -x@.  If @m@ has some other value then scramble @z@ in
+ *             an unhelpful way.
+ */
+
+void f25519_condneg(f25519 *z, const f25519 *x, uint32 m)
+{
+  mask32 m_xor = FIX_MASK32(m);
+  piece m_add = m&1;
+# define CONDNEG(x) (((x) ^ m_xor) + m_add)
+
+  z->P[0] = CONDNEG(x->P[0]);
+  z->P[1] = CONDNEG(x->P[1]);
+  z->P[2] = CONDNEG(x->P[2]);
+  z->P[3] = CONDNEG(x->P[3]);
+  z->P[4] = CONDNEG(x->P[4]);
+  z->P[5] = CONDNEG(x->P[5]);
+  z->P[6] = CONDNEG(x->P[6]);
+  z->P[7] = CONDNEG(x->P[7]);
+  z->P[8] = CONDNEG(x->P[8]);
+  z->P[9] = CONDNEG(x->P[9]);
+
+#undef CONDNEG
+}
+
+/*----- Multiplication ----------------------------------------------------*/
+
+/* Let B = 2^63 - 1 be the largest value such that +B and -B can be
+ * represented in a double-precision piece.  On entry, it must be the case
+ * that |X_i| <= M <= B - 2^25 for some M.  If this is the case, then, on
+ * exit, we will have |Z_i| <= 2^25 + 19 M/2^25.
+ */
+#define CARRYSTEP(z, x, m, b, f, xx, n) do {                           \
+  (z) = (dblpiece)((udblpiece)(x)&(m)) - (b) +                         \
+    (f)*ASR(dblpiece, (xx), (n));                                      \
+} while (0)
+#define CARRY_REDUCE(z, x) do {                                                \
+  dblpiece PIECES(_t);                                                 \
+                                                                       \
+  /* Bias the input pieces.  This keeps the carries and so on centred  \
+   * around zero rather than biased positive.                          \
+   */                                                                  \
+  _t0 = (x##0) + B25; _t1 = (x##1) + B24;                              \
+  _t2 = (x##2) + B25; _t3 = (x##3) + B24;                              \
+  _t4 = (x##4) + B25; _t5 = (x##5) + B24;                              \
+  _t6 = (x##6) + B25; _t7 = (x##7) + B24;                              \
+  _t8 = (x##8) + B25; _t9 = (x##9) + B24;                              \
+                                                                       \
+  /* Calculate the reduced pieces.  Careful with the bithacking. */    \
+  CARRYSTEP(z##0, _t0, M26, B25, 19, _t9, 25);                         \
+  CARRYSTEP(z##1, _t1, M25, B24,  1, _t0, 26);                         \
+  CARRYSTEP(z##2, _t2, M26, B25,  1, _t1, 25);                         \
+  CARRYSTEP(z##3, _t3, M25, B24,  1, _t2, 26);                         \
+  CARRYSTEP(z##4, _t4, M26, B25,  1, _t3, 25);                         \
+  CARRYSTEP(z##5, _t5, M25, B24,  1, _t4, 26);                         \
+  CARRYSTEP(z##6, _t6, M26, B25,  1, _t5, 25);                         \
+  CARRYSTEP(z##7, _t7, M25, B24,  1, _t6, 26);                         \
+  CARRYSTEP(z##8, _t8, M26, B25,  1, _t7, 25);                         \
+  CARRYSTEP(z##9, _t9, M25, B24,  1, _t8, 26);                         \
+} while (0)
+
+/* --- @f25519_mulconst@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
+ *             @const f25519 *x@ = an operand
+ *             @long a@ = a small-ish constant; %$|a| < 2^{20}$%.
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the product %$a x$%.
+ */
+
+void f25519_mulconst(f25519 *z, const f25519 *x, long a)
+{
+
+  piece PIECES(x);
+  dblpiece PIECES(z), aa = a;
+
+  FETCH(x, x);
+
+  /* Suppose that |x_i| <= 2^27, and |a| <= 2^23.  Then we'll have
+   * |z_i| <= 2^50.
+   */
+  z0 = aa*x0; z1 = aa*x1; z2 = aa*x2; z3 = aa*x3; z4 = aa*x4;
+  z5 = aa*x5; z6 = aa*x6; z7 = aa*x7; z8 = aa*x8; z9 = aa*x9;
+
+  /* Following `CARRY_REDUCE', we'll have |z_i| <= 2^26. */
+  CARRY_REDUCE(z, z);
+  STASH(z, z);
+}
+
+/* --- @f25519_mul@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the product %$x y$%.
+ */
+
+void f25519_mul(f25519 *z, const f25519 *x, const f25519 *y)
+{
+
+  piece PIECES(x), PIECES(y);
+  dblpiece PIECES(z);
+  unsigned i;
+
+  FETCH(x, x); FETCH(y, y);
+
+  /* Suppose that |x_i|, |y_i| <= 2^27.  Then we'll have
+   *
+   *   |z_0| <= 267*2^54
+   *   |z_1| <= 154*2^54
+   *   |z_2| <= 213*2^54
+   *   |z_3| <= 118*2^54
+   *   |z_4| <= 159*2^54
+   *   |z_5| <=  82*2^54
+   *   |z_6| <= 105*2^54
+   *   |z_7| <=  46*2^54
+   *   |z_8| <=  51*2^54
+   *   |z_9| <=  10*2^54
+   *
+   * all of which are less than 2^63 - 2^25.
+   */
+
+#define M(a, b) ((dblpiece)(a)*(b))
+  z0 =    M(x0, y0) +
+       19*(M(x2, y8) + M(x4, y6) + M(x6, y4) + M(x8, y2)) +
+       38*(M(x1, y9) + M(x3, y7) + M(x5, y5) + M(x7, y3) + M(x9, y1));
+  z1 =    M(x0, y1) + M(x1, y0) +
+       19*(M(x2, y9) + M(x3, y8) + M(x4, y7) + M(x5, y6) +
+          M(x6, y5) + M(x7, y4) + M(x8, y3) + M(x9, y2));
+  z2 =    M(x0, y2) + M(x2, y0) +
+       2* M(x1, y1) +
+       19*(M(x4, y8) + M(x6, y6) + M(x8, y4)) +
+       38*(M(x3, y9) + M(x5, y7) + M(x7, y5) + M(x9, y3));
+  z3 =    M(x0, y3) + M(x1, y2) + M(x2, y1) + M(x3, y0) +
+       19*(M(x4, y9) + M(x5, y8) + M(x6, y7) +
+          M(x7, y6) + M(x8, y5) + M(x9, y4));
+  z4 =    M(x0, y4) + M(x2, y2) + M(x4, y0) +
+       2*(M(x1, y3) + M(x3, y1)) +
+       19*(M(x6, y8) + M(x8, y6)) +
+       38*(M(x5, y9) + M(x7, y7) + M(x9, y5));
+  z5 =    M(x0, y5) + M(x1, y4) + M(x2, y3) +
+          M(x3, y2) + M(x4, y1) + M(x5, y0) +
+       19*(M(x6, y9) + M(x7, y8) + M(x8, y7) + M(x9, y6));
+  z6 =    M(x0, y6) + M(x2, y4) + M(x4, y2) + M(x6, y0) +
+       2*(M(x1, y5) + M(x3, y3) + M(x5, y1)) +
+       19* M(x8, y8) +
+       38*(M(x7, y9) + M(x9, y7));
+  z7 =    M(x0, y7) + M(x1, y6) + M(x2, y5) + M(x3, y4) +
+          M(x4, y3) + M(x5, y2) + M(x6, y1) + M(x7, y0) +
+       19*(M(x8, y9) + M(x9, y8));
+  z8 =    M(x0, y8) + M(x2, y6) + M(x4, y4) + M(x6, y2) + M(x8, y0) +
+       2*(M(x1, y7) + M(x3, y5) + M(x5, y3) + M(x7, y1)) +
+       38* M(x9, y9);
+  z9 =    M(x0, y9) + M(x1, y8) + M(x2, y7) + M(x3, y6) + M(x4, y5) +
+          M(x5, y4) + M(x6, y3) + M(x7, y2) + M(x8, y1) + M(x9, y0);
+#undef M
+
+  /* From above, we have |z_i| <= 2^63 - 2^25.  A pass of `CARRY_REDUCE' will
+   * leave |z_i| <= 2^38 + 2^25; and a second pass will leave |z_i| <= 2^25 +
+   * 2^13, which is comfortable for an addition prior to the next
+   * multiplication.
+   */
+  for (i = 0; i < 2; i++) CARRY_REDUCE(z, z);
+  STASH(z, z);
+}
+
+/* --- @f25519_sqr@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x@ = an operand
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the square %$x^2$%.
+ */
+
+void f25519_sqr(f25519 *z, const f25519 *x)
+{
+
+  piece PIECES(x);
+  dblpiece PIECES(z);
+  unsigned i;
+
+  FETCH(x, x);
+
+  /* See `f25519_mul' for bounds. */
+
+#define M(a, b) ((dblpiece)(a)*(b))
+  z0 =    M(x0, x0) +
+       38*(M(x2, x8) + M(x4, x6) + M(x5, x5)) +
+       76*(M(x1, x9) + M(x3, x7));
+  z1 =  2* M(x0, x1) +
+       38*(M(x2, x9) + M(x3, x8) + M(x4, x7) + M(x5, x6));
+  z2 = 2*(M(x0, x2) + M(x1, x1)) +
+       19* M(x6, x6) +
+       38* M(x4, x8) +
+       76*(M(x3, x9) + M(x5, x7));
+  z3 =  2*(M(x0, x3) + M(x1, x2)) +
+       38*(M(x4, x9) + M(x5, x8) + M(x6, x7));
+  z4 =    M(x2, x2) +
+       2* M(x0, x4) +
+       4* M(x1, x3) +
+       38*(M(x6, x8) + M(x7, x7)) +
+       76* M(x5, x9);
+  z5 = 2*(M(x0, x5) + M(x1, x4) + M(x2, x3)) +
+       38*(M(x6, x9) + M(x7, x8));
+  z6 = 2*(M(x0, x6) + M(x2, x4) + M(x3, x3)) +
+       4* M(x1, x5) +
+       19* M(x8, x8) +
+       76* M(x7, x9);
+  z7 = 2*(M(x0, x7) + M(x1, x6) + M(x2, x5) + M(x3, x4)) +
+       38* M(x8, x9);
+  z8 =    M(x4, x4) +
+       2*(M(x0, x8) + M(x2, x6)) +
+       4*(M(x1, x7) + M(x3, x5)) +
+       38* M(x9, x9);
+  z9 = 2*(M(x0, x9) + M(x1, x8) + M(x2, x7) + M(x3, x6) + M(x4, x5));
+#undef M
+
+  /* See `f25519_mul' for details. */
+  for (i = 0; i < 2; i++) CARRY_REDUCE(z, z);
+  STASH(z, z);
+}
+
+/*----- More complicated things -------------------------------------------*/
+
+/* --- @f25519_inv@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
+ *             @const f25519 *x@ = an operand
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores in @z@ the multiplicative inverse %$x^{-1}$%.  If
+ *             %$x = 0$% then @z@ is set to zero.  This is considered a
+ *             feature.
+ */
+
+void f25519_inv(f25519 *z, const f25519 *x)
+{
+  f25519 t, u, t2, t11, t2p10m1, t2p50m1;
+  unsigned i;
+
+#define SQRN(z, x, n) do {                                             \
+  f25519_sqr((z), (x));                                                        \
+  for (i = 1; i < (n); i++) f25519_sqr((z), (z));                      \
+} while (0)
+
+  /* Calculate x^-1 = x^(p - 2) = x^(2^255 - 21), which also handles x = 0 as
+   * intended.  The addition chain here is from Bernstein's implementation; I
+   * couldn't find a better one.
+   */                                  /* step | value */
+  f25519_sqr(&t2, x);                  /*    1 | 2 */
+  SQRN(&u, &t2, 2);                    /*    3 | 8 */
+  f25519_mul(&t, &u, x);               /*    4 | 9 */
+  f25519_mul(&t11, &t, &t2);           /*    5 | 11 = 2^5 - 21 */
+  f25519_sqr(&u, &t11);                        /*    6 | 22 */
+  f25519_mul(&t, &t, &u);              /*    7 | 31 = 2^5 - 1 */
+  SQRN(&u, &t, 5);                     /*   12 | 2^10 - 2^5 */
+  f25519_mul(&t2p10m1, &t, &u);                /*   13 | 2^10 - 1 */
+  SQRN(&u, &t2p10m1, 10);              /*   23 | 2^20 - 2^10 */
+  f25519_mul(&t, &t2p10m1, &u);                /*   24 | 2^20 - 1 */
+  SQRN(&u, &t, 20);                    /*   44 | 2^40 - 2^20 */
+  f25519_mul(&t, &t, &u);              /*   45 | 2^40 - 1 */
+  SQRN(&u, &t, 10);                    /*   55 | 2^50 - 2^10 */
+  f25519_mul(&t2p50m1, &t2p10m1, &u);  /*   56 | 2^50 - 1 */
+  SQRN(&u, &t2p50m1, 50);              /*  106 | 2^100 - 2^50 */
+  f25519_mul(&t, &t2p50m1, &u);                /*  107 | 2^100 - 1 */
+  SQRN(&u, &t, 100);                   /*  207 | 2^200 - 2^100 */
+  f25519_mul(&t, &t, &u);              /*  208 | 2^200 - 1 */
+  SQRN(&u, &t, 50);                    /*  258 | 2^250 - 2^50 */
+  f25519_mul(&t, &t2p50m1, &u);                /*  259 | 2^250 - 1 */
+  SQRN(&u, &t, 5);                     /*  264 | 2^255 - 2^5 */
+  f25519_mul(z, &u, &t11);             /*  265 | 2^255 - 21 */
+
+#undef SQRN
+}
+
+/* --- @f25519_quosqrt@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x, *y@ = two operands
+ *
+ * Returns:    Zero if successful, @-1@ if %$x/y$% is not a square.
+ *
+ * Use:                Stores in @z@ the one of the square roots %$\pm\sqrt{x/y}$%.
+ *             If %$x = y = 0% then the result is zero; if %$y = 0$% but %$x
+ *             \ne 0$% then the operation fails.  If you wanted a specific
+ *             square root then you'll have to pick it yourself.
+ */
+
+static const piece sqrtm1_pieces[NPIECE] = {
+  -32595792,  -7943725,   9377950,   3500415,  12389472,
+    -272473, -25146209,  -2005654,    326686,  11406482
+};
+#define SQRTM1 ((const f25519 *)sqrtm1_pieces)
+
+int f25519_quosqrt(f25519 *z, const f25519 *x, const f25519 *y)
+{
+  f25519 t, u, w, beta, xy3, t2p50m1;
+  octet xb[32], b0[32], b1[32];
+  int32 rc = -1;
+  mask32 m;
+  unsigned i;
+
+#define SQRN(z, x, n) do {                                             \
+  f25519_sqr((z), (x));                                                        \
+  for (i = 1; i < (n); i++) f25519_sqr((z), (z));                      \
+} while (0)
+
+  /* This is a bit tricky; the algorithm is from Bernstein, Duif, Lange,
+   * Schwabe, and Yang, `High-speed high-security signatures', 2011-09-26,
+   * https://ed25519.cr.yp.to/ed25519-20110926.pdf.
+   *
+   * First of all, a complicated exponentation.  The addition chain here is
+   * mine.  We start with some preliminary values.
+   */                                  /* step | value */
+  SQRN(&u, y, 1);                      /*    1 | 0, 2 */
+  f25519_mul(&t, &u, y);               /*    2 | 0, 3 */
+  f25519_mul(&xy3, &t, x);             /*    3 | 1, 3 */
+  SQRN(&u, &u, 1);                     /*    4 | 0, 4 */
+  f25519_mul(&w, &u, &xy3);            /*    5 | 1, 7 */
+
+  /* And now we calculate w^((p - 5)/8) = w^(252 - 3). */
+  SQRN(&u, &w, 1);                     /*    6 | 2 */
+  f25519_mul(&t, &w, &u);              /*    7 | 3 */
+  SQRN(&u, &t, 1);                     /*    8 | 6 */
+  f25519_mul(&t, &u, &w);              /*    9 | 7 */
+  SQRN(&u, &t, 3);                     /*   12 | 56 */
+  f25519_mul(&t, &t, &u);              /*   13 | 63 = 2^6 - 1 */
+  SQRN(&u, &t, 6);                     /*   19 | 2^12 - 2^6 */
+  f25519_mul(&t, &t, &u);              /*   20 | 2^12 - 1 */
+  SQRN(&u, &t, 12);                    /*   32 | 2^24 - 2^12 */
+  f25519_mul(&t, &t, &u);              /*   33 | 2^24 - 1 */
+  SQRN(&u, &t, 1);                     /*   34 | 2^25 - 2 */
+  f25519_mul(&t, &u, &w);              /*   35 | 2^25 - 1 */
+  SQRN(&u, &t, 25);                    /*   60 | 2^50 - 2^25 */
+  f25519_mul(&t2p50m1, &t, &u);                /*   61 | 2^50 - 1 */
+  SQRN(&u, &t2p50m1, 50);              /*  111 | 2^100 - 2^50 */
+  f25519_mul(&t, &t2p50m1, &u);                /*  112 | 2^100 - 1 */
+  SQRN(&u, &t, 100);                   /*  212 | 2^200 - 2^100 */
+  f25519_mul(&t, &t, &u);              /*  213 | 2^200 - 1 */
+  SQRN(&u, &t, 50);                    /*  263 | 2^250 - 2^50 */
+  f25519_mul(&t, &t2p50m1, &u);                /*  264 | 2^250 - 1 */
+  SQRN(&u, &t, 2);                     /*  266 | 2^252 - 4 */
+  f25519_mul(&t, &u, &w);              /*  267 | 2^252 - 3 */
+
+  /* And finally... */
+  f25519_mul(&beta, &t, &xy3);         /*  268 | ... */
+
+  /* Now we have beta = (x y^3) (x y^7)^((p - 5)/8) = (x/y)^((p + 3)/8), and
+   * we're ready to finish the computation.  Suppose that alpha^2 = u/w.
+   * Then beta^4 = (x/y)^((p + 3)/2) = alpha^(p + 3) = alpha^4 = (x/y)^2, so
+   * we have beta^2 = Â±x/y.  If y beta^2 = x then beta is the one we wanted;
+   * if -y beta^2 = x, then we want beta sqrt(-1), which we already know.  Of
+   * course, it might not match either, in which case we fail.
+   *
+   * The easiest way to compare is to encode.  This isn't as wasteful as it
+   * sounds: the hard part is normalizing the representations, which we have
+   * to do anyway.
+   */
+  f25519_sqr(&t, &beta);
+  f25519_mul(&t, &t, y);
+  f25519_neg(&u, &t);
+  f25519_store(xb, x);
+  f25519_store(b0, &t);
+  f25519_store(b1, &u);
+  f25519_mul(&u, &beta, SQRTM1);
+
+  m = -consttime_memeq(b0, xb, 32);
+  rc = PICK2(0, rc, m);
+  f25519_pick2(z, &beta, &u, m);
+  m = -consttime_memeq(b1, xb, 32);
+  rc = PICK2(0, rc, m);
+
+  /* And we're done. */
+  return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/f25519.h b/f25519.h
new file mode 100644 (file)
index 0000000..d097c0d
--- /dev/null
+++ b/f25519.h
@@ -0,0 +1,295 @@
+/* -*-c-*-
+ *
+ * Arithmetic modulo 2^255 - 19
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of secnet.
+ * See README for full list of copyright holders.
+ *
+ * secnet is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version d of the License, or
+ * (at your option) any later version.
+ *
+ * secnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with secnet; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ *
+ * This file was originally part of Catacomb, but has been automatically
+ * modified for incorporation into secnet: see `import-catacomb-crypto'
+ * for details.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef CATACOMB_F25519_H
+#define CATACOMB_F25519_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "fake-mLib-bits.h"
+
+#ifndef CATACOMB_QFARITH_H
+#  include "qfarith.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef union {
+  int32 p26[10];
+} f25519;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @f25519_set@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to write the result
+ *             @int a@ = a small-ish constant
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets @z@ to equal @a@.
+ */
+
+extern void f25519_set(f25519 */*x*/, int /*a*/);
+
+/* --- @f25519_load@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to store the result
+ *             @const octet xv[32]@ = source to read
+ *
+ * Returns:    ---
+ *
+ * Use:                Reads an element of %$\gf{2^{255} - 19}$% in external
+ *             representation from @xv@ and stores it in @z@.
+ *
+ *             External representation is little-endian base-256.  Elements
+ *             have multiple encodings, which are not produced by correct
+ *             software; use of noncanonical encodings is not an error, and
+ *             toleration of them is considered a performance feature.
+ *
+ *             Some specifications, e.g., RFC7748, require the topmost bit
+ *             (i.e., bit 7 of @wv[31]@) to be ignored.  Callers
+ *             implementing such specifications should clear the bit
+ *             explicitly.  (It's much easier for a caller who wants the bit
+ *             to be ignored to clear it than for a caller who wants the bit
+ *             to be significant to apply the necessary change by hand.)
+ */
+
+extern void f25519_load(f25519 */*z*/, const octet /*xv*/[32]);
+
+/* --- @f25519_store@ --- *
+ *
+ * Arguments:  @octet zv[32]@ = where to write the result
+ *             @const f25519 *x@ = the field element to write
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a field element in the given octet vector in external
+ *             representation.  A canonical encoding is always stored, so,
+ *             in particular, the top bit of @xv[31]@ is always left clear.
+ */
+
+extern void f25519_store(octet /*zv*/[32], const f25519 */*x*/);
+
+/* --- @f25519_pick2@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x, *y@ = two operands
+ *             @uint32 m@ = a mask
+ *
+ * Returns:    ---
+ *
+ * Use:                If @m@ is zero, set @z = y@; if @m@ is all-bits-set, then set
+ *             @z = x@.  If @m@ has some other value, then scramble @z@ in
+ *             an unhelpful way.
+ */
+
+extern void f25519_pick2(f25519 */*z*/, const f25519 */*x*/,
+                        const f25519 */*y*/, uint32 /*m*/);
+
+/* --- @f25519_pickn@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result
+ *             @const f25519 *v@ = a table of entries
+ *             @size_t n@ = the number of entries in @v@
+ *             @size_t i@ = an index
+ *
+ * Returns:    ---
+ *
+ * Use:                If @0 <= i < n < 32@ then set @z = v[i]@.  If @n >= 32@ then
+ *             do something unhelpful; otherwise, if @i >= n@ then set @z@
+ *             to zero.
+ */
+
+extern void f25519_pickn(f25519 */*z*/, const f25519 */*v*/, size_t /*n*/,
+                        size_t /*i*/);
+
+/* --- @f25519_condswap@ --- *
+ *
+ * Arguments:  @f25519 *x, *y@ = two operands
+ *             @uint32 m@ = a mask
+ *
+ * Returns:    ---
+ *
+ * Use:                If @m@ is zero, do nothing; if @m@ is all-bits-set, then
+ *             exchange @x@ and @y@.  If @m@ has some other value, then
+ *             scramble @x@ and @y@ in an unhelpful way.
+ */
+
+extern void f25519_condswap(f25519 */*x*/, f25519 */*y*/, uint32 /*m*/);
+
+/* --- @f25519_add@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the sum %$x + y$%.
+ */
+
+extern void f25519_add(f25519 */*z*/,
+                      const f25519 */*x*/, const f25519 */*y*/);
+
+/* --- @f25519_sub@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the difference %$x - y$%.
+ */
+
+extern void f25519_sub(f25519 */*z*/,
+                      const f25519 */*x*/, const f25519 */*y*/);
+
+/* --- @f25519_neg@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
+ *             @const f25519 *x@ = an operand
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z = -x@.
+ */
+
+extern void f25519_neg(f25519 */*z*/, const f25519 */*x*/);
+
+/* --- @f25519_condneg@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
+ *             @const f25519 *x@ = an operand
+ *             @uint32 m@ = a mask
+ *
+ * Returns:    ---
+ *
+ * Use:                If @m@ is zero, set @z = x@; if @m@ is all-bits-set, then set
+ *             @z = -x@.  If @m@ has some other value then scramble @z@ in
+ *             an unhelpful way.
+ */
+
+extern void f25519_condneg(f25519 */*z*/, const f25519 */*x*/, uint32 /*m*/);
+
+/* --- @f25519_mulconst@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
+ *             @const f25519 *x@ = an operand
+ *             @long a@ = a small-ish constant; %$|a| < 2^{20}$%.
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the product %$a x$%.
+ */
+
+extern void f25519_mulconst(f25519 */*z*/, const f25519 */*x*/, long /*a*/);
+
+/* --- @f25519_mul@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the product %$x y$%.
+ */
+
+extern void f25519_mul(f25519 */*z*/,
+                      const f25519 */*x*/, const f25519 */*y*/);
+
+/* --- @f25519_sqr@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x@ = an operand
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the square %$x^2$%.
+ */
+
+extern void f25519_sqr(f25519 */*z*/, const f25519 */*x*/);
+
+/* --- @f25519_inv@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@)
+ *             @const f25519 *x@ = an operand
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores in @z@ the multiplicative inverse %$x^{-1}$%.  If
+ *             %$x = 0$% then @z@ is set to zero.  This is considered a
+ *             feature.
+ */
+
+extern void f25519_inv(f25519 */*z*/, const f25519 */*x*/);
+
+/* --- @f25519_quosqrt@ --- *
+ *
+ * Arguments:  @f25519 *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const f25519 *x, *y@ = two operands
+ *
+ * Returns:    Zero if successful, @-1@ if %$x/y$% is not a square.
+ *
+ * Use:                Stores in @z@ the one of the square roots %$\pm\sqrt{x/y}$%.
+ *             If %$x = y = 0% then the result is zero; if %$y = 0$% but %$x
+ *             \ne 0$% then the operation fails.  If you wanted a specific
+ *             square root then you'll have to pick it yourself.
+ */
+
+extern int f25519_quosqrt(f25519 */*z*/,
+                         const f25519 */*x*/, const f25519 */*y*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/fgoldi-tests.in b/fgoldi-tests.in
new file mode 100644 (file)
index 0000000..c574fc6
--- /dev/null
@@ -0,0 +1,782 @@
+### Test cases for arithmetic mod 2^448 - 2^224 - 1.           -*-conf-*-
+### Extracted from Catacomb.
+
+###--------------------------------------------------------------------------
+test add
+
+## Some easy ones.
+x ffffffffffffff01000030000000ffffff2f00000002000030000000ffffff5f000000fbfffffffffffffcffff4f000000ffffffefffffff
+y 00
+z ffffffffffffff01000030000000ffffff2f00000002000030000000ffffff5f000000fbfffffffffffffcffff4f000000ffffffefffffff
+
+x fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
+y 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+z fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
+
+x fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff
+y 01
+z 00
+
+## Random tests.
+x 6b3944398448a0a5f6c4e1be9abfcbb082b8f68f1c831d51ef2244f6e1a4c4baaf0ada769c1261b8e14b4856de381d69961078ea1949d39c
+y 62e933c5f93e57e042d66b89d3c72ee85441b1207732d888b3d6bc35f3bcef91a6f4564cb085fd3239191c2fe427dcdb0e81164d30ca8145
+z cd2278fe7d87f785399b4d486e87fa98d7f9a7b093b5f5d9a2f9002cd561b44c56ff30c34c985eeb1a656485c260f944a5918e374a1355e2
+
+x 34938a406030a285024e9ff0a45987b53accc9d5d59828de8b8e07ba693b64d1dd2c7a190e708253a9ae57572e44fa458c8f8ac87cd96037
+y 9d05863131328886c7203fe70924761e56244d40a04d4b5592f1c6a457b9d94fe950fb8a865f9091ba9223479f3e46680fb78ccddc776bf2
+z d298107291622a0cca6eded7ae7dfdd390f0161676e673331e80ce5ec2f43d21c77d75a494cf12e563417b9ecd8240ae9b4617965951cc29
+
+x 4e9cb6823482233daf59662d00212f2afe42183f8ce949b2e0ca5473e32ab647fe9bc1c472b2288715c0d5b118043fbc9aec782654363cdd
+y 6c62329ec8eb576b6866cb6af702b891dd2cd72d21c354ada34221141381acca066fb46a8fbce28df44f0ac8062e38847067b8639be867f8
+z bbfee820fd6d7ba817c03198f723e7bbdb6fef6cadac9e5f840d7687f7ab6212050b762f026f0b150a10e0791f3277400b54318aef1ea4d5
+
+x b46d33f24a69c2288bed34eb054d1fcd6244606cffca7d53ff4e68f113174655a9a72898ad2699fe49d069a0a84e077bf48205008dee04aa
+y 9abc68911a75a6a376837cc6fc0e18c63cfb81747a59ba1314412f032f8b2a2fc5dde29176d141e71dbc11aeb2ecb9a336c8467882a175ea
+z 4f2a9c8365de68cc0171b1b1025c37939f3fe2e079243867139097f443a270846e850b2a24f8dae5678c7b4e5b3bc11e2b4b4c780f907a94
+
+x 1195eae69f2bad43b7b8330395e41c811bae2f753f0a6727b9decd2e553dce743dbb568b45140c3a464c8646db12b3af18df328a95640706
+y 8fc020ba693b4014fbf4e9c64223a8c3234e1361b8e2a745e3897f582537e20417831c159c107451fec49b88c4cde774330d8986430b39e0
+z a0550ba10967ed57b2ad1dcad707c5443ffc42d6f7ec0e6d9c684d877a74b079543e73a0e124808b441122cf9fe09a244cecbb10d96f40e6
+
+x 4b25a323cba12b5d042369a065a3696c7613898205f7defd3ab15ec351ec9fe1ba453c8b9abf254ff793c92b1f77d5f23f7629c04ec5c70d
+y b12ee8f930b029e2e4b79b808566b88b8087a510e5f80751ffc8f5426709bc2b40608e3e769dbd97d37dfe8a36fd25fbc1efb2cd9eda09f2
+z fc538b1dfc51553fe9da0421eb0922f8f69a2e93eaefe64e3a7a5406b9f55b0dfba5cac9105de3e6ca11c8b65574fbed0166dc8ded9fd1ff
+
+x c441e6cebc634bd7de7de356e855528d52f4affae7cdd585352d94218ca171929b17b8f49ea294f5151a277c116519de5ff92ce4e2f6ce0a
+y 809617d4e40d53223f01887bfab5a7d2dc1eb4f680ae59981b33e11fe71345b3155f567cc867cd9e48c8b534870c7df49dff883c0900d8cd
+z 44d8fda2a1719ef91d7f6bd2e20bfa5f2f1364f1687c2f1e5160754173b5b645b1760e71670a62945ee2dcb0987196d2fdf8b520ecf6a6d8
+
+x a92361d9c458605877a6d9229128b1a52f7bab378d0d389568aae10d09d419b0e6436684b438abcaa3e1710efee5ecec1af06cf0c82b339d
+y 74bc6cd43025234b1a6e15fe2d4fab520c874af6f896b82ecb096b0ec3cf73ecf04ef1d13ca612ef0981b8aca0a769ae60202eca36410b0e
+z 1de0cdadf57d83a39114ef20bf775cf83b02f62d86a4f0c333b44c1ccca38d9cd7925756f1debdb9ad622abb9e8d569b7b109bbaff6c3eab
+
+x f0ed25db758767b83b1d5ab6f8bdbe8e263b18341ea296b2a5d27c0d928004d6c48695ac88af863ed12be6629d8a1b58ca83ddb4ff9c778b
+y 44998d5a87e29ace239af04334451efca0d8bb88b441140caab3e79da9c73f1354df0c4e2a8148141bb44c33eb63f1c0025ec2b289390e06
+z 3487b335fd6902875fb74afa2c03dd8ac713d4bcd2e3aabe4f8664ab3b4844e91866a2fab230cf52ecdf329688ee0c19cde19f6789d68591
+
+x 64429139cb6dd44a64984ac73cdf306354a32772da0724c647164d89218906de465c0c47f2841564fc69933d140088a02584bbeb7a138e7a
+y 391d7bf04dd8082b6b196651c251737ba319720b66075f2e65a06023e1dc9697ee4c540b6fae20bdc333c9a95e69266b5ebeccf0b2aea18d
+z 9e5f0c2a1946dd75cfb1b018ff30a4def7bc997d400f83f4acb6adac03669d7535a9605261333621c09d5ce77269ae0b844288dc2dc22f08
+
+x 0bb7ca441d108e3d7a4c43025798eb1f1036e2d2200e2457aa93a631c068bf9e99805e8c69344d6f5fc063865f2e94bb954c20645f8b7003
+y 3f47bc6701604867acc3cf534d62c9847617954d860c34ac2bcacbfb1c24c99a7442a6170ea6539df0c98afaf6fc8f45dcaa77afebcc8290
+z 4afe86ac1e70d6a426101356a4fab4a4864d7720a71a5803d65d722ddd8c88390ec304a477daa00c508aee80562b240172f797134b58f393
+
+x 93205ac6e814337d0d12f8e55f0b62a32ba948cbc6df03293d51e67a7aa7e1457d201991f3392f1cc4a4a9b6b2ed27407ac4e24a5b0e2664
+y c2d648607a99e6dccb9f9940ffed57de39928d9c3fcbabd79876ecf1a5476ff5a637d0052f04d82a2794bf0e31268fd6ff640b4aa1ac921f
+z 55f7a22663ae195ad9b191265ff9b981653bd66706abaf00d6c7d26c20ef503b2458e996223e0747eb3869c5e313b7167a29ee94fcbab883
+
+x 42bb562d81bac7f606d2157697f29f1799b3e5172f003f44785b80006fb56681b832ff6e7875d6a146b09a9a95f9f3cfb210f5b9aa545e0c
+y e7cc109d2ea008a1c938c66e296911c0d7503b1a961f23edce9532c718e53518729dcc6f7e921f831c56d1d8ee7c5b4919f4030ce6703e68
+z 298867caaf5ad097d00adce4c05bb1d770042132c51f623147f1b2c7879a9c992ad0cbdef607f62463066c7384764f19cc04f9c590c59c74
+
+x 4cfc133cf2b3e22f569340c3a59299087f9caf8b36562d418f2e18494769278c16a22641e4de8f675e9540d6fc0f8c210a64dd63c8d01453
+y f33b0a3beaad1fb12ba48d69ef999bb7a5af3bd2b977aaf518bc65a13caaa9d61cacbb7c5ce6173a282d341cf83c86a458c8d2d10a1c1ac2
+z 40381e77dc6102e18137ce2c952c35c0244ceb5df0cdd736a8ea7dea8413d162334ee2bd40c5a7a186c274f2f44c12c6622cb035d3ec2e15
+
+x fc64ef657d34477c17b0674b697cc5a4bc8e665ba1dee02e5afd0d2f57e0a64abb2bc428215d9e8ece95c5283e4233d483201c286e4997cb
+y ed4af51625762548e95f32e7042f07bb260f734fb9ba43301daddff9a863990d79791d5db1bbbdbad75c09ce313d93638c219c989702c5ed
+z eaafe47ca2aa6cc400109a326eabcc5fe39dd9aa5a99245f77aaed280144405834a5e185d2185c49a6f2cef66f7fc6371042b8c0054c5cb9
+
+x 2fa4cdcae0b01f3f3aa28d4ff311054c73683c09749eb312cd4ff7cf018fa647a66b44477459cab757b9149623ecf9064dba16d5601eafb7
+y b378045a6652eea3cc9a8530dea6361daa86866f038e579670f2d50e072417342f1887827335a0a041d1411b24a68d8f190edd8a251ac3c7
+z e31cd22447030ee3063d1380d1b83b691defc278772c0ba93d42cdde09b3bd7bd583cbc9e78e6a58998a56b14792879666c8f35f8638727f
+
+x 5107c636bcd6bc59ec9c7fcf04efbf90fdde936bff7e221be660d542f74fcccb8b49220b93744203bdb7b026f1bb9fd9a64c0187fd3d99a7
+y ee48bc6d5c231bd7be253ed69171d2525157d0d8fe12fdafa6e7a3285f0d966fd4c570928f61850138489fca5cb540444c24b602d9025899
+z 405082a418fad730abc2bda5966092e34e366444fe911fcb8c48796b575d623b600f939d22d6c704f5ff4ff14d71e01df370b789d640f140
+
+x 475e593758fa8506baa94e1b6070aeaff278d905af67f9e5a5273ae0737825d220c02ae7a89f39998f98895c83e51e7bd0cc0c9126273792
+y 3f724d7bbb27bf8b2f4e328bd865e412ed6207802703def28b9b64567b15f7648c1f96ca5092400e32427f9880c95fa0a83f7fbdd6b2d2b7
+z 87d0a6b213224592e9f780a638d692c2dfdbe085d66ad7d831c39e36f08d1c37addfc0b1f9317aa7c1da08f503af7e1b790c8c4efdd9094a
+
+x fb7923d1a8666b372b41792749ae312903e1b1a8198970a5da6d85dc19a4326bcde206ee841a2bf106c95e99b42fa7eb3fa559b4b88d31c2
+y 45e467dafaee144bbd614028c0ea4d3a37b4ef99ded5c9e44b7526916218202401233364bffadac9424143bac99b4c2d89ceea71c3fd0ea4
+z 415e8baba3558082e8a2b94f09997f633a95a142f85e3a8a26e3ab6d7dbc528fce053a52441506bb490aa2537ecbf318c97344267c8b4066
+
+x 2212850af1b191227fc4875e981ee15968832cb6898243af481b62d91ae5cb26fdcd72e45a54cbbbd9efc5e1739f8683d8ab318586b51e7c
+y 6b7b3294bfd31a11644924c988b0b19cfc1db66d8e674040ee21537b54aed4e1e217f0b3427d7d4d9dc7d9dcbcda8c2c47c5348b9eaa7ddb
+z 8e8db79eb085ac33e30dac2721cf92f664a1e22318ea83ef363db5547093a008e0e562989dd1480977b79fbe307a13b01f71661025609c57
+
+###--------------------------------------------------------------------------
+test sub
+
+x 890e734c6f4af5b1c62cf6fdd0facf76af535bdc9781396c59a6cd8c37cc96aac97fa61bef07c60c69dfb633049014868473d28481385ba1
+y 0a06a622804bfe9041259a435be8c40aa56d1be10dd3c4261157c16c0d0d99d11b0f5dce0b164a2e6d4c53813242954830a39f2c894fb315
+z 7f08cd29effef62085075cba75120b6c0ae63ffb89ae7445484f0c202abffdd8ad70494de3f17bdefb9263b2d14d7f3d54d03258f8e8a78b
+
+x 17935b9768cf9ecdc3b3a4c3c87ee20f766bca820f620c1852a48d680f445f1a28ee6a9a18fbdcdb9f35846bc6f0bbb1687b227bcadd4c3a
+y 9f913b62023a48e577ac9aaa6d06bb5cf46ea3acc2946a80f66fba02859837491a31b6740a5ed1178c8b6faf4198ac836419deb8aa439c0d
+z 78012035669556e84b070a195b7827b381fc26d64ccda1975b34d3658aab27d10dbdb4250e9d0bc413aa14bc84580f2e046244c21f9ab02c
+
+x b1689e72355c7305d5cab07e2d672e7b92872c115f03f9b45fe7c9d3354ea0d3702f4f915900085ec44e816dcd731086c999c0e97ce52b40
+y a85e9b5cbe9f628049f91b9adcc1db63f19e8f7c37b92e43015d0f76f188c1cfe89c86910afb82c2c6f1f7197562b919380a1b32b2439006
+z 090a031677bc10858bd194e450a55217a1e89c94274aca715e8aba5d44c5de038892c8ff4e05859bfd5c89535811576c918fa5b7caa19b39
+
+x 8f952f2233cdba45ccaafcb8e6d17b38529a44ff49e8ac8dc6378710d5e5af052c460e2758e3ee28f5866e71737c9b6e7731c03d11d21cd6
+y 5bc41fd436b58032dd4f50cd0c57bda1127a3033c2183d8133cb9c40760ea41bb42f48f36b6a2f3bcd0dbc60b5bef5e4b712308ca0f2b443
+z 34d10f4efc173a13ef5aacebd97abe963f2014cc87cf6f0c936ceacf5ed70bea7716c633ec78bfed2779b210bebda589bf1e90b170df6792
+
+x 708939d3a13fe996dd90b1128231b7da3593c12d9ab880a4da9febe7f12bfefe72aab1608145911fdfa1e3f1f59b426a06dee253d4d3eeb6
+y 008929e61e53becf9bc6dcbf6414f3a71e9f134fcab293cd42e096fef3d87a472a79ed1ce623708aee31e12f5bef9bc6d0aa470ce2a52f80
+z 700010ed82ec2ac741cad4521d1dc43217f4addecf05edd697bf54e9fd5283b74831c4439b212195f06f02c29aaca6a335339b47f22dbf36
+
+x a7996b0ae1d8ad5856ae5cf3abc8fc61c4b3579d951b632b9af67dce957365759fb5a6f54965a86b1dcccc9439eebdeb04f616c3fb4db382
+y 2df8e6cf52e985d0e20f4f5e9bbaf1b8bd7d7b982da05568b7ea82fd2a5c0302d0ce9feec5e135eca886fd30827905eae204a51e498a173d
+z 7aa1843a8eef2788739e0d95100e0ba90636dc04687b0dc3e20bfbd06a176273cfe606078483727f7445cf63b774b80122f171a4b2c39b45
+
+x 74179531aaf2ee4e7a309350982fc9ce501ad18c650f0adacce5da9b520ce27c04ca69dca0e719713d4d10db532401bee26b7ff9819bf532
+y 6a3554898f2951ed005bc4ac74dfd0ef124cffbb52301109d8414719473dc17a602a3b530195c383efa22dd6da87414395886e4b9dd5b5f3
+z 09e240a81ac99d6179d5cea32350f8de3dced1d012dff8d0f4a393820acf2002a49f2e899f5256ed4daae204799cbf7a4de310aee4c53f3f
+
+x e7c145e38ca66fd86991538ab11231abb60af8b0ab7460e047f7b5b69bbe4a3a56c28c14131c35621f4014d541ffabd642c774bc1a5c66c7
+y 9ca047c2251cc6012bd734198e4b2c6ca0d50a85db601659b8380510fc6c1d08a27fa5fb8eb3c9e5622185f83fba6ed128d153cc9563e1d6
+z 4a21fe20678aa9d63eba1e7123c7043f1635ed2bd0134a878fbeb0a69e512d32b442e71884686b7cbc1e8fdc01453d051af620f084f884f0
+
+x 8f01ab3bbedf7ac443423793a422910a54dd73f121ce6f52270d7953386bf2b0eb228b2560b7103aa94f3190e80038505f2b21a9f138c414
+y 44a6b845b4b3b6d9c55478664fa2134df50e7ff4c5184aa57bcc8d01da42cdbb78da3898fd92287b604b6a369c06d695241c48605b57808f
+z 4a5bf2f5092cc4ea7dedbe2c55807dbd5ecef4fc5bb525adab40eb515d2825f57248528d6224e8be4804c7594cfa61ba3a0fd94896e14385
+
+x 1b6f84c1ad9ec3d008f345a19305aa35e5b55efeb535024b0fc9aee4be1c031bb070655fc5e672ea75b5db98cff0dcfb5427e21e5ffc4fa9
+y ad5d4e308c69186e87ac97551e9ec34f2d1746d5f6712b126c3415346ac2271450aca96fc6b9e82ef7e2f3fad60df4f184e34dff8fb53b02
+z 6e1136912135ab628146ae4b7567e6e5b79e1829bfc3d638a39499b0545adb0660c4bbeffe2c8abb7ed2e79df8e2e809d043941fcf4614a7
+
+x 25ce194230be078d7f35b85d68706d768fec7994654fcd3f63f3d32eaf59f17bc87a617d41f76b7d0c78b63377a203e43194f0b056d26b0b
+y 76266bea72a15cdc355867a490e775c909b7b6cfc833107e7c6b7dbaed2c8491c6d000b2d7d2beb72d72937285aa1bceff18aa35d0c52158
+z aea7ae57bd1cabb049dd50b9d788f7ac8535c3c49c1bbdc1e6875674c02c6dea01aa60cb6924adc5de0523c1f1f7e715327b467b860c4ab3
+
+x c010bfa3d130f868f2b975318139c2a847c69014b76164192b437fd7e26b892a5a2425670fe3e8fd9efdfa250f57579d1af2d24f8eb6ce92
+y bfe65616e278b6ce46b295600131bf5ea092451a87f6bc3adf1c86f2fe717351b073062ced1394a14051bb33f3874cca569aae8ba97605f9
+z 002a688defb7419aab07e0d07f08034aa7334bfa2f6ba7de4b26f9e4e2f915d9a9b01e3b22cf545c5eac3ff21bcf0ad3c35724c4e43fc999
+
+x b2f21992b1f2155b7afc3a1d731b52c03cf14208e634b7da123888d652afcd919e9f5f0bea8b9986c71a7ba08fefe58ee0402d9a23b95f2c
+y ae241fa6292c63f3c09301255a866825b39c9645512ea123486f9a873cacab567cd169c463fb1cf0417633a7055d831d23fd1d58dd42e726
+z 04cefaeb87c6b267b96839f81895e99a8954acc2940616b7cac8ed4e1603223b22cef54686907c9685a447f989926271bd430f4246767805
+
+x b714b60b2614ab6ce63bf8eae621357f2e921f79de94982fcd5f524015db3faa52b15ff042733958fa202786f61bfed0b9fb5d5873619aec
+y 0c99e1da4c747ad1a625321cf9359b1d823544d1eacfddc38e4bfd729ed2f9fb37760242340f7986843fb8fa0435bcb5cffdf11453caebcf
+z ab7bd430d99f309b3f16c6ceedeb9961ac5cdba7f3c4ba6b3e1455cd760846ae1a3b5dae0e64c0d175e16e8bf1e6411beafd6b432097ae1c
+
+x c5425daf8f7089def2ff910e256d9496fc109d2698cf15dec1ce3f8116231969c5ed327626362b0658c60e74023a3cae5ef128fb5d27cad7
+y bc4e49fbf095f73894c4d623a210475cb7ba78ebbcbee8ab55a851162f789fb21e72de95afe4ddd45b90289f94f6d02b5f5a4b90c603ea31
+z 09f413b49eda91a55e3bbbea825c4d3a4556243bdb102d326c26ee6ae7aa79b6a67b54e076514d31fc35e6d46d436b82ff96dd6a9723e0a5
+
+x 9aa20b4259efd3a701a63347181fa63f56f42a97ef836bf3aab88d30bbf28a91bbf713a0170024e6057e2281ac113f9b58cb13d63e850ea7
+y 09e7104367d8c0441d811ecc619af04def9236752c2d47bc508b0de3c3b29c74533d8eb9fee13279aed8d58247e4010206c697d9b72bab43
+z 91bbfafef1161363e424157bb684b5f16661f421c35624375a2d804df73fee1c68ba85e6181ef16c57a54cfe642d3d9952057cfc86596363
+
+x e8ead9316aeb8f56d43418cd3bb1a71234c9e20b4a6dc1604ffdfdbcaacebe73b71d18c2c167544304d895d67e2daa2538a4ad0708cd9acf
+y ff3603f0960bb7a92f2b7fbfe242b467164e0ca72e89bcab6c467b5391166d05c601b38de40643f04d5b50ff8ec62b18c69e9df74f01babe
+z e9b3d641d3dfd8aca409990d596ef3aa1d7bd6641be404b5e2b6826919b8516ef11b6534dd601153b67c45d7ef667e0d72051010b8cbe010
+
+x f37b41d9950036d560f02b8befd6f5c73096b8995850b9fc563291fba59fd994916744fbd4c1dd5d17a9e5ecd4ec4a658dfdae1ba7024bc6
+y eeda58ba400f16a946381fb11f0ac0db895957236bcc629ce9d1ea425eef8412ea73af488b97f1afa950736f26c3cace887417b699cc3410
+z 05a1e81e55f11f2c1ab80cdacfcc35eca63c6176ed8356606d60a6b847b05482a7f394b2492aecad6d58727dae298096048997650d3616b6
+
+x 2bdb71a053047c4173718ce104e5b8671fbd61c59bfe8b20b890ceda15a69d24eec3775f4ce8a9c16d36e50626bc334e0fc1be492d800c06
+y b1ccd0dac33ac46b2709f9626ed70136f98dfbc705ad93ea8f1b325d644daf2c0180cb83bfdbb7398d3f58c0f6600056a174850b9db91ed4
+z 790ea1c58fc9b7d54b68937e960db731262f66fd9551f83528759c7db058eef7ec43acdb8c0cf287e0f68c462f5b33f86d4c393e90c6ed31
+
+x 8f3fd6346c7f2dacf0d7cdb88a5bca3b222a895a07b169d0bcd0af0a9aa634876ae1a939262dd75bd12b5a97127155a015e00acac7d5cbc8
+y 0e9c03c5a06accdddd0d8613e41a00f2b586e297e366987e02e7536e0ca1b4c2c75fed619655acddffe8585c7a828432d90575731a4c8519
+z 81a3d26fcb1461ce12ca47a5a640ca496ca3a6c2234ad151bae95b9c8d0580c4a281bcd78fd72a7ed142013b98eed06d3cda9556ad8946af
+
+###--------------------------------------------------------------------------
+test condswap
+
+x db0be3ccfda1e2f8492bffb5d3344f1856ff1896b6a067d2fa064423ac5b05b669db1c9b51899c44a7f470be4173856d9aa3d1cd10cb8c9b
+y 3005560f89232a97cebf6808e7493dd0f17e572556b53723b57faee51d8a0a45c7fb51aeb916f59c74ea6041494483b2fdce72189d1bd031
+m 0xffffffff
+xx 3005560f89232a97cebf6808e7493dd0f17e572556b53723b57faee51d8a0a45c7fb51aeb916f59c74ea6041494483b2fdce72189d1bd031
+yy db0be3ccfda1e2f8492bffb5d3344f1856ff1896b6a067d2fa064423ac5b05b669db1c9b51899c44a7f470be4173856d9aa3d1cd10cb8c9b
+
+x ea009751f6a7045ec7d6d46b16cbe663f5a78fca3835626c79864bec4030443bb9349654d52b2edab92b8f4aa876a97e868aa6267a54e6b1
+y 8c6f864ef7f664f4985ed8c1ea0c63bd7ab355b5321c2712791b610a2dadddc90a65ca8d5c25ff199b011193796b08f96420934615103b7b
+m 0x00000000
+xx ea009751f6a7045ec7d6d46b16cbe663f5a78fca3835626c79864bec4030443bb9349654d52b2edab92b8f4aa876a97e868aa6267a54e6b1
+yy 8c6f864ef7f664f4985ed8c1ea0c63bd7ab355b5321c2712791b610a2dadddc90a65ca8d5c25ff199b011193796b08f96420934615103b7b
+
+x dc3aa7d363058993cbdc54e95f3c972a2cea17cdf9370fccdfedfa1ba939ca35f762c5c6283f84348282fd56d83539804427eabe3bd6170d
+y 8c47a0990eccf7300986232dbc8ee26e8996c3bb4b73663ec5525312bea8975221c9f49039840c181d042654a8c1806bb86702ac7d0b80f4
+m 0x00000000
+xx dc3aa7d363058993cbdc54e95f3c972a2cea17cdf9370fccdfedfa1ba939ca35f762c5c6283f84348282fd56d83539804427eabe3bd6170d
+yy 8c47a0990eccf7300986232dbc8ee26e8996c3bb4b73663ec5525312bea8975221c9f49039840c181d042654a8c1806bb86702ac7d0b80f4
+
+x 69b45538513af2148e0a2903539bc5e20fca4da447278bf5967091d2e781121080c14a41989f9ee5218c444d3a42989ba890c7be7faae5d3
+y 935eadbde0c571c29deb4d8404dd39a8cca177ced36c359abfa7a6cafe6075422e1d79cba8d81cdbdfa4a5144faf37b19ca22b2b40fe1a0b
+m 0x00000000
+xx 69b45538513af2148e0a2903539bc5e20fca4da447278bf5967091d2e781121080c14a41989f9ee5218c444d3a42989ba890c7be7faae5d3
+yy 935eadbde0c571c29deb4d8404dd39a8cca177ced36c359abfa7a6cafe6075422e1d79cba8d81cdbdfa4a5144faf37b19ca22b2b40fe1a0b
+
+x de30072f175127ad4200a08099f4d0df0edfa40eb02e21a03c5628dcb2f70da8bce9ebbb1ebed2aca391e73a4114c06bcdbf762bf28777cf
+y 5eaf3aecf1f7d1fd3b43be8fa450163c79f162b0c6eaa4b1ad39baaf3a4c36564e001c935fdce38e90789151beff0f3cc4fdfc2d86dcb587
+m 0x00000000
+xx de30072f175127ad4200a08099f4d0df0edfa40eb02e21a03c5628dcb2f70da8bce9ebbb1ebed2aca391e73a4114c06bcdbf762bf28777cf
+yy 5eaf3aecf1f7d1fd3b43be8fa450163c79f162b0c6eaa4b1ad39baaf3a4c36564e001c935fdce38e90789151beff0f3cc4fdfc2d86dcb587
+
+x 1bb20a5a05b190737ad6b2bc5bc2b9259fa7e36eac8f3032a7c56ed59c1510baaea32bba898b329b0c64fadbe454095b9f82b366bfae3d8b
+y cf0a87c8befed020caf82f37b4c5f17d2aa9ff8ab75baa156cfe2716ac1eaabf9bc760c2ddcd66a9d02a8384ad1db9e8f857b151d126e0ef
+m 0x00000000
+xx 1bb20a5a05b190737ad6b2bc5bc2b9259fa7e36eac8f3032a7c56ed59c1510baaea32bba898b329b0c64fadbe454095b9f82b366bfae3d8b
+yy cf0a87c8befed020caf82f37b4c5f17d2aa9ff8ab75baa156cfe2716ac1eaabf9bc760c2ddcd66a9d02a8384ad1db9e8f857b151d126e0ef
+
+x c186531a219344dc485cd5dad6500616ac8e0653693168573cb9be590b02dfb1ddc5d87d27f2d9fa46ffeda955a6285b7ef2b9bf84825d06
+y 91f3be7eb2e0be38d92974d81be5126ef40d358f242d23aa4863fb16ba3e8844e02edc87c0206e211587886ed532da0ab148cfcf64e9b58d
+m 0x00000000
+xx c186531a219344dc485cd5dad6500616ac8e0653693168573cb9be590b02dfb1ddc5d87d27f2d9fa46ffeda955a6285b7ef2b9bf84825d06
+yy 91f3be7eb2e0be38d92974d81be5126ef40d358f242d23aa4863fb16ba3e8844e02edc87c0206e211587886ed532da0ab148cfcf64e9b58d
+
+x 9f2476d6db424d19ee0cba4ed091da5b44ca63caf2f711eaeb7edcc75f49e0d0c367c1f2817b6bb39460f897432901064cabed7f6a03b1f0
+y 66e7dcd34d76a19e3285685112b7619f9a3557764a918922faf1370bb97c2b2fa845dd34662cfe7299ab702c68fd43b5f6f15a0af6625f2e
+m 0xffffffff
+xx 66e7dcd34d76a19e3285685112b7619f9a3557764a918922faf1370bb97c2b2fa845dd34662cfe7299ab702c68fd43b5f6f15a0af6625f2e
+yy 9f2476d6db424d19ee0cba4ed091da5b44ca63caf2f711eaeb7edcc75f49e0d0c367c1f2817b6bb39460f897432901064cabed7f6a03b1f0
+
+x f124ac31d304a29cdd94bdc0611c61064a7c5f09cf6847bccd52fc7a7b77ede73b42b1ef75f000de4361028e0fb63896f4ef5ad3bc1b9c90
+y 6629084a230c793086e469b9a01e052ad7a5680d6955667e0dfb19a250f447d9e238695400dc4ecaeefcebed44d374e57ec4e414f5629e63
+m 0x00000000
+xx f124ac31d304a29cdd94bdc0611c61064a7c5f09cf6847bccd52fc7a7b77ede73b42b1ef75f000de4361028e0fb63896f4ef5ad3bc1b9c90
+yy 6629084a230c793086e469b9a01e052ad7a5680d6955667e0dfb19a250f447d9e238695400dc4ecaeefcebed44d374e57ec4e414f5629e63
+
+x b64f2952510827bef3d32ef6347251274c7241d9913268a7a6a5c360a4b29e7ed04d09a9ee5aa83235eaf8c0582b076b21d78b7062952773
+y 77897028a9a81fd54362a6085aa2c2fd6fdd44589f447c7310b9b3b5a29b54ed15c57e2c9fbff16f20129a4dbd43640a0d1037e277ca5c93
+m 0xffffffff
+xx 77897028a9a81fd54362a6085aa2c2fd6fdd44589f447c7310b9b3b5a29b54ed15c57e2c9fbff16f20129a4dbd43640a0d1037e277ca5c93
+yy b64f2952510827bef3d32ef6347251274c7241d9913268a7a6a5c360a4b29e7ed04d09a9ee5aa83235eaf8c0582b076b21d78b7062952773
+
+x 4d75efd204a66aed323456e6f55cb891ee7a31d739ae89726e0ea84532f9c740d1b647b117094fb85da2c62da04f3b9cb13db6b840046b7c
+y 0afd07bb073a150e7b82711e1f42f7b0789af8192ea6b4e1b24a3d48de7f8b802875aca5a02a9d24deca0b58c895992a449d01026495b96c
+m 0x00000000
+xx 4d75efd204a66aed323456e6f55cb891ee7a31d739ae89726e0ea84532f9c740d1b647b117094fb85da2c62da04f3b9cb13db6b840046b7c
+yy 0afd07bb073a150e7b82711e1f42f7b0789af8192ea6b4e1b24a3d48de7f8b802875aca5a02a9d24deca0b58c895992a449d01026495b96c
+
+x 1ff4eb5f0280744f0c909cede8be29cccb8ae43e4626018a9a1d352a97d987678863ba34bdeb183bb5e9347e96760665f5881570778a2e19
+y 49cd390a9edc7fad6c84c2e44ce09e490161094d2dc6cad30759fbef10aa30e5aa6474bc46571188418f3e4a2b19ecfc379a1f94e3a44e48
+m 0x00000000
+xx 1ff4eb5f0280744f0c909cede8be29cccb8ae43e4626018a9a1d352a97d987678863ba34bdeb183bb5e9347e96760665f5881570778a2e19
+yy 49cd390a9edc7fad6c84c2e44ce09e490161094d2dc6cad30759fbef10aa30e5aa6474bc46571188418f3e4a2b19ecfc379a1f94e3a44e48
+
+x e96c0316baf01c25ef8a41c02e99aa84c82f8eecd3249be268834afb5f7e95f0ad10bfad4160bb335c30ffd6a1090c91c57eb6ac7a7a5e66
+y 115e6f115bc4e19af60710f3dd821fb58cb680a32d6973eae9ea3e48f1928dc1d9f684a8c8de80affc59bc0fb342bb040f89d2d46b8ff8fc
+m 0x00000000
+xx e96c0316baf01c25ef8a41c02e99aa84c82f8eecd3249be268834afb5f7e95f0ad10bfad4160bb335c30ffd6a1090c91c57eb6ac7a7a5e66
+yy 115e6f115bc4e19af60710f3dd821fb58cb680a32d6973eae9ea3e48f1928dc1d9f684a8c8de80affc59bc0fb342bb040f89d2d46b8ff8fc
+
+x 71bd8f5036da4c33f6940348ea448c2f9bccb152dab40b410bd695923a9e255b33aaf361055be4bb9a570e201dce784cc1ccb0f89faca85f
+y 971b2f6569ddd9099a87ec4086d8218abcfbe81579f25f03634e471170a5088f48a6cfd09ed9e389ca37b780165c00b206304229135b6044
+m 0xffffffff
+xx 971b2f6569ddd9099a87ec4086d8218abcfbe81579f25f03634e471170a5088f48a6cfd09ed9e389ca37b780165c00b206304229135b6044
+yy 71bd8f5036da4c33f6940348ea448c2f9bccb152dab40b410bd695923a9e255b33aaf361055be4bb9a570e201dce784cc1ccb0f89faca85f
+
+x 0f1165e19968f3e6159e9f7f843c1b849e5c3917af4e2798869112c6efca9993ed339c8495eec8c54b286820bf7befdc8ae344e4d309c077
+y 7ce5a2ae66b9bddd30c98d9aa9fcdd6ef90d244d10115d15cf5d81e9e389f6852b153a42c642447043fcfd278166b92c624508973449b0e8
+m 0xffffffff
+xx 7ce5a2ae66b9bddd30c98d9aa9fcdd6ef90d244d10115d15cf5d81e9e389f6852b153a42c642447043fcfd278166b92c624508973449b0e8
+yy 0f1165e19968f3e6159e9f7f843c1b849e5c3917af4e2798869112c6efca9993ed339c8495eec8c54b286820bf7befdc8ae344e4d309c077
+
+x 6dd07b4891d8f45ad1ee64da38383ec50d6f29634767607eca19a547cadc3c157ebe7d86a28d4d2fa2d40f2c5402d8b338cfd8d30aeadb6a
+y 63da9a5a0cd51e58168ddb305c0e70a2f898279dae6394e1b3e1ef3a0763847d5d2f15be493114360204d037d7d3c3a9e746d27dcb544ded
+m 0xffffffff
+xx 63da9a5a0cd51e58168ddb305c0e70a2f898279dae6394e1b3e1ef3a0763847d5d2f15be493114360204d037d7d3c3a9e746d27dcb544ded
+yy 6dd07b4891d8f45ad1ee64da38383ec50d6f29634767607eca19a547cadc3c157ebe7d86a28d4d2fa2d40f2c5402d8b338cfd8d30aeadb6a
+
+x d91228b648f75350d775432af35be9aa283e9729fcd3b689f0c7ee02ea67efd33493980ae5eec92ad6ab42ccd253a7aab5a62c26be275278
+y 07c5d1b4f9b8db88cd4187b1ae5e175bf703af12b26d066c1d55dd367569d3e23e3d0470f3c47e6761746ce7de39cf563500d026a6791980
+m 0xffffffff
+xx 07c5d1b4f9b8db88cd4187b1ae5e175bf703af12b26d066c1d55dd367569d3e23e3d0470f3c47e6761746ce7de39cf563500d026a6791980
+yy d91228b648f75350d775432af35be9aa283e9729fcd3b689f0c7ee02ea67efd33493980ae5eec92ad6ab42ccd253a7aab5a62c26be275278
+
+x f9e764e20657319802b53ee29df43b0d83d994d9049b9820fc0c31b631265c49f6613923a042eadce5902fb81753784ff5a9c0de2c4f6b12
+y 6ab2f8279e82aa65e8326e5c60bfa067e4967b3ea67d0369853282e5429736529a43eeee3fdf24ebbe5ca85b59647994fc99c90da83c6229
+m 0xffffffff
+xx 6ab2f8279e82aa65e8326e5c60bfa067e4967b3ea67d0369853282e5429736529a43eeee3fdf24ebbe5ca85b59647994fc99c90da83c6229
+yy f9e764e20657319802b53ee29df43b0d83d994d9049b9820fc0c31b631265c49f6613923a042eadce5902fb81753784ff5a9c0de2c4f6b12
+
+x 772289865ac905fac203e4654b258890ddb91cac71c6d2af3826e3acfebfa222c937b40069ce3a757e2ffd960b5821ed1ad54e4ad2e3c6fd
+y 58dbf838ab81a754533c7f80fea48cbc981f724e4c150ddbb0afb5c711a8e21079446f77c427f7eb1892c096fa3eae5e2b070413611cd184
+m 0xffffffff
+xx 58dbf838ab81a754533c7f80fea48cbc981f724e4c150ddbb0afb5c711a8e21079446f77c427f7eb1892c096fa3eae5e2b070413611cd184
+yy 772289865ac905fac203e4654b258890ddb91cac71c6d2af3826e3acfebfa222c937b40069ce3a757e2ffd960b5821ed1ad54e4ad2e3c6fd
+
+x 0bd6656d68c41bfc5389db274367f69191754919435ba58d2256017b5bc595d102c6f4f745b3ceb0c32bd0a6cdadded3a3dc925ef2b5c73c
+y 1d903009c74d3d135a192bd42466cd28303f482626a7d10832f1f6eae72c3b051b0373e62300a71226011475034f0bfc6c9a65601bb83993
+m 0xffffffff
+xx 1d903009c74d3d135a192bd42466cd28303f482626a7d10832f1f6eae72c3b051b0373e62300a71226011475034f0bfc6c9a65601bb83993
+yy 0bd6656d68c41bfc5389db274367f69191754919435ba58d2256017b5bc595d102c6f4f745b3ceb0c32bd0a6cdadded3a3dc925ef2b5c73c
+
+###--------------------------------------------------------------------------
+test mulconst
+
+x cb908747a1af81f52715ef8440aed06aaacbcd7903c99cdecef5ec54e7845bedaad6475028b0cbdb0d53b6eeb71843f900fefd398a083d5a
+a -417895
+z e95e64fd1b2e2e79d1bfef5c96942eaf7ca5d40b1af774ed9c4ea2351c8ae81013f896bafd1f0b0e3a3c2ca3347c6cf88f988877af5e009b
+
+x 46b23d83c0848e79af947191cb76b087483beec6224af749e59c0c5ae27ff8abada31da895f8132aae0457f5ddc30d18a8d52046fbe6ef55
+a 384370
+z 31c9bf2f3bdfd3c1dc115db96d7a1c15e2a9ae67dfebccddc9408a0dcd147d9aa62ce4a55a2d6ad54542317756a08d6be3b959bf132624e2
+
+x 53e19751de62909506bebf74411d359014ec4b6afbb8ce14eeed8a3938013f0fee6897e3cc3adcbc90d7df321c4caa1941d0e5909551335d
+a -49682
+z 82fb902a8992ec1032a6837cec56189c45d1c1fdc47748e17dd9ecabc807a52eb537d6411f99f4d3b328e7ca76475924f90506a8adeb908e
+
+x 7ff3b9b3d8ee248a48d0c8d308d8c3658374acc92303143061a46656ae2b35094ed7b5b27d23366c0e42ee0a9471a4355d81cda0e4390348
+a 131908
+z adbb3dd21e634dfe2c41593c65249f03a048338037d4a107892df36f10e3ff68402d6f48e74bc7a7858f2c3650fd2a10acdfd4213850529e
+
+x f532f4f5ab5447b083ee4225246aaa4448696e4fc8bcf5b0ec1b52df88354e5327d7a3cf6e15db9945205968c275755ea3906a27437d29ed
+a 383911
+z 1f42b3585a2553ab19b14639c3e3aca636d88053c70fb758962713783bcd824b729fb4d01dd56a344d991bf2d32a2967acf470b39bee88a6
+
+x ef0e2a829097e50575eae6b1ad3fa10b8e417b0363654e0cb07a563a905c02e367c6f1ad7be1469b9f5295e3db0726853adffb820715f7d1
+a -226220
+z a7c5387af1b9f61f09d628feac1a050173021386775c9f534557b8841b812155325e3632eee7a2302ef8af0b4746575d6c2bcf3b29f674b0
+
+x 3b4655b1c22542ca413f76bc24751a01cdab6b385b50301d67fd62ba31ad132150e38e12a849405112c4742e93b92849bd8b872c29edb2f9
+a -89924
+z b51c0dfa2407a89435fedbcfd7835b6e0849d8626995fd00974f44c49d794d3c5dc16028e9fdee45bbcd269035e8bdba695a6653028d4d59
+
+x 48bdc2073bff25ae9bf7fcc368d65602a71e48c343bc7181c361331f108867d56c588f698aa5b91222f5dbbc859bce656f2607b053222fc7
+a 66432
+z e845dfe65d563884074ffeecaa325706df4a129b73b056cab6ad999588216d72525222ce00ce4d2ffb09fcf6f010a6eeb2eb753fefd44b47
+
+x 98a26f23f83673a480076b2fc7ccfef07fbbe70c4160d5af638c345f7d17b00931efff543fd47b7b8b362a70657a458566ada4aefd1c5eaf
+a 492192
+z 0ef483482255b5ca0f8338317f6eaf9c4fbf8bde8b8b04e26d2cdc0632186f1e62a9c3a1be23e8dc444ce50783135aeca614c884bdb77a30
+
+x 6ebf7c4e06837120cc852a077945656046e64c2d88ce440bdfc8d38736a4d510a722bc8b0d225f11df0e704e4b04c48bf481da68fd1e150e
+a -7098
+z 8d4e2cd12323b5744442fe4e4fc21748b344d7f94794398ec187f0f986ee743cd733a7a16bd4495818ab033103f020c794c988c5d2c1628a
+
+x 94e49f2bb473a7273abed94363c4dc3d13db159e3c3698a62ce5f321252aa03c7f63dd6eff9529c985f43abc7283d11140cb44ff6fd0f3d3
+a -392951
+z 58a606cdc1bf1d5646fc08c7a6b3336fbe532c823c70242ea7536cc6dcdde7c4f492306e39ac0fb88367e41d63a8305d69fab57a52c8c284
+
+x cd262298ce3b73294bfb523c30206fc3771144890a0ebcef19e02e5085973a6aeefabdf8cb7186d57be38ee84b114b9a7a22556c0cf88df1
+a -237681
+z 7553420c53b255fb909d6e9008f043e7af25a2a9c29b177b830ff1ae6f6fdcb6aefb8386465f24634fb04c6078322ac691586f91cf7928bd
+
+x cc9bd2e72ce15dd50877f95812b65c65cf09b14e2817784a5b296c123e498c532362180a932a455b2ddb75e26335dbcb21eb94a90ebb6940
+a 246794
+z 8838e720b6e497d9cde9fbddc2333c13cb5bdbbbe5afe41ffd61f5035c8c4987fddb8036c25b0505765bf1a5aa369c6bf7723c65278584a8
+
+x d8ab6b8f3523e98f49140e051c0b744bb0068d20f499c0763aa28ec1d1dd7e86356f357149c317376be96cd520b3ae04a2c4d468d74745e8
+a -360296
+z 4c0bc5f6fc52c6302b74c790d57ccc8fae59f2aeebb59c3393c56e70060f4d170ea41354f5040804a6e8dcb4a7c585ee71a6d90454e701de
+
+x 6036fbfb9fcc223a1776ec67c9424788aabe553a7d6a0472159edc747ebaf97e99f7263ece635ef0b702a3610aef32e17f59fae503e18d74
+a -5433
+z f6fa9a49b55077330fcda976a19ba7cfd98e44fa54044840df0ae9e19710193e684703f7fadbcbbc534e7be3adec0cae0d95ea414494f368
+
+x a3433dfc89ec4d6d858bb5b018e2d474b7de7604ed4491957fe16453d3793740ef88136814f59b19ed3610252e74cbc3a36571d02e57913b
+a 237641
+z 7a01a802b7a5aca44675887d9cf94d04d4893e2dc5d7474090cb32798fa370690255f57d18dce2a57126bb5883672b5a74a1c780f48f7bd8
+
+x c17ecc6099e9630a4ec20f4199abe1c10d414f6d734014ada1e6f097090a2bb4e638fb52d9bf56080d77c2b535f52cb091cbaad3c65072e8
+a 517226
+z 708adeac4ff99cac4c3eb649d55276f58a7d21a0507af176a53893c567050d352af501a9c242baf53121e8b56f5679b175dc01538350b644
+
+x 134263fd765e5f1da64900df5643c5241d4fa8a9e96ee59f01667b64f9122e85e995b90d4bf5d5fe9f68825dfa6edd19d8ce009270ae2984
+a 390674
+z 2ffbda7ccbeecd8dc4600965679146753c496d35bfa546e13edbbaa259065b024c8aaa3a17a3384f4f14d5ee01371ac55fb50a153b4ac1c0
+
+x 54326fffef9f0fe1207a07c8ac063d64b3fe81528e005f857319a74da2c3423a552b05f8c465908b028a2dcf15cb7158c99a1d2bdfd890da
+a -255467
+z e554e875e480c68c4fd780425ff8fb50f18bbafd0536a09489bc7cf197fdcb80dd4c7e31447a1a862066b6761ea39ea3b8c3002039c86b40
+
+x 5c30f73ec3addb2d27e0e79579063f2d30fa9fb47c2b6a3a32553120a047cad83abc901e5a5b4a65f8e51144f7eb0abec9a4d105236b2618
+a -466309
+z 5ec894f6abe2d88971da11b982c3322d1f533a326057816f6273585bfa186a7f569ddf93c27e8e74719ddb515689d5935c56e6b86936f22b
+
+###--------------------------------------------------------------------------
+test mul
+
+## Easy tests.
+x 03
+y 02
+z 06
+
+x f7ffffdfffffff00000050000000000000a0ffffff03000090fffffffbffffafffffff00000020000000fdffff9ffffffff9ffff7fffffff
+y ffffffffffffff01000030000000ffffff2f00000002000030000000ffffff5f000000fbfffffffffffffcffff4f000000ffffffefffffff
+z bfffff6f02000083ffff5f010000a1ffff9ffcffffc0ffff6ffdffffc4ffffff02000082ffff8f03000089ffff6ffaffff7cffffff000000
+
+x f8ff7ffeff5f00001000000800000300000100a0ffffafffff130000fbffff0100000000e0ffffebffffffff7ffffffffeff1f0000080000
+y f7ff7f0200e0ffffefffff070000faff7ffefffffefffffffff7ffff040080ffff1fffff8ffffff7ffff0500800200000000f0fffffbffff
+z 0a0100240020f5ff7ffdff4fffff4100003a00201400400300a8feff030180e6fffff9ff8f02003001002c0000f0ff9f0600d0f8ff670200
+
+## Random tests.
+x 94aa99eaba90c5eb2efd7101c8efeffc1e44c8fcd84ccb8ef27b9792ae12534c0a250e5400407177bd655e51c343f776a3fd26474da4dc74
+y 284a0f7df2d7d7c760cc57b1606625884c1643020230a9eecca7de6098f5338ddf9297daecae8a07e199494cb6db91c2c683566bf79545d2
+z 213a31ed7e494f470736ded872f2c4f3675562a7b42bf01ea246be0ecaae2a61ae500690df9f99ea9fa8e5e1b9ccf3614bc34148b7693c91
+
+x a434abefb0de3c7f5e33f9230ead871bb3f06888c0d568b9a74fa32b676dc600fed2d54a042e1b97340852c4d6ef796a18561884d760d4ad
+y 99d4c85f047d3dd8e530c50ae7d80815a30ec6ba820316f5da922cfa7a51ab45290ac2ab8a53082716a6d7f77ac5a285fac298eca4fd9c52
+z 97b2991fcc858d5667d3674484db9435ba71ab0c836c534efb823c123f9e94d0d3445257c55c73e8bd62f1d7acf1d75fea5eea669bfb9912
+
+x fe9911abbe57f1ddd61acd062d59637b129a1571af65fb70169db0d8b12b498a66d1eefcf9c8cbea01179f113afef0ae192550828885689c
+y e371e9a11f662e38caff28cf4cf5ca8cdfe4a8b99fa12a33765a22ae25506874fdcd85388ed406a955d293320e01957f119027ec4803c2a9
+z 171b49441f9891d927d2f6436eee1dc59e7872730be496638017b42151cdf00e9abb212bafc47c05a4e185bf7cf21ccd97b0c8ea426e4381
+
+x 1c300df44d28406d070b10c1920e01ea8b9056d9e1d6f9704dbda3f6328c26a28e9e4aa07dc79e03c09c5639cf8b8c783c8b430b9d8c21a8
+y c565b0357a1e8aff3b3a6164ff34c9598a1c15a1551224fb38d25dfa3b0627c9d992dbd215910236aeeed23f4efd99640054b6648946346c
+z f7871e06efb6f737cb4e04f708827092e94e3c70faee57f70096b9d674d0ac5b228824924bb705de49de9f9c0e834462093a9a5551fc7d5d
+
+x 9014dd22854f1f21fa1475d74eba669101c871c2a21ffd5d10f0792e3cc5d34f15b4735759575dda169e2dd868a5ae64dbeaa2a654cfde5c
+y c6f59ecf6add5ff92813cd6f37de9c6f8d3ae9cd33e4f3236ff43127f463f297c3067493868adf7823bc285a3d609a57d9b0b841a9b628a1
+z cbebe67e30ed82acb0de699a5d874121257b78c2b0642583713b58fdcd089a6277a5c5e571538e4af9025dfc63cd78931be51780055dfb2f
+
+x c8fc23a431d744e45e8bcd2dd2ca612db40b26287970aa878a5cf6283c51b2bd4edb76f705f29bc3911a9aee8fb7272009520f3590ac4c4a
+y c1015900ea58d6305b8b558c992bff50a8614843cd3d11274830dff6e1db405f8b268100fbc5e44c477cc2a9e83f825c7840e560fc2b2920
+z 6ecf49d92efb60a15a9de38ff37d3b23b339d889ad8b11cb332df260b9c49fd28b287a559fa5a5edf732b3bd1014711fb7d088a37cf6ef72
+
+x daaea5c9549776d866be36a032027a65eb8325b1684d3c37cba068e69aad7d4f104ff47c14f669883cdef5dae9a0c7840379631ef97e6bc3
+y f8dc00891a9c55481a224309a8024ea257850b2bc62ab10bb5ea5b836776cd46994900d6656b7f7e0d9092fd824b16d20ea14528a0de7729
+z 83d3eb62429c2ece396cd7069dfa2985630da2fb0949b52f1df9231c82f32022543d4a2302241d0146b4db97f44ec5342b6444f463ad056f
+
+x 786f4ebb20161c96f93ffe3ee2b0cae50fc454d910b3fae4fbd8454b8ab7975c6cab8f6a1b593996b24b22603137a52ee732f9d19f9a6e43
+y d78d3df4f455c8f5d98baaa17200d4c94056e21768c4ca783188bf15c28dc86c581fd9c150f923f905becba19361ca94f7434d8a74744669
+z e857a2020e1877b50151772bcf06763285c1d8b2b5ffdb63e13ef4985ccc3b965fdb053305f16feea4a3ac0edad21423c80ef847181bdff7
+
+x 6b48bf18ec4557e745cad3e106511bd5a9bbe136c77cf639745f891f54bb16c11e19770eb5112df8bb6755b97cb1e23c9c7efe589693764e
+y 95c2a38f889c451f792c3d5d8b3237eed3f99e2b4857bfc48f75d7c0de3f293d2cfa7f97d65d75e0e3df633d84931973ac542ce07ba974b1
+z 2fdfb1146b569ac98b0811e600e2d8e578023024ed704f97c7f7d56a2b4a33ac6ec68d14f0789441a904d175fbf8b91603c532ecdffd27e4
+
+x 1fbba059c333843e3cf0cff19bec99bd0cfc89c3b390200165680b742fe540b32042959022e7393c9e13ef7fa3f1dd5ac46595803210c536
+y c723bb3649b1d95647636abffd325e363931782f02002ad6d75d2082c980a7a2c5e1d51045880b36d4f62c16250faffcb2acb824d8d3d5d4
+z 97041eef8892ecaaa97c4effb8c69160b3878fd302bc5f0862bfe4894bf23193738d8dd95c9eee9539e23fff67243372b97f02c3a3934555
+
+x 26f5bc0c2c49899690fa423478ab1cf7000be27609bf683896a6ce3f619510b061ca04debb6c64540e724d113cd4b8ff3485337851367700
+y b8540188b9ca77a82899c7fd26412dcbd6a3c9b45be595f63bce7426d7c16eb20c3a2dc86afe9064edc19840f75f05de828c276e98451ee5
+z d973580e88abb6c83defc009607082ffbdcae6ce9d577218580459711682f8708a15de9c62e3ca3b50e91a7bf5781deee152ac801a64fe81
+
+x 6c044d6556abb8efdf5b180695293464a8bc4b9cab201822053c7295973ea0a8866425629cfff1d372a48f51dbc6a7f828691194c32c2c5c
+y da28b84dfd48f206972fe282449991597bc7f0734916b6f7a253897fca2ccd6b80aa477cfd08549b6d25bd18932128e59889e2dcfaf76157
+z a599fabf997468487b9376500b58a51e0e00c86d9eac6f50157aa1017d99ac8b95e7842b36071a192784ef72433c06a1dd042990b71ffe8f
+
+x 50378c6ac56816962d428ea523a0cf87121fb3c53b37bac6d3a05fcbdfb8a5fb20aa014f1e1b01a3963534d403baeb7c436f72cf3cc5db58
+y 78901fa015c6f0d3e1072aa87d865579fa405615691a3f27945f9b1431ee8bce8ac9965a1f9b0f42ff10bc77c43cc93566eee9a9b79866ed
+z 00127644003ed4b518f04abbd058a46015fb328883b92070bc5cf0fd98d7307dfabbc65f3e8551c622792efabe55f03953e498e360410790
+
+x 5db2f6db35af2e1c84ab6832b967bf987cd03adea7113fb8806ce8fb3ffa426dc10997e13afcd39cf5cd65f65f8a09e650fad8e5f6ef2648
+y b063695bc97a18d6ccb0785ee4588951dcbee420ce8e37b25cce325352968015c94f9bb784f3a2bfa34c6a1edf710b63f139fff6d4f7b2f3
+z 999284a309482f67ab6460e73ad1ad267052b59fe50cd58a245e22079e2b50b119e312ff60a65037cf9faeaa259d22f689eaedd7924f1093
+
+x d5baefaae7fc9000e0d55f287f740dfb1899ba6e9e36338959a16ac5e5f45442a37086b5519a0b439f38b129328aebf468dec4b59c89a249
+y 4febc8666dcf2b150faec9902a5f57e97275e7b122724c2b77d9b78655b455d424db93f859b8de6b09c4bad6d5ba68349c65c41caca67f8b
+z 19e6ed86dc819e6b4368d196679328710f63bf1fcba6652265508b509ecd0e3e8b8bf17f8f1eeb361af107ef684a729a3635cb55de3f8605
+
+x 9974be322a0f471cfe0855456104219d8037ca1cb5aacb9ff5da86a047ce159430cfd92f67e764244996668ac44d8d9787dc1b5754d215c1
+y 78c00f878fb41fdb0cd22c026881d5022fc470755e6261945b9bfcc3868f591f08288e4d64a65c9f3d0b05d3ab7f27d801aef29e5e98caf8
+z fd51b84f21b06377054dc879b8a176a7799951d5669486b210e4528b9f52bd60f88c2a068f722d85fa12761a4caf2f05bcdeecb7ed62646e
+
+x f4048d4a1602eeec43cdf20c3ac9f7b359935bae3648070276faf07a5c58fdf79771ba6c077ddeae47617971e2145f4960587637e7028822
+y 32635c7425108f5d19e35e4d91a4bdf3310bc884c9061d0697556ae25e17cd611e090c1179ca9a68225b283c8ab98a7b1e97508592c60c66
+z 8d6a91d016aaa7a0da03b06f5876ce8e8a71d1e5e5eb430d6c5ae16e1d6d9b61e77179b4f6fe43ce37cae27689983d41923f3b30e9d9f930
+
+x 9023c019bf7ef6df45e0e44111903c622220bd3dde046679540302451d001e47a153b0ac7dcfb9831e2d262d8e27002197d9640900e4c1cc
+y 1f5e2ca612ec6f14df4b528cc35001e763b9414a81381a1a3c7008c0cc525bdb00aea94ce2348f380dda43b5edf4fec7c8cf5ea2f5fec4b8
+z bf2c241efc180988232b83cda91e12dd0aec0d22ab68353c9841c4ea0547fd1b377fbca125f8cf92c426f8eb859f85a3853516ec104d9b6e
+
+x bbdecfafa9284e3067081b7d1bd7ce0e488829859628a8f6a38bc1a3ca6ec3130dbc1345b69abb7224b047fd3f2dadcf9cc11a8ec46a6436
+y 49a956ee69cdfecf29440d60fde9db1edd94619af97f625d45dc83c64994fe6c1ac858150cb526ca3c58a9fdc09d409ee3ed0b0cbcdb711c
+z 7abfd47fdfcceb278c917afd059e335110bec63fea48dedf7f8275da8922201ea06be39e3d1bccea2d38f5eb7d7aa5ef4e6fe6792a9f0ce0
+
+x a9483d4f0c94eac273adc392c3f425be610206683cbb6806dca47be3b54ad142fa2c54a7a473675556bcc8cfd50649af3c58d7a91e84b428
+y b986365aa08f088fe04aaaf2e00468af3fb41cda961b56ece5bedfd83cf9a0fb959ae70c23d9b27cd1eaf8b611d9e578aa0b9d899b81d5f1
+z 4af529627637ad3f3f1269319f4fd426d31e276287ee525d0c64974e55fca1cd58694eadf47e44dc3e843e01c36b22f9717067a907840ca1
+
+###--------------------------------------------------------------------------
+test sqr
+
+## Easy tests.
+x 03
+z 09
+
+x f7ffffdfffffff00000050000000000000a0ffffff03000090fffffffbffffafffffff00000020000000fdffff9ffffffff9ffff7fffffff
+z 8c000040010000f3ffffff040000f4000040120000ff0000800a000099000060060000030000000a0000e7010000180000290200800b0000
+
+## Random tests.
+x 776cf7ee39df23538f76e6be87ecbb1ed78477b858e3520f24b2b36f09a7dd61daf7bd5990af13c11b1419d8215eb69c30efc3917097797b
+z 870001f8ff173e02ce682526a513ff99c6e9688cbec13839ecbf0fbc11d8f84f6cf53041b5bdcbc624f9787db9babe61cd477cb9395590d1
+
+x 1e5ef8dd68207b3c3d3c670acee7ecb277ee6bc10be9fa3f3d800e1414bf402298ca443de6fd57ca899188c884a93d4b9c9d1b00a7c9ce44
+z 4a6d6da8002b6a0f3f5c3a9631254ccc62cf66c93279c4b77dda55d32514c8b388b543002f8055321c7195ce1fd26f51f48732e664cdc62f
+
+x e02eba6cd5ec1cc39ab92db439896520e50a5f9e9ed6d31ad37d00ebb2a54cb68f1c0ae537006ec2ffb14aaad2de16ff06194929b702b95a
+z 95632fd74045a49782f6f9d0c86d554cf6efd07f9eef57d669828c77537d4c3a69138d755855640064f5e9bc8fbe0eca96fb04053f565431
+
+x bad2a1348fc0b54791f9f2875009c8be2d30f14526fbbc22c439c1ae2b865436cd74f428766e4e676b795fe9333312f6334d4e4ec2378e26
+z d87a8f7ca45620b4646fad2c22792538bd16f37879dbc4d87c21cafa60c282f6415fde2fb6293a8b8a6e5b3901f88d75f9243023b68f41d3
+
+x d6d221f2bf71eba62e49db570e13ca69f4a8a33543298619cda7c8d2524c9446b11ae7b7d301579f047565b7044b5286c2478896800ad992
+z fdb163312b884bc6d74c4c269011311388ead9c069884f48487f9ac0d62b39aa175e81976fb599716aaa68db4c02985a6f0ffe522b0fb21b
+
+x 20cc05120202e684981bce1db74af493d218ed8e0f5e76fad46bfeb98c69e504113b0eb91771c602cb422ae09846fbfef7c47afd09689277
+z b07d84ff34dc5f0cbcc60037400ee04ba09f34d1d7a0c6a80672a3f6c1da630681d4207ce1325d301b36f0acaafd7579a108646f5a26b755
+
+x 72c4c3e4fcfd36389f558e0d4016f3f088145be47b2de85ee7ab963fcd8c7adf449d5b7c37ad8a32cf97ea9bde5c220fc896cf1b91633e19
+z 1e8f68736c3b259b661c0c1ec065a642e717f9e4d86003411b8e15ff89537d8e129c116d2f8a9e7e1b46879deedd66fa6ce2b60ab680cfb0
+
+x 8c524f059e7ebcf3af3072dbd2f76ebc530adba6d26240c8675b5451d5558db648e7a61fefb1369cf2939ba1fadcf8e40385db5d57cacace
+z a19188e6821f5cc2c53b7e59ae6f70e95fb929c0f282627ccfa2c6d9cb59dc871e9dcf3e2a8d6d66b7a6907d4d36c9de03c3d74325d8c1f1
+
+x dd47eb6f4f68cd3a9abd6af401bd6f3c795d89474dd41a89025b24c8349a0de417c3676bb6ee36002d7c8ff6b4fb4491e693cfa617e079f8
+z 871f46c93dea48a0d937b3f1f724f66615daa9200f0b48cee01c3b20e4a05dd6ce01bd7b2713e096cc2bd1c5ce7ca0c075aed0fc1ef6fa51
+
+x 577870fdb83454eed0711eb51d7bd91f9843769737566823e41d0668fad45c82fe069347769244af7230e6fbc40f5a71151279ae65e9893a
+z efabd464218df4a490b9870d541c45e9b7ab29bae25d9e976539a553995ded0edc5610916883642a032eae4e96eb9e4e1443f747dec98135
+
+x 8ba84194db2aad7b46005423b1251555ea931b933e0083fee76b9863fb528927f27a4a0617b8d75de306103b592a0fbd51b72bfbb051ee2d
+z 3a29e940174d846df65d51070295f535a03e988fc401ef62f5dd2456cf52668390e61e7b6912186d6d5260f6d6977004003bb106abbdaf02
+
+x 9f17e0943b4e39051abfd8f4512ef177fd5c368ebdf4b0af49df2e1d89e30c4e68ec474d81203964bfe9c1fecc1279e5e4f598ac97b48cb0
+z d794adb47cff3f7666dd0a934896015e59f278d9b1d6dc7a06328da96d6e6520670598129b7e1b26f9537216364199cf5c0010f23692ec90
+
+x a6b51625066e4cccb7d45dff5b182e2a6bf4b1cce7090a187d38dd39f08afad6f868c0277bf70d5fb88b6e67432526e4feb39ae707e34990
+z 67315efb85e16a1e97130092cc351759d9c18261845329f63eba1e77d91ad2c7df51ffa50b655de81bc807ea2b3e137214a2b08b400f2b7a
+
+x 28a0fe53cf73a0419fdb4cb493c6425be8aa812c3693411816c90621097a9d5687feb16ebf874a30ec849297742b7aab5921427d7b474190
+z 69300770a5bc2c9c599431e5f879ef3f3ec065e3a2cfe82e3499018add58acada581e9e81d40799fc74674b9721da018a64138519abdb108
+
+x fad58259395fd5bbcfca35b095253a3a121b62f1694e14cd9e2f85bd08e8a15d1dff98e3b81eeec678821a1ee9d6192c8351bde45ce0581f
+z bee7e0d6d4de419981ba2aa3964adfc7545e21b72b65c774b2029c22e06f251cebf04cdffd23e2051b57f986cbf7e56f047050714a275e72
+
+x 91e548171a8136d2d26e6bea02cb16ec9591e9cd5b913184b22b43d1029bdb214ef737f6e45f473f7d95b8fde075645c3b0c2dd2bd224278
+z abe2936ecf2ac3012455dcac906f691f2d96490539c9621658fd7f66790bbfe0d2df07165ea80e0c3282642d45b63b7db476b53e4f94f1c5
+
+x a52c855daa9ede16ea8de7c681436d5d31eda6ca5b441f972e5cf5639a1c56f689fcb411965271853de2893f22b81d7d0facafdb49292e39
+z 382480e92d44199fe5f7c357ad2e5a7277beab1a3055d48e679516151ca85ee3cb498b172087d588738daac2ec1da9638552d76be97626ad
+
+x c65888cdc1a575fc9a06dce8800607f56fe88839948b7e4e2713aae44b0ae6b7c6b68786b11b430d22766e9e4d76af118a972729c67c06b7
+z 31311e4ff9600089b533cdac6c05de3ddfe6a450ee7fc90cde1bb297e2deb750336ac3ed2f6fa9b88ece846be6f6aeb392f6753eb6fa475e
+
+x a61c81d621df61ece4b7274f63ae4e9f2e2df1d603fc9303ee361962b2d70bd783ff1b5d8f3ed27f17e7773b2b1c85af7fbd70387bdef5d3
+z a014ef20adc291c0238be3759ceb9f9645524b961761c8a991ce67efbddda568359fe36e762980d75a58a7ba10b803c9f883fe4d2239a08b
+
+x 96ced952366c324c5fccd48ac5d475cc1944e7e455dc093f0d9680d6d6abf1e45c76a286ac46acb4de061b9eb673a2d3124e6c3b921ad71f
+z 6debaeff6a7d2bb2c1389cb3338fc87b2a32e651ecb8d43fc012efc9b9c59c79487b742f0b30d0b64ac283af0d3b877102c6a7ff0f606eb9
+
+###--------------------------------------------------------------------------
+test inv
+
+x d665678f17043846f953fb09c88295d7fd0a53bc70ec7d396aff56e7dfa376f3a338f0da0af9e07b66d3ff7443e3829b541bd667201999d4
+z 6839ab730bf666c6ca987d254d83bf32b981b466c147f04b823981da75e12c9ded469a0a462861a987c13f05739f47596401fec25a5eee5c
+
+x bb8d567f6163a92603a388405121bd58abfcf05c596bf0624bf65b6a8fe03e6940648382fe01e5ab58e37ce235f4acbfb9e02624001c49da
+z 3f60d0fa0036da2db915e232bd841d09f006d4ba018c1d268af86d36990579d669ee63393b95c202645dcb1225fe9e64d14270905e63eb79
+
+x d456692d8e00bf9cd86d22a9f4ad9e9879e6298274854ae82729ebbdb0cc46877caeb381506dbb097b10c180d615661189da65d431e3003b
+z 6e0f5a173fb60be882a2b570200515dc7ad473e2192470ba89e6dda6cfdd6ff77026a1d76acdded7b5881a54d68605140a4ffceae70906d5
+
+x 359ab073b7465de1358a5772aef79db09118541c062421cb30a972525a351f16b5545daed5f9ce8e91a283818df6cdbf443831fbe5f3e848
+z 2b0ea74e6f4533498eb3f34247a9674f3a2cf2ab0e4fde65ff11b0d1e756430bc5452ca4b85bd3a1f10f6e4e3b1874df8d19f390a9021757
+
+x 3509fb8b7688f354738d4a8ca4091f66c880db794aacec6115e675090394ca77e1c83b955aaf4d8e75c6e4e9200be1ce5693532a561d970d
+z cafa18317193054cff7884bada249422ba889c19693d66610fb774fb4bdfeac0e67a5ba6f84ace126c125c46b4cfd627ee777e231a6ffc1f
+
+x 42e2babc095d88b61caa8883e91fd045106db9c4eeb4d945703c1dee3229c58869e21f73909ae2f3c4437d301a2a3724d67f6ad310f63835
+z 28c43a594b6471412f504dc10fd79d2c04ec029a7723cfa0a90aef036991f1b56cf156e2cbc7533671086edb54036e9f4ddc9bfe2e3ffcda
+
+x 9c01d006213bcfda413517ec815e8cebc06707f5649398a9d14a5d64754375c1ded8aaefd838e8eba84746de07a0f9b32caa2325c4c8e540
+z 0a3b64374ac2149d602a9f0ee4fcf6d814c476f451531a086b04b0dd598287b1758f77780b7de08573326a9767e816309d871fb1962bb1a4
+
+x 7bbd8a2de4bd2ffee4e93d0dd2fa9c5d4abcf9ab86c097921fe7d603b7ffdd07006c7d79d1a10267edce9b3069b134bed727c8f0ed1aca13
+z c909ffafbcc09a96723b9afba8ec0d00d5ce0c9d85de3c1e4de24cf44fb934bd0d2397b380885b7419cbbeac339fc85e2161f08c2f3515d7
+
+x 6a64650ccf103604c3b030415f7114c88c7094fbd0fd2f2b6b907a27fe104ef4e0684c17ff9f26f15eee5e7442e679ecad3e49a0629cb5c3
+z 9db77e47433997640b4c0916c5123e8a4d9c7c0bcd12b2dafccbababd6c9dbc3f4ec7991ea68b3ad4ffc6f0be4920764c65d98bdeba8a811
+
+x c3823c71f6c0f3679cb9c776e437e718f856c8fde038418942d062423113352aeb60ab84138f2bf73f268386cab0f2a1419660e966c24187
+z 558bff4fffa85d6f67ad44938f5b4473d250a87a120af9ff645a7db37a43808abe30c19c90bac94adb190840078214518e189d6c9fc5bef2
+
+x 44bd920b0eaf47695f93d063cd85c43c58470c23796f4a106b298d5f2b091210d103e9575c369bb0be66b2323d89cc29602a8071697931c6
+z 67464f2dab3a95c9ac7c783017105df7d561d7ae499ad89c4698da2c0710a1654c89966a7bd30d2d5c0511ed9f020309cde84cecd66be8d0
+
+x a6b12fc35e62532ea7c1fd49dd834bb7957da914ec3daf2e4f446b54916d016054cb59ffd4e3d9eecd4a18b08033ee8d9ff84db072cc4f86
+z cc70960f0bb743da1b23d11eb87530a820484a861abd68d2ed7079b487d88481d915b1b34c29d9938b5fa54d05c75cb1aebf0b722a6770b6
+
+x 1773dc978cd9f94186b83fd5e10a456b48058acd9e3bbacbecee2cfd0f8303c64721ca64c2913d57764336ea055700c2fcafc60d9f4b817e
+z 49e443096eb28c167ee62c63bfe4079418fa8e7f9e58757e13327680890b02ce7c9e5bbbc51366e0b3f5315edc456b6f65a09ea1b1a24438
+
+x 552158406db36accc32edde2f0ce46e23a1d406f60e54ca6a789386df36a57434c826c9586c4b371df3179f675e5956fe7dc3022f785d9e0
+z e0025a1007d3dff5e44947a0292bee8db5abbd1a0fca1d3ab0a64a37925396cd96c21af54d36656eb0b60c63fd5651622ec5487d53f976e4
+
+x 6b006d36f60750bb5c59f6eb31e2efe6098ab67de7a7a8a27201652380a295c408ec78351c2a799d62227dffd4731b7605e5c462dce2c1e8
+z 21785aae5f73da711f6144894728627824b685fac3d95068a9d0c4e0ee058301a8953322a5ee5be75452164a55477f1a987103a718bf98ca
+
+x 700cb76911e718ce8829f8d767c53e333dd2f7f20d2c020d1da3cc9ce96b9f6c7aad67450d5aab8f8c60e8ad77d4b5fdb86fae92a0ac30fe
+z 257f202b457f19f27ceed047e6778204c2b71646fcc96e19c6f07518780bb5b1c456fd6e93ce2f1cb0aea1a225137511dc71e446c1fe22c3
+
+x 0c909e0326649d4d375452c5b233a86e90b0fa88b20aa54e02685edd02b70aa022ed8af31e994b70b20101a5cfd8e16ba53c702840b4a16b
+z 98c41073ea843b4b5ad6b0589699f48a1576e3d834f8e595b8859069b71bf5e16126aa93b20259ff0a03976ff6d7f78239ec1059f8cf1193
+
+x 4529761361781e67037eae69c5ca9977b1e21468834eb83cd369471e5092249015cd263563bff9348a0f51e4a8517e27236ed1ecfe30a780
+z e20d5896be18bb273bb0ba84f6c070de45378bac6d793685e654764e5aa847d48403a68560b48dcb12573ac737366ae701072300615b4659
+
+x 6fae83f7eadeaca22b6781f400b01f9de186b12e31fdf56e0ebe98a8420baacf5069ffdf26d0215c16b64027dd69ff29709a64cfe8f52dcb
+z daa266a02c4500d989670eb63ab78219892d9c1ca2e17f4b5200cf1d920cfece5e80050be77f81a616de840bf19c23835ed17d57aeeea0f5
+
+x 23ca16e8b4c15f8f2b216441d851368d185a7f8587f398b0cf775875678241094538708da0cb2260c5e056b59c003c30c8f84f5088d0c99c
+z 9de1360b4718fc762e6ffab46827c5e4672a77d797aa608b31c132d1ad8138e7a64ba1f4278a07a6088f8cec9a01ea9bc1427c55241433c5
+
+###--------------------------------------------------------------------------
+test sub-mulc-add-sub-mul
+
+u 07ebfe324f64b54e938951a1e437bab4d35c2bbf5f210c5d78ca2b4eb7ef9c3dab61724be4fa7c2e43086b58db7e961f62a44b029f9901d5
+v d44920bba642b8162d1c3e956e060bbe6f15484298c2ec55575ee378556b0e8826f627bebda963b7d4d9f1c768a49cd408957105d3c6008a
+a -41997
+w e3647583d41ee4e813045d4f7a8b53af084c1dfeab8db93472810e8c54d253a2c100a6fc341bd92223341150d363f00f1c2bbb9ff9f8e7ca
+x d61c770618adfc42ef3ac4272dfae86a674f8ae4c273d26ad7b9a29943c4740e0c9535812b9ef0d17fb4bfcc77bf60646aa96a11c29035a3
+y 76c496c2c798e23c657eb80c44940229ba88f21bcacb21cb6b4cdc8b93d10832f3c4d31819fbeacb6c5a516c7889f0e639abc29ec4d7b604
+z 5a94d8487539381061d764a3806e31e1b2add772d2f9cb9c4fb96336f7b36534a9a0f7caf30b7e086c875670a0d568f895502983b1dec2ef
+
+u e1792f9e9c7b70293e041a9059df95bcac07b4112f25d35375ade1794660a0a10c520adf06fd477c79a170ab88108e4b74bc47ede8ddc0a4
+v 6cffa5fd3f07f203fcf08c399690b793a152e65aa99c6f9b465d39861c3c46691b635cd02c9e77083ecdee73a54aa1aab5ce6044cb2cb8d8
+a 23228
+w 31cd1c1937619b8fe711d22912104fd03fcfa3f14f81f3bc7ec9839c5440836d7c9b92158c818933aa614f9a085f9a1c18d71dd11d09a6db
+x 2386136ccd81814300b5f3fa148c4025e6d7a2d9da344e56b42811deaa3d4ecbd5365f91d941d7bab20b305ac6dd0457a4b81cc611bb5f11
+y 16bf2b1e10c77597990088a8df91150a6e7b6c3008e6584909b2f7184358abf6b59674e210aeec3219a5202440139aecde4a4b6e0f46dbaa
+z dd373d5908b408e51e3c6f8da1c439f845d40467057a34a96cd53680661b329f073d0bfe6af98543d5d38c3d0476c19d20c54226e7bf8d7c
+
+u fe6d00268bafd5878e0a4ddebad8dff25399a1d18e69f94b471029058e9712b98263d88b4dea5d08d8fe70b3a62ba2d136c2c2713ca809ea
+v 12be184341bbd7ab5a668f3c3e4b13a60c70cd4e1f229f90901be24a285f3ff0b7391aee82529076c14232f61a11b6a8edffd56af603a25b
+a -252008
+w 178e5309ab3a578b8b09149da9539d93309c5214b61e3c045034847354f59d58fee27e31dfcf5d5daa24b5a605686b468a3db727583709d4
+x 8da5b2f4c39e442c729a09cf04405136c55cf7b76fbe949ec3b34fb17b2edabcac44f4b4a19afb58c9d86eb87a0c58cff2cf196e6cac7da2
+y 3b0be5158a7c13a6c71455025ea5b4466eaa321956fa785f9b74872532e3767d796da94ac47e6d25a368ea1ac79c44fda8d2e13edae5c219
+z 7ad75999f1bd89b130fa03274247b36b2c2684163097d46deb852083b5fab0e8755d2150dcd2ee563757f05eb1d132df284ccf818cd56b9c
+
+u e4ef0519fc7af554a4a348cfcea95c6c18752f4a35a946b7d2ad1e6aa77d64ec4012eea4faead2d91c66b0d57198b19317a79e136a98caf9
+v 008c72ff456f0f941781020ce6387d8065772af7c68955668a7cb05b53f00960f15fc463029a2e2a353a2fd3bc43790a847ea35c75d6cd26
+a 287411
+w 5ee722a21955b3bec9ed5f151686af9da9d3f5e6491e3d9a8d82237b1e3dddb58b827264ab5a1aca3eb8c1de7922b59744567e0467a4357f
+x 9381ebf793f7b3f523f4621e934217ba463f96279ce2e7d165fc00ea037b20254948132dd2f0481ad9816e1f66da64d081e4d24866094af9
+y 62e4648d4716c6e0f99357c8c099c4988cfec4fa21873b7928350f174679f59629a54d78bc8d239800709a585d4890fb2b634f68ec13cd78
+z 850e54cf9388bdaf3de63c3e73823c0f39f0b9bf15a9f0262f24c828d2fc8cd7d1ac939193804fac3d92467e26ba5e57d1dc4f8664a270af
+
+u 5f3811d6b8277fd93a197bf4f3dec4bf4dd5fc6a0ac92ee3d0e64ae48fa9e1373cfd63da945db924bbac41a2b78f6819ccdf2820b1a3c4ff
+v ee669edf4430678ff1190be8e39c06dd00cd9982ab5b625e5a6814ec456f68f9467f1f38519f4bcb392772479ba553060391752ab4fc70aa
+a -254559
+w 3d11820f867d39b2b1169030c24a9307eb387f44ee0fc8d53a946e56065e8cf9af6069c9c8099de1565f3d491c33248965ebf941987ade48
+x 9582a93732bb52eba39d81c161dd0a996b50dadb13b4eb54085ecb9e86117ed25cb7c78d1a5cc3807a97d740710c2fbf65f97e8de3591163
+y 501c2ca79204d22e6c52d32d405310853e7e29da884c0f14782e9029929751821f81a9493c8dd76e582bb48465ce5b40d7c5e398322ceada
+z dcdc428d085f7548c99d963af7b8af997c1503307d75e298efbfc042d425d385a6b7321d86d5af13809ed3ec6bc5d96afcd026d08caeaa30
+
+u d17c198598d3b5188e5807c445976b769d458ca952a7b99da4b19ffa3b35b6100bd3605136143912640e402a7cb91675e61527244844409b
+v 9cac226e58f5ffbc41bb82b769ed12d061eef4d2d0369eb12724bcd4db6a1ff85f22d6b25003cbea0308a1b7dcce1450283d4e96ac8d4b8c
+a 516083
+w 9f92e7a68af5c7737f3f3e959d2b55230ca11e0dd467bd52a20b91816ce61ac7fa7059934c7a952e43058ff4f277170ec5ecc4cab51baef5
+x d4fb3628a45e2290c7fd201ca434ef83911ac2687218605782b3cdca577e692a389756e6b9a0891311727d623fe8ea601fb13efe238adee0
+y ce572b3cdd011749634a577c727aa4516d00c4236cdf3b4664c2be35d3efe7e0b140b5ef2d4a0339a8a29eb26025e60e7d166913251966be
+z 790d7ef8990c44fd271d5a41c55a6d552f60fd8980c1c3b91919fdd5e291c75b0a0cbc4224dfd2ce93de2eef53249f3d9d0955f05b4cefaa
+
+u 396fe89631a66fcf4368600d3a8cbfa6fc903cc8d157f13ac0e4a569436c3230c0a9319a55ebb7e61d428e74b8ce740e973ee5d2b0a99a61
+v f644b35fe8d9bd57a0e6837ef03d889df2248a06a0e52a9cdc80307cf68c496f34aa82f246b8d6e040d166ffa1920b7d921938bb33f8e8a0
+a -339102
+w 716c673c21cd0d92d86f8060beba37c65b7d9eb8b1d4f8aa5665478278ea5c3a2a2c4f606aa179bc8b38f4f37b3e077959ac7c8c81a5fba2
+x 6379d7843800b16ad06ff70511c7ff656fc93ff95a05617b4adf7e2b6810cf2cf81dfd6b0c7d478d52f2f4989a13a3ccbc3a4e30f85a3279
+y 5b982eda7d33ef68c0d94400610744b91572443614a128bc90011a953bc9422910640047809049a513c413b4390a09395da3de6958c44b64
+z 91cf825bde194c05cadbb9dcee5f08f152d2bacabc144b4ee498b82ddf4074846ccc75d366184ee29bd322deaf99d6ae81563cc2e7b2e98d
+
+u b8bb334fbe75e81a417ef59e14b52898e34dcc8bca4bb2caa987dc31950a9afa4dd356735dd163eba9073056a2e7f259f1485ef37acf8c24
+v 0e872ffa891f664be01868170c452c25cbd41dd0e4df0a66c0ed67dfd3d007c25c50e4b0615450906c69788080546b9a4ad425402c422580
+a 287059
+w 52356b0443301992c676f6cfa7eeca79d586324bbb5f8aa71163b89d863ffc7879e55c363ce260fd6ab160e18ef0921d81a4d634799fe816
+x 35be6d14d3dc696bb20c90de43c7e08b2427ffc9c63a5c37767ee6756894b6d94c748e9d2c4d8519cbdc2efaa215874bb1923cf7aa5a826c
+y 8db5fd04e45f9f93c7a2a2e238c7f001fd7c059d02fce693340c106ebb98d7f6f3029d3e820e2e3e912901c33c3dfce56d68a7c42a2f2e0a
+z 29ff4f6533b4292d0e8f2a7abbd1269d1455d8ec34cadca9df875d544ba10395c36d1e750fb66ff0a9d97a92538a63ab48db8583fa6ebd5f
+
+u 74dfa3166dee585d6d4c5f310259a6f9a407e5c520559f22a3f290733d2f0ba8a276d46820bc73f9231fe25dcc8e9c2e2542eda5024180ed
+v 50881f8d2fac3278cadb483b7db6e179306b6e967f8fbdb53f70f443ba9f1b1073921a0a1f46c8833856e6a0ead7ab6f445abf833d2550f7
+a -430161
+w 10b16716f590c13b435ce912fd4adb5dcb4982d8e0302dfccff5f9d388efaae716e8d9e2915de30d365a04468f4bec0f4489d81c0e159bd0
+x b4e67998a7579734cf8f0fc281bb29e1c3dd4dd4d9c1434e830d4d093ea2b908137dad647ab349c5858d1b3ce20f7378546033114dc0fa68
+y 76a10a58f6136ec6b73d96ed1d506b758ddf6f54326f7b2a12d28dec9ed880dac2d16f2f57004c7df846ffb4c5c7de814a0245668df0e804
+z 33216663bc217e49c81d64e3957f3a16452193b677c68f3df80315c7496995a752c7f42807d22e6a23ad2f5568ada163ba168cd1ff3631c0
+
+u c047f2b5077afcb0c246abb9104309be15f2c2da8e703e74459d34281992fbbfb95b1012067415c5b17650d10f5d2d12b84c3c825068b881
+v 831adf8c6481178176f11f1d7010fa4b51c6e30ae8a9aec3a748a47bad643ff69cc8e1ba47bf9d33183de1c1220e989c58d6b23e8a602ddd
+a -445266
+w db32546436b5d585cd4fefcdf8affd7c467c31699787dedd133f205641fcf74ee246a5f62dee25eefb54091b5dd0cb4dc7cfad9cc68bb9cb
+x 9ea3da4650bbc07d7cefbff97a9bebe5aa932772ce0e47a4bdfaab1be5457f652f9882d8e4ca286b7bce092a4fe93b1c0473a2d5d33d92d3
+y a8eeaf02c9e281f2522def4792beff7382ae509316b80ca3e70b36c080706f9cc8589518dd9b27e61c3f3e28c8608524bc201076d6ae2fcb
+z 463c925f11987399440da6a502b87ee798b2dfc37f012951af57dda87651de7bb96c2c30890e6b65771e70ee08bf41e2bde696dfcb177e83
+
+u 63428356e8b4c5147870a0e653866093d5ca20a691524e3adba1c95af70fc706fdb420391c230dcb70cbad21f028b03e7554efac7bc8bed6
+v e99ca8f8dfe11c545b49031f68a605229adac19568b5cfb9b02b9721416c225179968b5583d0588ead12790c5df7c13bae466f934e997b4e
+a -445574
+w 7ace55b2ba3365a01a872ef5882a8d47518fec37bd816d809d4716301a7b6811926eb5aa593fb2c852ae2455fa42e92be1038d96ebf31966
+x db9244d18540fb524ec9455f493b570aba16ee4f4491247fa18efe63a43c70e533ad6660f64e836675bd788113993836c43a3c5868efe068
+y 8cc4affd9631c4ff75313f43588d977f24b58a0ef1c3275b7c142e6113f20d72fe974f11c9f7cf3dc176e1799dcb4230d5bb138ddee2eb34
+z 179440042f537fcd021678f32a1346547ac1a4aa5dc3e5bed329c543ec35058efa16af2ca066ffb7087a3daf68345aa3a0a21c6133fd3a59
+
+u 993bb02c2ae6974f6988293ce6eae32f520758329e80ae242801f45937baed48cb9bbc111731aea52883ca30286b7593746e6522fc3ccd54
+v 2bbbb81c8e51356355a1e49ebc1c6e160119eca0df8c07d171783665c9d96af7164e6bd7384002ed5c19f531bda705b90e06130bfcb2ad17
+a -159409
+w 6b3eb1b9dac2b8f6d86a0d983bd2b36a98c760ecf5f4aa30e22726e8048cc2e633a7a7bdc862d6bb02fcb0d9e854ac9dce8cb9982645ba44
+x fba6ac4753539d9dea1190d160994937af74be3f73856e56dd7ef4fffd1f6e2d99f1466fff7ec4bacd115f4e1f8708adb8c9afa7b17ee887
+y 7f28c3d4526328a9f03cbfb3a0b04fc2aac564effcdbcedfd61a160d0499c83742255e86764c344887a93f7f1851903372e40d7034b16f03
+z 2bec5989a2f2fc934dc0e673f07f0ea7ebade4d4bdf7bf472f7e779a716dbc4aa01771bd1dcc634780b0da41389c108a76fc67235e028142
+
+u 96ab5a1f5b6cffe08fbe3118d7bf2d09e6da8dfdb0ce69cae1c2d3fe71864db59befd7e252410d04a858ef680a754b2d42f7f4ab7cd38e0d
+v 673d469ae9193bb79aace5d641041c94b81f6f9a9d12e5a05db86674899ed5650b8d4d30bb00f2b51b0261245dd3a2e18a10f8109cae1535
+a 197264
+w 83f7aaef3c944d9d6ef3c329224067a204f738f3625488ba01845e31fa07dda26e08a4e395687b322f594fed860bf1597ab33536c5f24c53
+x 9bdc4e2e4e412b65af636a24480a40ab73df53fb209619044317f90df9bba10e5892aa502ee86e1039a8547a4e119caa359e8095ef0f5827
+y 659ea4924522edb2aa50430f9bf5ba3112c60af504dd290215a52c8bc275fa8fe0042348811a7cacd0d8bbf95255a547ae9b82db70326b25
+z a28bd6727521f46a3ab3ac32a3452c03b7ceca3c06c4e5f260c1868935269b8cbeb3d303cc6df3faee2595788af6f24a52ef8237763793a1
+
+u a0de95d94e3506ed563b974d07454fd347f7b37aa1e9453e0145d23e1867f2aea78434ace37877022343cad84d9100c7683b33c115014903
+v ceeac84a960af7e749645352ddbd4a9f7fd77e96268ed8548e4247b6084e13a193233ba02c49da24c89f2a62ed50029ab38eb6566167aaab
+a -5830
+w 8568f4c8837fbef756a3c03ee6a59f7ce0b5ffe370afb5c18545e4fe88eae49c65c642494e1cba91c4eb8b2fa94df6ca22b21d3e7b717f3a
+x 70170f374d567a159bd8e354eceee6aacbedfcf9a2be6b530808152a96e93a301518f0042baecaf90170bdc4cc8c2e1003bfe737cd258929
+y cfa4cd159f5793a1833bfdb97261c204d3a80a01e1488ce8c628e68225bbcffa785093267eb3f75702e70b6abef59bc0a223ecfa09aac356
+z 7302a30f89bf3163baf814605772b0ca175aec6a030e53a2677c49351d88f1c095a1974e1dabcf5859c206f4bd3e932f7973766e81e0c278
+
+u c297bf2bf6e64d4446a2e5d1c6448f5881c5973ccf6e75730dcf2bb74096e603a354461e02e818a94ace1f47053d23710719135cdd366d92
+v 8966ea0a08b7f43706340232c68a264c54b4e609ad8c901d0c0768c2aa5660434e5d4ce7510883238b17a8c92f8013d2488730d3a28ca291
+a -266784
+w c52a9e11dce1938ffb862357a9a696ee72c9fe18f7163d29052c949b4ac0fa151052dffa3546cdefdef598c28ebcc620d064783e8ee20413
+x 04f0bdf761a2cfebb822a12bb44b2def0906ae99cf84e7bff6d033e4082c2fed1961942288b0e2beb11a0e96db8a5037fa61631cd89896e4
+y add0f3d532987482db8148a8ef3724e27ad497bdcd804686114acb3a86e4e561001a7af6420bbeef57b77bf8444c4b978e5cd136083d9118
+z efda70e401d9e5beea539fb3ce7a145bfc90422e049387f222db53edae81078046fb1e2db538ebd7ba36ff5509691c83ef9c51f3581edc2e
+
+u 06768f69843008554828e6665685231b32e60fa878cdc11536819fb04874df4c6f9023b356f1cfb03a1706d04f472f1f1cba2148e161f936
+v 61d686b96bd02a99efe67123f3962e318ce9836b1ed0b7a39ae98483f38efa78a89063badbf97325b4743b2342647ed8a44a164e76328781
+a -301528
+w f8987e1314d3a3fa7ed1784fd04e4b381e9bbee6a785400e51d66402bd95c13de03e4a8213fbcbcec493f0ab8f3aef54794d8baeb9579b57
+x dee30a4b1359ae1459b790e8bedbce16eef2e299082dd2a07e46063c79af11524e438740af78d161afbd5b410888ab9f64eb4129dd1caadf
+y cc52f548a25b964b2556be59c5243b63a323701d696d8d3f866be512554227b8aa3567960aec684ba50701be5528f188a9bcba490517949f
+z bf88a0bbfcf8d048525ba4b7f64988bb8db5ab4abe40c20530b512f130dd54ed8f0bf9c36f51c20735415e25905d4047d896bf6eef7325ec
+
+u b2fd5cba9d6d5487c5257954d1d170a99cd27c2e990aa7b20006d8615b929f9024c5b3a0b063dc9c364a668cde34b4a26ec4e374d38d2a32
+v e4796d1ed6d6cd3443a095e6f91e80db3ea043b1f9026e4015a4abff5b2ecde79848dd0b856db0f47a6f29e1759fbaeb2ac82d2d8a939d89
+a -338517
+w 65c169eec5df306b2d17d58f7c1f833bea184fadbbc8924803cc0ff2804d24531e69004059169f29423b5692d54c92fec7936933eac92317
+x ab7c743547424e08a733876339fc4434d1c0ede96dbcfc7a92acbb6ec4e1f6e330d13cee90e4378863022bb49b57b6b4617b37fb5e6f7d0a
+y 5fb79ffb10f7c3bc4cc98025f7c7f71bdb4041a5161e7fdee2a701692d16ae77d23680becc76f14e66a7e961d8841adad5485043e13b7694
+z 365da4af25fe7f21edf0706495f44475b2d3a9b157b3008dd745cb8e756e3da662108d6c05d573aedfbaa0fd0c8420b6b7ab8d418d273be2
+
+u 0b1fe73972fe3400b1a9563b759cc65dc7f685031405e14ecbf1ab977c7c9afceafa91f51d1127f09058b637c9cdc39fa665be7c2a4d55d6
+v 349cebcab0d98aea0beb0d38dde902e4f6caa23cbb066e68ef8d384613b4ecf6d21780ae1844c4b3eb9598cfd62fc001505d3ce4e66746ae
+a -242599
+w 7c7018b38125bf7415723b398f888458a647f4a2f2ff0b7dcbd6eb7ae873c44068429efde0be1f2f28ae1c8e01db9f812442fabaf51ffadb
+x c125c39bcf8ae742747cc2f711e470b8386403e275a14e5651f1dae89231cb3ee186a3d2c1b1a74002ac70e1fc1a5adc89a17734aa231650
+y feb78a43f6e633e7b92ffb2789f6486cc7597ce0ce9ce2486828af900d97c9ee8fcd0f52d43d01e141f9987ad194dfaa8a31b9d649e487ac
+z 32318ade75655d7aacba10759063893db2482b2083a924915afefc63891f9951b58bf5525f5b330f16422c65bdf77a5508f1830849c2a941
+
+u 080f596d6be6f4554477689f6ac45ff60a880924f6e609701bd6d1fe32eb4f1be13edf39399eb170fa5b5b9801e38301e7ed768383cab6cf
+v f14535e25853aa97a8bc8128610eaab77977d07d3a89608a837b16fb2c2878f8edf11a2276f3c42ee21ba275dd4e6059574f887abcf6480f
+a 273443
+w f273139e62664cb2b5f9c268c37abfcddc054c0f30ed8f0fd643017a989512cf115467ca704b3442b1c92496e378f4df6434b27e9c9fbacb
+x 8af391a0b26881d67fa19196d5dded3e00cc3dc60247781ec1d000e635b6f39f7186e948bbb5b03894f0a000b27838dbda844836c5c29d99
+y 56513a9d50e48e2464df2069404f09c21d4bf112d2223ea316e78cb4ebbca403327ab344af7e15b17b9865ea8d801cc7d4f6f7283687c3bd
+z 9c3043751d7889855a337637b51e1fb9c7bb47d75ef529e4e8545822cbb2f535ef1579b9c660813438e2e9f16bb35f4a7843d3e7820e1406
+
+u a5d6bc11f9251ec7d03e87c267b2eb05d51fdbeb24970e2c87a7d8923f7adbf4bff904e5ae498f5984072d7a21c703ba6765bc3292e43bfe
+v 2be24a92df5b92545f72e710d4a5c71f881d544305e891dc9fcf2b39a24a5e80fe44f856411fc886566f428b5443af8140543e549d092170
+a -140922
+w 629534899a55d04d6e0c879ea02b9eb05675cf6074ce400d8caa25b2adc59eedcd88f203f9440db9fb06c5bfcd65512324d01f871b485650
+x 867e9ed2dbef2b0d485a7d5dc71266eae2b6053c2f1e09dfba6192f015419e06868aaaefefdc3b03cb26e50cc4861f38eac76ac69e5ab1fd
+y 61d009f31c5be4eaca1f44ab6800f0116dadb7923e427db6e525f03c17b380eaa6d0c8f06440674c80f0040c272b8b956366a82ca28dccbf
+z a7628d76da5a4a8dcabfcd28252b9fb1f780e2d32f72a0f1f8da7ff7d354c6d35a72efb2b75e87c332f93557c1a5e1bd51813e18ee1fe241
diff --git a/fgoldi.c b/fgoldi.c
new file mode 100644 (file)
index 0000000..14b98ed
--- /dev/null
+++ b/fgoldi.c
@@ -0,0 +1,589 @@
+/* -*-c-*-
+ *
+ * Arithmetic in the Goldilocks field GF(2^448 - 2^224 - 1)
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of secnet.
+ * See README for full list of copyright holders.
+ *
+ * secnet is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version d of the License, or
+ * (at your option) any later version.
+ *
+ * secnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with secnet; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ *
+ * This file was originally part of Catacomb, but has been automatically
+ * modified for incorporation into secnet: see `import-catacomb-crypto'
+ * for details.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "fgoldi.h"
+
+/*----- Basic setup -------------------------------------------------------*
+ *
+ * Let Ï† = 2^224; then p = Ï†^2 - Ï† - 1, and, in GF(p), we have Ï†^2 = Ï† + 1
+ * (hence the name).
+ */
+
+/* We represent an element of GF(p) as 16 28-bit signed integer pieces x_i:
+ * x = SUM_{0<=i<16} x_i 2^(28i).
+ */
+
+typedef  int32  piece; typedef  int64  dblpiece;
+typedef uint32 upiece; typedef uint64 udblpiece;
+#define PIECEWD(i) 28
+#define NPIECE 16
+#define P p28
+
+#define B28 0x10000000u
+#define B27 0x08000000u
+#define M28 0x0fffffffu
+#define M27 0x07ffffffu
+#define M32 0xffffffffu
+
+/*----- Debugging machinery -----------------------------------------------*/
+
+#if defined(FGOLDI_DEBUG)
+
+#include <stdio.h>
+
+#include "mp.h"
+#include "mptext.h"
+
+static mp *get_pgoldi(void)
+{
+  mp *p = MP_NEW, *t = MP_NEW;
+
+  p = mp_setbit(p, MP_ZERO, 448);
+  t = mp_setbit(t, MP_ZERO, 224);
+  p = mp_sub(p, p, t);
+  p = mp_sub(p, p, MP_ONE);
+  mp_drop(t);
+  return (p);
+}
+
+DEF_FDUMP(fdump, piece, PIECEWD, NPIECE, 56, get_pgoldi())
+
+#endif
+
+/*----- Loading and storing -----------------------------------------------*/
+
+/* --- @fgoldi_load@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to store the result
+ *             @const octet xv[56]@ = source to read
+ *
+ * Returns:    ---
+ *
+ * Use:                Reads an element of %$\gf{2^{448} - 2^{224} - 19}$% in
+ *             external representation from @xv@ and stores it in @z@.
+ *
+ *             External representation is little-endian base-256.  Some
+ *             elements have multiple encodings, which are not produced by
+ *             correct software; use of noncanonical encodings is not an
+ *             error, and toleration of them is considered a performance
+ *             feature.
+ */
+
+void fgoldi_load(fgoldi *z, const octet xv[56])
+{
+
+  unsigned i;
+  uint32 xw[14];
+  piece b, c;
+
+  /* First, read the input value as words. */
+  for (i = 0; i < 14; i++) xw[i] = LOAD32_L(xv + 4*i);
+
+  /* Extract unsigned 28-bit pieces from the words. */
+  z->P[ 0] = (xw[ 0] >> 0)&M28;
+  z->P[ 7] = (xw[ 6] >> 4)&M28;
+  z->P[ 8] = (xw[ 7] >> 0)&M28;
+  z->P[15] = (xw[13] >> 4)&M28;
+  for (i = 1; i < 7; i++) {
+    z->P[i + 0] = ((xw[i + 0] << (4*i)) | (xw[i - 1] >> (32 - 4*i)))&M28;
+    z->P[i + 8] = ((xw[i + 7] << (4*i)) | (xw[i + 6] >> (32 - 4*i)))&M28;
+  }
+
+  /* Convert the nonnegative pieces into a balanced signed representation, so
+   * each piece ends up in the interval |z_i| <= 2^27.  For each piece, if
+   * its top bit is set, lend a bit leftwards; in the case of z_15, reduce
+   * this bit by adding it onto z_0 and z_8, since this is the Ï†^2 bit, and
+   * Ï†^2 = Ï† + 1.  We delay this carry until after all of the pieces have
+   * been balanced.  If we don't do this, then we have to do a more expensive
+   * test for nonzeroness to decide whether to lend a bit leftwards rather
+   * than just testing a single bit.
+   *
+   * Note that we don't try for a canonical representation here: both upper
+   * and lower bounds are achievable.
+   */
+  b = z->P[15]&B27; z->P[15] -= b << 1; c = b >> 27;
+  for (i = NPIECE - 1; i--; )
+    { b = z->P[i]&B27; z->P[i] -= b << 1; z->P[i + 1] += b >> 27; }
+  z->P[0] += c; z->P[8] += c;
+}
+
+/* --- @fgoldi_store@ --- *
+ *
+ * Arguments:  @octet zv[56]@ = where to write the result
+ *             @const fgoldi *x@ = the field element to write
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a field element in the given octet vector in external
+ *             representation.  A canonical encoding is always stored.
+ */
+
+void fgoldi_store(octet zv[56], const fgoldi *x)
+{
+
+  piece y[NPIECE], yy[NPIECE], c, d;
+  uint32 u, v;
+  mask32 m;
+  unsigned i;
+
+  for (i = 0; i < NPIECE; i++) y[i] = x->P[i];
+
+  /* First, propagate the carries.  By the end of this, we'll have all of the
+   * the pieces canonically sized and positive, and maybe there'll be
+   * (signed) carry out.  The carry c is in { -1, 0, +1 }, and the remaining
+   * value will be in the half-open interval [0, Ï†^2).  The whole represented
+   * value is then y + Ï†^2 c.
+   *
+   * Assume that we start out with |y_i| <= 2^30.  We start off by cutting
+   * off and reducing the carry c_15 from the topmost piece, y_15.  This
+   * leaves 0 <= y_15 < 2^28; and we'll have |c_15| <= 4.  We'll add this
+   * onto y_0 and y_8, and propagate the carries.  It's very clear that we'll
+   * end up with |y + (φ + 1) c_15 - Ï†^2/2| << Ï†^2.
+   *
+   * Here, the y_i are signed, so we must be cautious about bithacking them.
+   */
+  c = ASR(piece, y[15], 28); y[15] = (upiece)y[15]&M28; y[8] += c;
+  for (i = 0; i < NPIECE; i++)
+    { y[i] += c; c = ASR(piece, y[i], 28); y[i] = (upiece)y[i]&M28; }
+
+  /* Now we have a slightly fiddly job to do.  If c = +1, or if c = 0 and
+   * y >= p, then we should subtract p from the whole value; if c = -1 then
+   * we should add p; and otherwise we should do nothing.
+   *
+   * But conditional behaviour is bad, m'kay.  So here's what we do instead.
+   *
+   * The first job is to sort out what we wanted to do.  If c = -1 then we
+   * want to (a) invert the constant addend and (b) feed in a carry-in;
+   * otherwise, we don't.
+   */
+  m = SIGN(c)&M28;
+  d = m&1;
+
+  /* Now do the addition/subtraction.  Remember that all of the y_i are
+   * nonnegative, so shifting and masking are safe and easy.
+   */
+      d += y[0] + (1 ^ m); yy[0] = d&M28; d >>= 28;
+  for (i = 1; i < 8; i++)
+    { d += y[i] +      m;  yy[i] = d&M28; d >>= 28; }
+      d += y[8] + (1 ^ m); yy[8] = d&M28; d >>= 28;
+  for (i = 9; i < 16; i++)
+    { d += y[i] +      m;  yy[i] = d&M28; d >>= 28; }
+
+  /* The final carry-out is in d; since we only did addition, and the y_i are
+   * nonnegative, then d is in { 0, 1 }.  We want to keep y', rather than y,
+   * if (a) c /= 0 (in which case we know that the old value was
+   * unsatisfactory), or (b) if d = 1 (in which case, if c = 0, we know that
+   * the subtraction didn't cause a borrow, so we must be in the case where
+   * p <= y < Ï†^2.
+   */
+  m = NONZEROP(c) | ~NONZEROP(d - 1);
+  for (i = 0; i < NPIECE; i++) y[i] = (yy[i]&m) | (y[i]&~m);
+
+  /* Extract 32-bit words from the value. */
+  for (i = 0; i < 7; i++) {
+    u = ((y[i + 0] >> (4*i)) | ((uint32)y[i + 1] << (28 - 4*i)))&M32;
+    v = ((y[i + 8] >> (4*i)) | ((uint32)y[i + 9] << (28 - 4*i)))&M32;
+    STORE32_L(zv + 4*i,             u);
+    STORE32_L(zv + 4*i + 28, v);
+  }
+}
+
+/* --- @fgoldi_set@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to write the result
+ *             @int a@ = a small-ish constant
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets @z@ to equal @a@.
+ */
+
+void fgoldi_set(fgoldi *x, int a)
+{
+  unsigned i;
+
+  x->P[0] = a;
+  for (i = 1; i < NPIECE; i++) x->P[i] = 0;
+}
+
+/*----- Basic arithmetic --------------------------------------------------*/
+
+/* --- @fgoldi_add@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const fgoldi *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the sum %$x + y$%.
+ */
+
+void fgoldi_add(fgoldi *z, const fgoldi *x, const fgoldi *y)
+{
+  unsigned i;
+  for (i = 0; i < NPIECE; i++) z->P[i] = x->P[i] + y->P[i];
+}
+
+/* --- @fgoldi_sub@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const fgoldi *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the difference %$x - y$%.
+ */
+
+void fgoldi_sub(fgoldi *z, const fgoldi *x, const fgoldi *y)
+{
+  unsigned i;
+  for (i = 0; i < NPIECE; i++) z->P[i] = x->P[i] - y->P[i];
+}
+
+/*----- Constant-time utilities -------------------------------------------*/
+
+/* --- @fgoldi_condswap@ --- *
+ *
+ * Arguments:  @fgoldi *x, *y@ = two operands
+ *             @uint32 m@ = a mask
+ *
+ * Returns:    ---
+ *
+ * Use:                If @m@ is zero, do nothing; if @m@ is all-bits-set, then
+ *             exchange @x@ and @y@.  If @m@ has some other value, then
+ *             scramble @x@ and @y@ in an unhelpful way.
+ */
+
+void fgoldi_condswap(fgoldi *x, fgoldi *y, uint32 m)
+{
+  unsigned i;
+  mask32 mm = FIX_MASK32(m);
+
+  for (i = 0; i < NPIECE; i++) CONDSWAP(x->P[i], y->P[i], mm);
+}
+
+/*----- Multiplication ----------------------------------------------------*/
+
+/* Let B = 2^63 - 1 be the largest value such that +B and -B can be
+ * represented in a double-precision piece.  On entry, it must be the case
+ * that |X_i| <= M <= B - 2^27 for some M.  If this is the case, then, on
+ * exit, we will have |Z_i| <= 2^27 + M/2^27.
+ */
+#define CARRY_REDUCE(z, x) do {                                                \
+  dblpiece _t[NPIECE], _c;                                             \
+  unsigned _i;                                                         \
+                                                                       \
+  /* Bias the input pieces.  This keeps the carries and so on centred  \
+   * around zero rather than biased positive.                          \
+   */                                                                  \
+  for (_i = 0; _i < NPIECE; _i++) _t[_i] = (x)[_i] + B27;              \
+                                                                       \
+  /* Calculate the reduced pieces.  Careful with the bithacking. */    \
+  _c = ASR(dblpiece, _t[15], 28);                                      \
+  (z)[0] = (dblpiece)((udblpiece)_t[0]&M28) - B27 + _c;                        \
+  for (_i = 1; _i < NPIECE; _i++) {                                    \
+    (z)[_i] = (dblpiece)((udblpiece)_t[_i]&M28) - B27 +                        \
+      ASR(dblpiece, _t[_i - 1], 28);                                   \
+  }                                                                    \
+  (z)[8] += _c;                                                                \
+} while (0)
+
+/* --- @fgoldi_mulconst@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@)
+ *             @const fgoldi *x@ = an operand
+ *             @long a@ = a small-ish constant; %$|a| < 2^{20}$%.
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the product %$a x$%.
+ */
+
+void fgoldi_mulconst(fgoldi *z, const fgoldi *x, long a)
+{
+  unsigned i;
+  dblpiece zz[NPIECE], aa = a;
+
+  for (i = 0; i < NPIECE; i++) zz[i] = aa*x->P[i];
+  CARRY_REDUCE(z->P, zz);
+}
+
+/* --- @fgoldi_mul@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const fgoldi *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the product %$x y$%.
+ */
+
+void fgoldi_mul(fgoldi *z, const fgoldi *x, const fgoldi *y)
+{
+  dblpiece zz[NPIECE], u[NPIECE];
+  piece ab[NPIECE/2], cd[NPIECE/2];
+  const piece
+    *a = x->P + NPIECE/2, *b = x->P,
+    *c = y->P + NPIECE/2, *d = y->P;
+  unsigned i, j;
+
+#  define M(x,i, y,j) ((dblpiece)(x)[i]*(y)[j])
+
+  /* Behold the magic.
+   *
+   * Write x = a Ï† + b, and y = c Ï† + d.  Then x y = a c Ï†^2 +
+   * (a d + b c) Ï† + b d.  Karatsuba and Ofman observed that a d + b c =
+   * (a + b) (c + d) - a c - b d, saving a multiplication, and Hamburg chose
+   * the prime p so that Ï†^2 = Ï† + 1.  So
+   *
+   *   x y = ((a + b) (c + d) - b d) Ï† + a c + b d
+   */
+
+  for (i = 0; i < NPIECE; i++) zz[i] = 0;
+
+  /* Our first job will be to calculate (1 - Ï†) b d, and write the result
+   * into z.  As we do this, an interesting thing will happen.  Write
+   * b d = u Ï† + v; then (1 - Ï†) b d = u Ï† + v - u Ï†^2 - v Ï† = (1 - Ï†) v - u.
+   * So, what we do is to write the product end-swapped and negated, and then
+   * we'll subtract the (negated, remember) high half from the low half.
+   */
+  for (i = 0; i < NPIECE/2; i++) {
+    for (j = 0; j < NPIECE/2 - i; j++)
+      zz[i + j + NPIECE/2] -= M(b,i, d,j);
+    for (; j < NPIECE/2; j++)
+      zz[i + j - NPIECE/2] -= M(b,i, d,j);
+  }
+  for (i = 0; i < NPIECE/2; i++)
+    zz[i] -= zz[i + NPIECE/2];
+
+  /* Next, we add on a c.  There are no surprises here. */
+  for (i = 0; i < NPIECE/2; i++)
+    for (j = 0; j < NPIECE/2; j++)
+      zz[i + j] += M(a,i, c,j);
+
+  /* Now, calculate a + b and c + d. */
+  for (i = 0; i < NPIECE/2; i++)
+    { ab[i] = a[i] + b[i]; cd[i] = c[i] + d[i]; }
+
+  /* Finally (for the multiplication) we must add on (a + b) (c + d) Ï†.
+   * Write (a + b) (c + d) as u Ï† + v; then we actually want u Ï†^2 + v Ï† =
+   * v Ï† + (1 + Ï†) u.  We'll store u in a temporary place and add it on
+   * twice.
+   */
+  for (i = 0; i < NPIECE; i++) u[i] = 0;
+  for (i = 0; i < NPIECE/2; i++) {
+    for (j = 0; j < NPIECE/2 - i; j++)
+      zz[i + j + NPIECE/2] += M(ab,i, cd,j);
+    for (; j < NPIECE/2; j++)
+      u[i + j - NPIECE/2] += M(ab,i, cd,j);
+  }
+  for (i = 0; i < NPIECE/2; i++)
+    { zz[i] += u[i]; zz[i + NPIECE/2] += u[i]; }
+
+#undef M
+
+  /* That wraps it up for the multiplication.  Let's figure out some bounds.
+   * Fortunately, Karatsuba is a polynomial identity, so all of the pieces
+   * end up the way they'd be if we'd done the thing the easy way, which
+   * simplifies the analysis.  Suppose we started with |x_i|, |y_i| <= 9/5
+   * 2^28.  The overheads in the result are given by the coefficients of
+   *
+   *   ((u^16 - 1)/(u - 1))^2 mod u^16 - u^8 - 1
+   *
+   * the greatest of which is 38.  So |z_i| <= 38*81/25*2^56 < 2^63.
+   *
+   * Anyway, a round of `CARRY_REDUCE' will leave us with |z_i| < 2^27 +
+   * 2^36; and a second round will leave us with |z_i| < 2^27 + 512.
+   */
+  for (i = 0; i < 2; i++) CARRY_REDUCE(zz, zz);
+  for (i = 0; i < NPIECE; i++) z->P[i] = zz[i];
+}
+
+/* --- @fgoldi_sqr@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const fgoldi *x@ = an operand
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the square %$x^2$%.
+ */
+
+void fgoldi_sqr(fgoldi *z, const fgoldi *x)
+{
+
+  dblpiece zz[NPIECE], u[NPIECE];
+  piece ab[NPIECE];
+  const piece *a = x->P + NPIECE/2, *b = x->P;
+  unsigned i, j;
+
+#  define M(x,i, y,j) ((dblpiece)(x)[i]*(y)[j])
+
+  /* The magic is basically the same as `fgoldi_mul' above.  We write
+   * x = a Ï† + b and use Karatsuba and the special prime shape.  This time,
+   * we have
+   *
+   *   x^2 = ((a + b)^2 - b^2) Ï† + a^2 + b^2
+   */
+
+  for (i = 0; i < NPIECE; i++) zz[i] = 0;
+
+  /* Our first job will be to calculate (1 - Ï†) b^2, and write the result
+   * into z.  Again, this interacts pleasantly with the prime shape.
+   */
+  for (i = 0; i < NPIECE/4; i++) {
+    zz[2*i + NPIECE/2] -= M(b,i, b,i);
+    for (j = i + 1; j < NPIECE/2 - i; j++)
+      zz[i + j + NPIECE/2] -= 2*M(b,i, b,j);
+    for (; j < NPIECE/2; j++)
+      zz[i + j - NPIECE/2] -= 2*M(b,i, b,j);
+  }
+  for (; i < NPIECE/2; i++) {
+    zz[2*i - NPIECE/2] -= M(b,i, b,i);
+    for (j = i + 1; j < NPIECE/2; j++)
+      zz[i + j - NPIECE/2] -= 2*M(b,i, b,j);
+  }
+  for (i = 0; i < NPIECE/2; i++)
+    zz[i] -= zz[i + NPIECE/2];
+
+  /* Next, we add on a^2.  There are no surprises here. */
+  for (i = 0; i < NPIECE/2; i++) {
+    zz[2*i] += M(a,i, a,i);
+    for (j = i + 1; j < NPIECE/2; j++)
+      zz[i + j] += 2*M(a,i, a,j);
+  }
+
+  /* Now, calculate a + b. */
+  for (i = 0; i < NPIECE/2; i++)
+    ab[i] = a[i] + b[i];
+
+  /* Finally (for the multiplication) we must add on (a + b)^2 Ï†.
+   * Write (a + b)^2 as u Ï† + v; then we actually want (u + v) Ï† + u.  We'll
+   * store u in a temporary place and add it on twice.
+   */
+  for (i = 0; i < NPIECE; i++) u[i] = 0;
+  for (i = 0; i < NPIECE/4; i++) {
+    zz[2*i + NPIECE/2] += M(ab,i, ab,i);
+    for (j = i + 1; j < NPIECE/2 - i; j++)
+      zz[i + j + NPIECE/2] += 2*M(ab,i, ab,j);
+    for (; j < NPIECE/2; j++)
+      u[i + j - NPIECE/2] += 2*M(ab,i, ab,j);
+  }
+  for (; i < NPIECE/2; i++) {
+    u[2*i - NPIECE/2] += M(ab,i, ab,i);
+    for (j = i + 1; j < NPIECE/2; j++)
+      u[i + j - NPIECE/2] += 2*M(ab,i, ab,j);
+  }
+  for (i = 0; i < NPIECE/2; i++)
+    { zz[i] += u[i]; zz[i + NPIECE/2] += u[i]; }
+
+#undef M
+
+  /* Finally, carrying. */
+  for (i = 0; i < 2; i++) CARRY_REDUCE(zz, zz);
+  for (i = 0; i < NPIECE; i++) z->P[i] = zz[i];
+}
+
+/*----- More advanced operations ------------------------------------------*/
+
+/* --- @fgoldi_inv@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@)
+ *             @const fgoldi *x@ = an operand
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores in @z@ the multiplicative inverse %$x^{-1}$%.  If
+ *             %$x = 0$% then @z@ is set to zero.  This is considered a
+ *             feature.
+ */
+
+void fgoldi_inv(fgoldi *z, const fgoldi *x)
+{
+  fgoldi t, u;
+  unsigned i;
+
+#define SQRN(z, x, n) do {                                             \
+  fgoldi_sqr((z), (x));                                                        \
+  for (i = 1; i < (n); i++) fgoldi_sqr((z), (z));                      \
+} while (0)
+
+  /* Calculate x^-1 = x^(p - 2) = x^(2^448 - 2^224 - 3), which also handles
+   * x = 0 as intended.  The addition chain is home-made.
+   */                                  /* step | value */
+  fgoldi_sqr(&u, x);                   /*    1 | 2 */
+  fgoldi_mul(&t, &u, x);               /*    2 | 3 */
+  SQRN(&u, &t, 2);                     /*    4 | 12 */
+  fgoldi_mul(&t, &u, &t);              /*    5 | 15 */
+  SQRN(&u, &t, 4);                     /*    9 | 240 */
+  fgoldi_mul(&u, &u, &t);              /*   10 | 255 = 2^8 - 1 */
+  SQRN(&u, &u, 4);                     /*   14 | 2^12 - 16 */
+  fgoldi_mul(&t, &u, &t);              /*   15 | 2^12 - 1 */
+  SQRN(&u, &t, 12);                    /*   27 | 2^24 - 2^12 */
+  fgoldi_mul(&u, &u, &t);              /*   28 | 2^24 - 1 */
+  SQRN(&u, &u, 12);                    /*   40 | 2^36 - 2^12 */
+  fgoldi_mul(&t, &u, &t);              /*   41 | 2^36 - 1 */
+  fgoldi_sqr(&t, &t);                  /*   42 | 2^37 - 2 */
+  fgoldi_mul(&t, &t, x);               /*   43 | 2^37 - 1 */
+  SQRN(&u, &t, 37);                    /*   80 | 2^74 - 2^37 */
+  fgoldi_mul(&u, &u, &t);              /*   81 | 2^74 - 1 */
+  SQRN(&u, &u, 37);                    /*  118 | 2^111 - 2^37 */
+  fgoldi_mul(&t, &u, &t);              /*  119 | 2^111 - 1 */
+  SQRN(&u, &t, 111);                   /*  230 | 2^222 - 2^111 */
+  fgoldi_mul(&t, &u, &t);              /*  231 | 2^222 - 1 */
+  fgoldi_sqr(&u, &t);                  /*  232 | 2^223 - 2 */
+  fgoldi_mul(&u, &u, x);               /*  233 | 2^223 - 1 */
+  SQRN(&u, &u, 223);                   /*  456 | 2^446 - 2^223 */
+  fgoldi_mul(&t, &u, &t);              /*  457 | 2^446 - 2^222 - 1 */
+  SQRN(&t, &t, 2);                     /*  459 | 2^448 - 2^224 - 4 */
+  fgoldi_mul(z, &t, x);                        /*  460 | 2^448 - 2^224 - 3 */
+
+#undef SQRN
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/fgoldi.h b/fgoldi.h
new file mode 100644 (file)
index 0000000..cac2ff1
--- /dev/null
+++ b/fgoldi.h
@@ -0,0 +1,212 @@
+/* -*-c-*-
+ *
+ * Arithmetic in the Goldilocks field GF(2^448 - 2^224 - 1)
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of secnet.
+ * See README for full list of copyright holders.
+ *
+ * secnet is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version d of the License, or
+ * (at your option) any later version.
+ *
+ * secnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with secnet; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ *
+ * This file was originally part of Catacomb, but has been automatically
+ * modified for incorporation into secnet: see `import-catacomb-crypto'
+ * for details.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef CATACOMB_FGOLDI_H
+#define CATACOMB_FGOLDI_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "fake-mLib-bits.h"
+
+#ifndef CATACOMB_QFARITH_H
+#  include "qfarith.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef union {
+  int32 p28[16];
+} fgoldi;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @fgoldi_load@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to store the result
+ *             @const octet xv[56]@ = source to read
+ *
+ * Returns:    ---
+ *
+ * Use:                Reads an element of %$\gf{2^{448} - 2^{224} - 19}$% in
+ *             external representation from @xv@ and stores it in @z@.
+ *
+ *             External representation is little-endian base-256.  Some
+ *             elements have multiple encodings, which are not produced by
+ *             correct software; use of noncanonical encodings is not an
+ *             error, and toleration of them is considered a performance
+ *             feature.
+ */
+
+extern void fgoldi_load(fgoldi */*z*/, const octet /*xv*/[56]);
+
+/* --- @fgoldi_store@ --- *
+ *
+ * Arguments:  @octet zv[56]@ = where to write the result
+ *             @const fgoldi *x@ = the field element to write
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores a field element in the given octet vector in external
+ *             representation.  A canonical encoding is always stored.
+ */
+
+extern void fgoldi_store(octet /*zv*/[56], const fgoldi */*x*/);
+
+/* --- @fgoldi_set@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to write the result
+ *             @int a@ = a small-ish constant
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets @z@ to equal @a@.
+ */
+
+extern void fgoldi_set(fgoldi */*x*/, int /*a*/);
+
+/* --- @fgoldi_add@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const fgoldi *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the sum %$x + y$%.
+ */
+
+extern void fgoldi_add(fgoldi */*z*/,
+                      const fgoldi */*x*/, const fgoldi */*y*/);
+
+/* --- @fgoldi_sub@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const fgoldi *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the difference %$x - y$%.
+ */
+
+extern void fgoldi_sub(fgoldi */*z*/,
+                      const fgoldi */*x*/, const fgoldi */*y*/);
+
+/* --- @fgoldi_condswap@ --- *
+ *
+ * Arguments:  @fgoldi *x, *y@ = two operands
+ *             @uint32 m@ = a mask
+ *
+ * Returns:    ---
+ *
+ * Use:                If @m@ is zero, do nothing; if @m@ is all-bits-set, then
+ *             exchange @x@ and @y@.  If @m@ has some other value, then
+ *             scramble @x@ and @y@ in an unhelpful way.
+ */
+
+extern void fgoldi_condswap(fgoldi */*x*/, fgoldi */*y*/, uint32 /*m*/);
+
+/* --- @fgoldi_mulconst@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@)
+ *             @const fgoldi *x@ = an operand
+ *             @long a@ = a small-ish constant; %$|a| < 2^{20}$%.
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the product %$a x$%.
+ */
+
+extern void fgoldi_mulconst(fgoldi */*z*/, const fgoldi */*x*/, long /*a*/);
+
+/* --- @fgoldi_mul@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const fgoldi *x, *y@ = two operands
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the product %$x y$%.
+ */
+
+extern void fgoldi_mul(fgoldi */*z*/,
+                      const fgoldi */*x*/, const fgoldi */*y*/);
+
+/* --- @fgoldi_sqr@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@ or @y@)
+ *             @const fgoldi *x@ = an operand
+ *
+ * Returns:    ---
+ *
+ * Use:                Set @z@ to the square %$x^2$%.
+ */
+
+extern void fgoldi_sqr(fgoldi */*z*/, const fgoldi */*x*/);
+
+/* --- @fgoldi_inv@ --- *
+ *
+ * Arguments:  @fgoldi *z@ = where to put the result (may alias @x@)
+ *             @const fgoldi *x@ = an operand
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores in @z@ the multiplicative inverse %$x^{-1}$%.  If
+ *             %$x = 0$% then @z@ is set to zero.  This is considered a
+ *             feature.
+ */
+
+extern void fgoldi_inv(fgoldi */*z*/, const fgoldi */*x*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/montladder.h b/montladder.h
new file mode 100644 (file)
index 0000000..bcd3539
--- /dev/null
@@ -0,0 +1,162 @@
+/* -*-c-*-
+ *
+ * Definitions for Montgomery's ladder
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of secnet.
+ * See README for full list of copyright holders.
+ *
+ * secnet is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version d of the License, or
+ * (at your option) any later version.
+ *
+ * secnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with secnet; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ *
+ * This file was originally part of Catacomb, but has been automatically
+ * modified for incorporation into secnet: see `import-catacomb-crypto'
+ * for details.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef CATACOMB_MONTLADDER_H
+#define CATACOMB_MONTLADDER_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Notes on the Montgomery ladder ------------------------------------*
+ *
+ * The algorithm here is Montgomery's famous binary ladder for calculating
+ * x-coordinates of scalar products on a particular shape of elliptic curve,
+ * as elucidated by Daniel Bernstein.
+ *
+ * Let Q = (x_1, y_1) be the base point, for some unknown y_1 (which will
+ * turn out to be unimportant).  Define x_n, z_n by x(n Q) = (x_n : z_n).
+ * Given x_n, z_n, x_{n+1}, z_{n+1}, Montgomery's differential addition
+ * formulae calculate x_{2i}, z_{2i}, x_{2i+1}, z_{2i+1}.  Furthermore,
+ * calculating x_{2i}, z_{2i} requires only x_n, z_n, and the calculation of
+ * x_{2i+1}, z_{2i+1} is symmetrical.
+ */
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* F designates a field, both naming the type of its elements and acting as a
+ * prefix for the standard field operations `F_add', `F_sub', `F_mul',
+ * `F_sqr', and `F_inv' (the last of which should return zero its own
+ * inverse); and the constant-time utility `F_condswap'.
+ *
+ * The macro calculates the x-coordinate of the product k Q, where Q is a
+ * point on the elliptic curve B y^2 = x^3 + A x^2 + x or its quadratic
+ * twist, for some irrelevant B.  The x-coordinate of Q is given as X1 (a
+ * pointer to a field element).  The scalar k is given as a vector of NK
+ * unsigned integers KW, each containing NBITS significant bits, with the
+ * least-significant element first.  The result is written to the field
+ * element pointed to by Z.
+ *
+ * The curve coefficient A is given indirectly, as the name of a macro MULA0
+ * such that
+ *
+ *     MULA0(z, x)
+ *
+ * will store in z the value (A - 2)/4 x.
+ */
+#define MONT_LADDER(f, mula0, kw, nk, nbits, z, x1) do {               \
+  f _x, _z, _u, _w;                                                    \
+  f _t0, _t1, _t2, _t3, _t4;                                           \
+  uint32 _m = 0, _mm = 0, _k;                                          \
+  unsigned _i, _j;                                                     \
+                                                                       \
+  /* Initialize the main variables.  We'll have, (x, z) and (u, w)     \
+   * holding (x_n, z_n) and (x_{n+1}, z_{n+1}) in some order, but      \
+   * there's some weirdness: if m = 0 then (x, z) = (x_n, z_n) and     \
+   * (u, v) = (x_{n+1}, z_{n+1}); if m /= 0, then the pairs are                \
+   * swapped over.                                                     \
+   *                                                                   \
+   * Initially, we have (x_0, z_0) = (1, 0), representing the identity \
+   * at projective-infinity, which works fine; and we have z_1 = 1.    \
+   */                                                                  \
+  _u = *(x1); f##_set(&_w, 1); f##_set(&_x, 1); f##_set(&_z, 0);       \
+                                                                       \
+  /* The main ladder loop.  Work through each bit of the clamped key. */ \
+  for (_i = (nk); _i--; ) {                                            \
+    _k = (kw)[_i];                                                     \
+    for (_j = 0; _j < (nbits); _j++) {                                 \
+      /* We're at bit i of the scalar key (represented by 32 (7 - i) + \
+       * (31 - j) in our loop variables -- don't worry about that).    \
+       * Let k = 2^i k_i + k'_i, with 0 <= k'_i < 2^i.  In particular, \
+       * then, k_0 = k.  Write Q(i) = (x_i, z_i).                      \
+       *                                                               \
+       * We currently have, in (x, z) and (u, w), Q(k_i) and Q(k_i +   \
+       * 1), in some order.  The ladder step will double the point in  \
+       * (x, z), and leave the sum of (x : z) and (u : w) in (u, w).   \
+       */                                                              \
+                                                                       \
+      _mm = -((_k >> ((nbits) - 1))&1u); _k <<= 1;                     \
+      f##_condswap(&_x, &_u, _m ^ _mm);                                        \
+      f##_condswap(&_z, &_w, _m ^ _mm);                                        \
+      _m = _mm;                                                                \
+                                                                       \
+      f##_add(&_t0, &_x, &_z);         /* x + z */                     \
+      f##_sub(&_t1, &_x, &_z);         /* x - z */                     \
+      f##_add(&_t2, &_u, &_w);         /* u + w */                     \
+      f##_sub(&_t3, &_u, &_w);         /* u - w */                     \
+      f##_mul(&_t2, &_t2, &_t1);       /* (x - z) (u + w) */           \
+      f##_mul(&_t3, &_t3, &_t0);       /* (x + z) (u - w) */           \
+      f##_sqr(&_t0, &_t0);             /* (x + z)^2 */                 \
+      f##_sqr(&_t1, &_t1);             /* (x - z)^2 */                 \
+      f##_mul(&_x, &_t0, &_t1);                /* (x + z)^2 (x - z)^2 */       \
+      f##_sub(&_t1, &_t0, &_t1);       /* (x + z)^2 - (x - z)^2 */     \
+      mula0(&_t4, &_t1);            /* A_0 ((x + z)^2 - (x - z)^2) */  \
+      f##_add(&_t0, &_t0, &_t4);       /* A_0 ... + (x + z)^2 */       \
+      f##_mul(&_z, &_t0, &_t1);         /* (...^2 - ...^2) (A_0 ... + ...) */  \
+      f##_add(&_t0, &_t2, &_t3); /* (x - z) (u + w) + (x + z) (u - w) */ \
+      f##_sub(&_t1, &_t2, &_t3); /* (x - z) (u + w) - (x + z) (u - w) */ \
+      f##_sqr(&_u, &_t0);              /* (... + ...)^2 */             \
+      f##_sqr(&_t1, &_t1);             /* (... - ...)^2 */             \
+      f##_mul(&_w, &_t1, (x1));                /* x_1 (... - ...)^2 */         \
+    }                                                                  \
+  }                                                                    \
+                                                                       \
+  /* Almost done.  Undo the swap, if any. */                           \
+  f##_condswap(&_x, &_u, _m);                                          \
+  f##_condswap(&_z, &_w, _m);                                          \
+                                                                       \
+  /* And convert to affine. */                                         \
+  f##_inv(&_t0, &_z);                                                  \
+  f##_mul((z), &_x, &_t0);                                             \
+} while (0)
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/qfarith.h b/qfarith.h
new file mode 100644 (file)
index 0000000..f41aa95
--- /dev/null
+++ b/qfarith.h
@@ -0,0 +1,187 @@
+/* -*-c-*-
+ *
+ * Utilities for quick field arithmetic
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of secnet.
+ * See README for full list of copyright holders.
+ *
+ * secnet is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version d of the License, or
+ * (at your option) any later version.
+ *
+ * secnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with secnet; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ *
+ * This file was originally part of Catacomb, but has been automatically
+ * modified for incorporation into secnet: see `import-catacomb-crypto'
+ * for details.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef CATACOMB_QFARITH_H
+#define CATACOMB_QFARITH_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <limits.h>
+
+#include "fake-mLib-bits.h"
+/*----- Signed integer types ----------------------------------------------*/
+
+typedef int32_t int32;
+typedef int64_t int64;
+#define HAVE_INT64 1
+
+/*----- General bit-hacking utilities -------------------------------------*/
+
+/* Individual bits, and masks for low bits. */
+#define BIT(n) (1ul << (n))
+#define MASK(n) (BIT(n) - 1)
+
+/* Arithmetic right shift.  If X is a value of type TY, and N is a
+ * nonnegative integer, then return the value of X shifted right by N bits;
+ * alternatively, this is floor(X/2^N).
+ *
+ * GCC manages to compile this into a simple shift operation if one is
+ * available, but it's correct for all C targets.
+ */
+#define ASR(ty, x, n) (((x) - (ty)((u##ty)(x)&MASK(n)))/(ty)BIT(n))
+
+/*----- Constant-time utilities -------------------------------------------*/
+
+/* The following have better implementations on a two's complement target. */
+
+/* If we have two's complement arithmetic then masks are signed; this
+ * avoids a switch to unsigned representation, with the consequent problem
+ * of overflow when we convert back.
+ */
+typedef int32 mask32;
+
+/* Convert an unsigned mask M into a `mask32'.  This is a hairy-looking
+ * no-op on many targets, but, given that we have two's complement
+ * integers, it is free of arithmetic overflow.
+ */
+#define FIX_MASK32(m) \
+  ((mask32)((m)&0x7fffffffu) + (-(mask32)0x7fffffff - 1)*(((m) >> 31)&1u))
+
+/* If Z is zero and M has its low 32 bits set, then copy (at least) the low
+ * 32 bits of X to Z; if M is zero, do nothing.  Otherwise, scramble Z
+ * unhelpfully.
+ */
+#define CONDPICK(z, x, m) do { (z) |= (x)&(m); } while (0)
+
+/* If M has its low 32 bits set, then return (at least) the low 32 bits of
+ * X in Z; if M is zero, then return (at least) the low 32 bits of Y in Z.
+ * Otherwise, return an unhelful result.
+ */
+#define PICK2(x, y, m) (((x)&(m)) | ((y)&~(m)))
+
+/* If M has its low 32 bits set then swap (at least) the low 32 bits of X
+ * and Y; if M is zero, then do nothing.  Otherwise, scramble X and Y
+ * unhelpfully.
+ */
+#define CONDSWAP(x, y, m)                                              \
+  do { mask32 t_ = ((x) ^ (y))&(m); (x) ^= t_; (y) ^= t_; } while (0)
+
+/* Return zero if bit 31 of X is clear, or a mask with (at least) the low 32
+ * bits set if bit 31 of X is set.
+ */
+#define SIGN(x) (-(mask32)(((uint32)(x) >> 31)&1))
+
+/* Return zero if X is zero, or a mask with (at least) the low 32 bits set if
+ * X is nonzero.
+ */
+#define NONZEROP(x) SIGN((U32(x) >> 1) - U32(x))
+
+/*----- Debugging utilities -----------------------------------------------*/
+
+/* Define a debugging function DUMPFN, which will dump an integer represented
+ * modulo M.  The integer is represented as a vector of NPIECE pieces of type
+ * PIECETY.  The pieces are assembled at possibly irregular offsets: piece i
+ * logically has width PIECEWD(i), but may overhang the next piece.  The
+ * pieces may be signed.  GETMOD is an expression which calculates and
+ * returns the value of M, as an `mp *'.
+ *
+ * The generated function writes the value of such an integer X to the stream
+ * FP, labelled with the string WHAT.
+ *
+ * The definition assumes that <stdio.h>, <catacomb/mp.h>, and
+ * <catacomb/mptext.h> have been included.
+ */
+#define DEF_FDUMP(dumpfn, piecety, piecewd, npiece, noctet, getmod)    \
+  static void dumpfn(FILE *fp, const char *what, const piecety *x)     \
+  {                                                                    \
+    mpw w;                                                             \
+    mp m, *y = MP_ZERO, *t = MP_NEW, *p;                               \
+    octet b[noctet];                                                   \
+    unsigned i, o;                                                     \
+                                                                       \
+    p = getmod;                                                                \
+    mp_build(&m, &w, &w + 1);                                          \
+    for (i = o = 0; i < npiece; i++) {                                 \
+      if (x[i] >= 0) { w = x[i]; m.f &= ~MP_NEG; }                     \
+      else { w = -x[i]; m.f |= MP_NEG; }                               \
+      t = mp_lsl(t, &m, o);                                            \
+      y = mp_add(y, y, t);                                             \
+      o += piecewd(i);                                                 \
+    }                                                                  \
+                                                                       \
+    fprintf(fp, "%s = <", what);                                       \
+    for (i = 0; i < npiece; i++) {                                     \
+      if (i) fputs(", ", fp);                                          \
+      fprintf(fp, "%ld", (long)x[i]);                                  \
+    }                                                                  \
+    fputs(">\n\t= ", fp);                                              \
+    mp_writefile(y, fp, 10);                                           \
+    fputs("\n\t== ", fp);                                              \
+    mp_div(0, &y, y, p);                                               \
+    mp_writefile(y, fp, 10);                                           \
+    fputs("\n\t= 0x", fp);                                             \
+    mp_writefile(y, fp, 16);                                           \
+    fputs(" (mod 2^255 - 19)\n\t= [", fp);                             \
+    mp_storel(y, b, sizeof(b));                                                \
+    for (i = 0; i < 32; i++) {                                         \
+      if (i && !(i%4)) fputc(':', fp);                                 \
+      fprintf(fp, "%02x", b[i]);                                       \
+    }                                                                  \
+    fputs("]\n", fp);                                                  \
+    mp_drop(y); mp_drop(p); mp_drop(t);                                        \
+  }
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/x25519-tests.in b/x25519-tests.in
new file mode 100644 (file)
index 0000000..a2d6263
--- /dev/null
@@ -0,0 +1,56 @@
+### Tests for X25519.                                          -*-conf-*-
+### Extracted from Catacomb.
+
+###--------------------------------------------------------------------------
+test x25519
+
+## These are from Daniel J. Bernstein, `Cryptography in NaCl', 2009-03-10,
+## https://cr.yp.to/highspeed/naclcrypto-20090310.pdf
+## Make Alice's public key.
+x 77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a
+Y 0900000000000000000000000000000000000000000000000000000000000000
+Z 8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a
+
+## Make Bob's public key.
+x 5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb
+Y 0900000000000000000000000000000000000000000000000000000000000000
+Z de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f
+
+## Make the shared secret using Alice's private key.
+x 77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a
+Y de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f
+Z 4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742
+
+## Make the (same) shared secret using Bob's private key.
+x 5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb
+Y 8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a
+Z 4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742
+
+## These tests are from RFC7748.  I've clamped the public values because
+## RFC7748 wants the top bits ignored.
+x a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4
+Y e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c
+Z c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552
+
+x 4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d
+Y e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a413
+Z 95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957
+
+###--------------------------------------------------------------------------
+test x25519-mct
+
+## These tests are from RFC7748.
+x 0900000000000000000000000000000000000000000000000000000000000000
+Y 0900000000000000000000000000000000000000000000000000000000000000
+n 1
+Z 422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079
+
+x 0900000000000000000000000000000000000000000000000000000000000000
+Y 0900000000000000000000000000000000000000000000000000000000000000
+n 1000
+Z 684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51
+
+## This one takes aaaaages.
+## 0900000000000000000000000000000000000000000000000000000000000000
+## 0900000000000000000000000000000000000000000000000000000000000000
+## 1000000 7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424;
diff --git a/x25519.c b/x25519.c
new file mode 100644 (file)
index 0000000..85c1187
--- /dev/null
+++ b/x25519.c
@@ -0,0 +1,108 @@
+/* -*-c-*-
+ *
+ * The X25519 key-agreement algorithm
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of secnet.
+ * See README for full list of copyright holders.
+ *
+ * secnet is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version d of the License, or
+ * (at your option) any later version.
+ *
+ * secnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with secnet; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ *
+ * This file was originally part of Catacomb, but has been automatically
+ * modified for incorporation into secnet: see `import-catacomb-crypto'
+ * for details.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "fake-mLib-bits.h"
+
+#include "montladder.h"
+#include "f25519.h"
+#include "x25519.h"
+
+/*----- Important constants -----------------------------------------------*/
+
+const octet x25519_base[32] = { 9, 0, /* ... */ };
+
+#define A0 121665
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @x25519@ --- *
+ *
+ * Arguments:  @octet zz[X25519_OUTSZ]@ = where to put the result
+ *             @const octet k[X25519_KEYSZ]@ = pointer to private key
+ *             @const octet qx[X25519_PUBSZ]@ = pointer to public value
+ *
+ * Returns:    ---
+ *
+ * Use:                Calculates X25519 of @k@ and @qx@.
+ *
+ *             Note that there is disagreement over whether the most
+ *             significant bit of @qx@ (i.e., the value @qx[31]&0x80@)
+ *             should be ignored or counted towards the represented value.
+ *             Historically implementations respected the bit; later
+ *             convention seems to be to ignore it.  This implementation
+ *             honours the bit: a caller who wants to ignore the bit can
+ *             easily clear it, while caller who wants to respect it has a
+ *             difficult job if this function ignores it.
+ */
+
+void x25519(octet zz[X25519_OUTSZ],
+           const octet k[X25519_KEYSZ],
+           const octet qx[X25519_PUBSZ])
+{
+  uint32 kw[8];
+  f25519 x1;
+
+  /* Load and clamp the key.  The low bits are cleared to kill the small
+   * subgroups on the curve and its twist, and a high bit is set to guard
+   * against careless implementations, though this isn't one of those.
+   */
+  kw[0] = LOAD32_L(k +  0); kw[1] = LOAD32_L(k +  4);
+  kw[2] = LOAD32_L(k +  8); kw[3] = LOAD32_L(k + 12);
+  kw[4] = LOAD32_L(k + 16); kw[5] = LOAD32_L(k + 20);
+  kw[6] = LOAD32_L(k + 24); kw[7] = LOAD32_L(k + 28);
+  kw[0] &= 0xfffffff8; kw[7] = (kw[7]&0x3fffffff) | 0x40000000;
+
+  /* And run the ladder. */
+  f25519_load(&x1, qx);
+#define MULA0(z, x) do { f25519_mulconst((z), (x), A0); } while (0)
+  MONT_LADDER(f25519, MULA0, kw, 8, 32, &x1, &x1);
+#undef MULA0
+  f25519_store(zz, &x1);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/x25519.h b/x25519.h
new file mode 100644 (file)
index 0000000..422d161
--- /dev/null
+++ b/x25519.h
@@ -0,0 +1,109 @@
+/* -*-c-*-
+ *
+ * The X25519 key-agreement algorithm
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of secnet.
+ * See README for full list of copyright holders.
+ *
+ * secnet is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version d of the License, or
+ * (at your option) any later version.
+ *
+ * secnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with secnet; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ *
+ * This file was originally part of Catacomb, but has been automatically
+ * modified for incorporation into secnet: see `import-catacomb-crypto'
+ * for details.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef CATACOMB_X25519_H
+#define CATACOMB_X25519_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Notes on the X25519 key-agreement algorithm -----------------------*
+ *
+ * This is X25519, as described in Daniel J. Bernstein, `Curve25519: new
+ * Diffie--Hellman speed records', PKC 2006,
+ * https://cr.yp.to/ecdh/curve25519-20060209.pdf
+ *
+ * Since then, the name `Curve25519' has shifted somewhat, to refer to the
+ * specific elliptic curve used, and the x-coordinate Diffie--Hellman
+ * operation is now named `X25519'.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "fake-mLib-bits.h"
+
+/*----- Important constants -----------------------------------------------*/
+
+#define X25519_KEYSZ 32u
+#define X25519_PUBSZ 32u
+#define X25519_OUTSZ 32u
+
+extern const octet x25519_base[32];
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @x25519@ --- *
+ *
+ * Arguments:  @octet zz[X25519_OUTSZ]@ = where to put the result
+ *             @const octet k[X25519_KEYSZ]@ = pointer to private key
+ *             @const octet qx[X25519_PUBSZ]@ = pointer to public value
+ *
+ * Returns:    ---
+ *
+ * Use:                Calculates X25519 of @k@ and @qx@.
+ *
+ *             Note that there is disagreement over whether the most
+ *             significant bit of @qx@ (i.e., the value @qx[31]&0x80@)
+ *             should be ignored or counted towards the represented value.
+ *             Historically implementations respected the bit; later
+ *             convention seems to be to ignore it.  This implementation
+ *             honours the bit: a caller who wants to ignore the bit can
+ *             easily clear it, while caller who wants to respect it has a
+ *             difficult job if this function ignores it.
+ */
+
+extern void x25519(octet /*zz*/[X25519_OUTSZ],
+                  const octet /*k*/[X25519_KEYSZ],
+                  const octet /*qx*/[X25519_PUBSZ]);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/x448-tests.in b/x448-tests.in
new file mode 100644 (file)
index 0000000..f6efcee
--- /dev/null
@@ -0,0 +1,49 @@
+### Tests for X448.                                            -*-conf-*-
+### Extracted from Catacomb.
+
+###--------------------------------------------------------------------------
+test x448
+
+## These are taken from RFC7748.
+x 3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3
+Y 06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086
+Z ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f
+
+x 203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f
+Y 0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db
+Z 884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d
+
+x 9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b
+Y 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Z 9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0
+
+x 1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d
+Y 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Z 3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609
+
+x 9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b
+Y 3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609
+Z 07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d
+
+x 1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d
+Y 9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0
+Z 07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d
+
+###--------------------------------------------------------------------------
+test x448-mct
+
+## These are taken from RFC7748.
+x 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Y 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+n 1
+Z 3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113
+
+x 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Y 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+n 1000
+Z aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38
+
+## This one takes aaaaages.
+## 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+## 0500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+## 1000000 077f453681caca3693198420bbe515cae0002472519b3e67661a7e89cab94695c8f4bcd66e61b9b9c946da8d524de3d69bd9d9d66b997e37;
diff --git a/x448.c b/x448.c
new file mode 100644 (file)
index 0000000..332ff7b
--- /dev/null
+++ b/x448.c
@@ -0,0 +1,97 @@
+/* -*-c-*-
+ *
+ * The X448 key-agreement algorithm
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of secnet.
+ * See README for full list of copyright holders.
+ *
+ * secnet is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version d of the License, or
+ * (at your option) any later version.
+ *
+ * secnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with secnet; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ *
+ * This file was originally part of Catacomb, but has been automatically
+ * modified for incorporation into secnet: see `import-catacomb-crypto'
+ * for details.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "fake-mLib-bits.h"
+
+#include "montladder.h"
+#include "fgoldi.h"
+#include "x448.h"
+
+/*----- Important constants -----------------------------------------------*/
+
+const octet x448_base[56] = { 5, 0, /* ... */ };
+
+#define A0 39081
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @x448@ --- *
+ *
+ * Arguments:  @octet zz[X448_OUTSZ]@ = where to put the result
+ *             @const octet k[X448_KEYSZ]@ = pointer to private key
+ *             @const octet qx[X448_PUBSZ]@ = pointer to public value
+ *
+ * Returns:    ---
+ *
+ * Use:                Calculates X448 of @k@ and @qx@.
+ */
+
+void x448(octet zz[X448_OUTSZ],
+         const octet k[X448_KEYSZ],
+         const octet qx[X448_PUBSZ])
+{
+  uint32 kw[14];
+  fgoldi x1;
+  unsigned i;
+
+  /* Load and clamp the key.  The low bits are cleared to kill the small
+   * subgroups on the curve and its twist, and a high bit is set to guard
+   * against careless implementations, though this isn't one of those.
+   */
+  for (i = 0; i < 14; i++) kw[i] = LOAD32_L(k + 4*i);
+  kw[0] &= 0xfffffffc; kw[13] |= 0x80000000;
+
+  /* And run the ladder. */
+  fgoldi_load(&x1, qx);
+#define MULA0(z, x) do { fgoldi_mulconst((z), (x), A0); } while (0)
+  MONT_LADDER(fgoldi, MULA0, kw, 14, 32, &x1, &x1);
+#undef MULA0
+  fgoldi_store(zz, &x1);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/x448.h b/x448.h
new file mode 100644 (file)
index 0000000..401f4e2
--- /dev/null
+++ b/x448.h
@@ -0,0 +1,101 @@
+/* -*-c-*-
+ *
+ * The X448 key-agreement algorithm
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of secnet.
+ * See README for full list of copyright holders.
+ *
+ * secnet is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version d of the License, or
+ * (at your option) any later version.
+ *
+ * secnet is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with secnet; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ *
+ * This file was originally part of Catacomb, but has been automatically
+ * modified for incorporation into secnet: see `import-catacomb-crypto'
+ * for details.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef CATACOMB_X448_H
+#define CATACOMB_X448_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Notes on the X448 key-agreement algorithm -------------------------*
+ *
+ * This is X448, as described in RFC7748, based on the elliptic curve defined
+ * in Mike Hamburg, `Ed448-Goldilocks, a new elliptic curve', EUROCRYPT 2016,
+ * https://eprint.iacr.org/2015/625/.
+ *
+ * The RFC-specified operation is simpler than the Diffie--Hellman function
+ * described in Hamburg's paper, since it doesn't involve the `Decaf'
+ * cofactor elimination procedure.  Indeed, it looks very much like X25519
+ * with Hamburg's curve slotted in in place of Bernstein's.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "fake-mLib-bits.h"
+
+/*----- Important constants -----------------------------------------------*/
+
+#define X448_KEYSZ 56
+#define X448_PUBSZ 56
+#define X448_OUTSZ 56
+
+extern const octet x448_base[56];
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @x448@ --- *
+ *
+ * Arguments:  @octet zz[X448_OUTSZ]@ = where to put the result
+ *             @const octet k[X448_KEYSZ]@ = pointer to private key
+ *             @const octet qx[X448_PUBSZ]@ = pointer to public value
+ *
+ * Returns:    ---
+ *
+ * Use:                Calculates X448 of @k@ and @qx@.
+ */
+
+extern void x448(octet /*zz*/[X448_OUTSZ],
+                const octet /*k*/[X448_KEYSZ],
+                const octet /*qx*/[X448_PUBSZ]);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif