uint-0.10.0/.cargo_vcs_info.json0000644000000001420000000000100120660ustar { "git": { "sha1": "63c5afbf8e0e903439d3c127c59b0e4a7991000b" }, "path_in_vcs": "uint" }uint-0.10.0/CHANGELOG.md000064400000000000000000000052241046102023000124750ustar 00000000000000# Changelog The format is based on [Keep a Changelog]. [Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ ## [Unreleased] ## [0.10.0] - 2024-09-11 - Removed From<[u8; n]> conversions, renamed `to_big_endian` / `to_little_endian` to write_as_*, and made them return byte arrays. [#859](https://github.com/paritytech/parity-common/pull/859) ## [0.9.5] - 2022-11-29 - Implemented bitwise assign traits. [#690](https://github.com/paritytech/parity-common/pull/690) ## [0.9.4] - 2022-09-20 - Made `one` const. [#650](https://github.com/paritytech/parity-common/pull/650) - Made `max_value` const. [#652](https://github.com/paritytech/parity-common/pull/652) - Made `is_zero` const. [#639](https://github.com/paritytech/parity-common/pull/639) - Added `abs_diff`. [#665](https://github.com/paritytech/parity-common/pull/665) ## [0.9.3] - 2022-02-04 - Simplified and faster `div_mod`. [#478](https://github.com/paritytech/parity-common/pull/478) - Fixed `overflowing_neg`. [#611](https://github.com/paritytech/parity-common/pull/611) ## [0.9.2] - 2022-01-28 - Migrated to 2021 edition, enforcing MSRV of `1.56.1`. [#601](https://github.com/paritytech/parity-common/pull/601) - Display formatting support. [#603](ttps://github.com/paritytech/parity-common/pull/603) ## [0.9.1] - 2021-06-30 - Added `integer_sqrt` method. [#554](https://github.com/paritytech/parity-common/pull/554) ## [0.9.0] - 2021-01-05 - Allow `0x` prefix in `from_str`. [#487](https://github.com/paritytech/parity-common/pull/487) ### Breaking - Optimized FromStr, made it no_std-compatible. [#468](https://github.com/paritytech/parity-common/pull/468) ## [0.8.5] - 2020-08-12 - Make const matching work again. [#421](https://github.com/paritytech/parity-common/pull/421) ## [0.8.4] - 2020-08-03 - Added a manual impl of `Eq` and `Hash`. [#390](https://github.com/paritytech/parity-common/pull/390) - Removed some unsafe code and added big-endian support. [#407](https://github.com/paritytech/parity-common/pull/407) - Added `checked_pow`. [#417](https://github.com/paritytech/parity-common/pull/417) ## [0.8.3] - 2020-04-27 - Added `arbitrary` feature. [#378](https://github.com/paritytech/parity-common/pull/378) - Fixed UB in `from_big_endian`. [#381](https://github.com/paritytech/parity-common/pull/381) ## [0.8.2] - 2019-10-24 ### Fixed - Fixed 2018 edition imports. [#237](https://github.com/paritytech/parity-common/pull/237) - Removed `uninitialized` usage. [#238](https://github.com/paritytech/parity-common/pull/238) ### Dependencies - Updated dependencies. [#239](https://github.com/paritytech/parity-common/pull/239) ### Changed - Modified AsRef impl. [#196](https://github.com/paritytech/parity-common/pull/196) uint-0.10.0/Cargo.lock0000644000000570110000000000100100500ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] [[package]] name = "anes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstyle" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" [[package]] name = "arbitrary" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e90af4de65aa7b293ef2d09daff88501eb254f58edde2e1ac02c82d873eadad" [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "az" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" [[package]] name = "bitflags" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "bumpalo" version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "ciborium" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" dependencies = [ "ciborium-io", "ciborium-ll", "serde", ] [[package]] name = "ciborium-io" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" [[package]] name = "ciborium-ll" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" dependencies = [ "ciborium-io", "half", ] [[package]] name = "clap" version = "4.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84ed82781cea27b43c9b106a979fe450a13a31aab0500595fb3fc06616de08e6" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" dependencies = [ "anstyle", "clap_lex", ] [[package]] name = "clap_lex" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "criterion" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" dependencies = [ "anes", "cast", "ciborium", "clap", "criterion-plot", "is-terminal", "itertools", "num-traits", "once_cell", "oorandom", "plotters", "rayon", "regex", "serde", "serde_derive", "serde_json", "tinytemplate", "walkdir", ] [[package]] name = "criterion-plot" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", "itertools", ] [[package]] name = "crossbeam-deque" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", "memoffset", "scopeguard", ] [[package]] name = "crossbeam-utils" version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if", ] [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "either" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "env_logger" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ "log", "regex", ] [[package]] name = "errno" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" dependencies = [ "errno-dragonfly", "libc", "windows-sys 0.48.0", ] [[package]] name = "errno-dragonfly" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" dependencies = [ "cc", "libc", ] [[package]] name = "getrandom" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", "wasi", ] [[package]] name = "gmp-mpfr-sys" version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0205cd82059bc63b63cf516d714352a30c44f2c74da9961dfda2617ae6b5918" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] name = "half" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hermit-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "is-terminal" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", "rustix", "windows-sys 0.48.0", ] [[package]] name = "itertools" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "js-sys" version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] [[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libm" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "linux-raw-sys" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" [[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ "autocfg", ] [[package]] name = "num-bigint" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-integer" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", ] [[package]] name = "num-traits" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "plotters" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", "plotters-svg", "wasm-bindgen", "web-sys", ] [[package]] name = "plotters-backend" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] [[package]] name = "proc-macro2" version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quickcheck" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" dependencies = [ "env_logger", "log", "rand", ] [[package]] name = "quote" version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "rand_core", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] [[package]] name = "rayon" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "regex" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "rug" version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01d157703b9f96e9be75c739e7030d1d81be377d882d93046670309381517772" dependencies = [ "az", "gmp-mpfr-sys", "libc", "libm", ] [[package]] name = "rustix" version = "0.38.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys 0.48.0", ] [[package]] name = "ryu" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", "syn 2.0.72", ] [[package]] name = "serde_json" version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syn" version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "tinytemplate" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ "serde", "serde_json", ] [[package]] name = "uint" version = "0.10.0" dependencies = [ "arbitrary", "byteorder", "criterion", "crunchy", "hex", "num-bigint", "quickcheck", "rug", "static_assertions", ] [[package]] name = "unicode-ident" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "walkdir" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", "winapi", "winapi-util", ] [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", "syn 1.0.107", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", "syn 1.0.107", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "web-sys" version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets 0.48.5", ] [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm 0.48.5", "windows_aarch64_msvc 0.48.5", "windows_i686_gnu 0.48.5", "windows_i686_msvc 0.48.5", "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm 0.48.5", "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" uint-0.10.0/Cargo.toml0000644000000034760000000000100101010ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.56.1" name = "uint" version = "0.10.0" authors = ["Parity Technologies "] build = false autobins = false autoexamples = false autotests = false autobenches = false description = "Large fixed-size integer arithmetic" homepage = "http://parity.io" readme = "README.md" license = "MIT OR Apache-2.0" repository = "https://github.com/paritytech/parity-common" [lib] name = "uint" path = "src/lib.rs" [[example]] name = "modular" path = "examples/modular.rs" [[test]] name = "uint_tests" path = "tests/uint_tests.rs" required-features = ["std"] [[bench]] name = "bigint" path = "benches/bigint.rs" harness = false [dependencies.arbitrary] version = "1.0" optional = true [dependencies.byteorder] version = "1.4.2" default-features = false [dependencies.crunchy] version = "0.2.2" default-features = false [dependencies.hex] version = "0.4" default-features = false [dependencies.quickcheck] version = "1" optional = true [dependencies.static_assertions] version = "1.0.0" [dev-dependencies.criterion] version = "0.5.1" [dev-dependencies.num-bigint] version = "0.4.0" [features] default = ["std"] std = [ "byteorder/std", "crunchy/std", "hex/std", ] [target.'cfg(all(unix, target_arch = "x86_64"))'.dev-dependencies.rug] version = "1.6.0" features = [ "integer", "std", ] default-features = false uint-0.10.0/Cargo.toml.orig000064400000000000000000000020631046102023000135510ustar 00000000000000[package] description = "Large fixed-size integer arithmetic" homepage = "http://parity.io" repository = "https://github.com/paritytech/parity-common" license = "MIT OR Apache-2.0" name = "uint" version = "0.10.0" authors = ["Parity Technologies "] readme = "README.md" edition = "2021" rust-version = "1.56.1" [dependencies] byteorder = { version = "1.4.2", default-features = false } crunchy = { version = "0.2.2", default-features = false } quickcheck = { version = "1", optional = true } hex = { version = "0.4", default-features = false } static_assertions = "1.0.0" arbitrary = { version = "1.0", optional = true } [features] default = ["std"] std = ["byteorder/std", "crunchy/std", "hex/std"] [[example]] name = "modular" [[test]] name = "uint_tests" required-features = ["std"] [dev-dependencies] criterion = "0.5.1" num-bigint = "0.4.0" [target.'cfg(all(unix, target_arch = "x86_64"))'.dev-dependencies] rug = { version = "1.6.0", default-features = false, features = [ "integer", "std", ] } [[bench]] name = "bigint" harness = false uint-0.10.0/README.md000064400000000000000000000031011046102023000121330ustar 00000000000000# Uint ## Description Provides facilities to construct big unsigned integer types which use no allocations (stack-based, fixed bit length). If you want to use a predefined `U128`, `U256` or `U512` type, take a look at the [`primitive-types`](https://github.com/paritytech/parity-common/tree/master/primitive-types) or [`ethereum-types`](https://github.com/paritytech/parity-common/tree/master/ethereum-types) crate. The focus on the provided big unsigned integer types is performance and cross-platform availability. Support a very similar API as the built-in primitive integer types. ## Usage In your `Cargo.toml` paste ``` uint = "0.8" ``` Import the macro ``` use uint::construct_uint; ``` If you're using pre-edition Rust in your main file ``` #[macro_use] extern crate uint; ``` Construct your own big unsigned integer type as follows. ``` // U1024 with 1024 bits consisting of 16 x 64-bit words construct_uint! { pub struct U1024(16); } ``` ## Tests ### Basic tests ``` cargo test --release ``` ### Basic tests + property tests ``` cargo test --release --features=quickcheck ``` ### Benchmark tests ``` cargo bench ``` ### Fuzz tests see fuzz [README.md](fuzz/README.md) ## Crate Features - `std`: Use Rust's standard library. - Enables `byteorder/std`, `rustc-hex/std` - Enabled by default. - `quickcheck`: Enable quickcheck-style property testing - Use with `cargo test --release --features=quickcheck`. - `arbitrary`: Allow for creation of an `uint` object from random unstructured input for use with fuzzers that use the `arbitrary` crate. - Disabled by default. uint-0.10.0/benches/bigint.rs000064400000000000000000000461271046102023000141240ustar 00000000000000// Copyright 2020 Parity Technologies // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! benchmarking for bigint //! should be started with: //! ```bash //! rustup run cargo bench //! ``` use criterion::{criterion_group, criterion_main}; use uint::{construct_uint, uint_full_mul_reg}; construct_uint! { pub struct U256(4); } construct_uint! { pub struct U512(8); } impl U256 { #[inline(always)] pub fn full_mul(self, other: U256) -> U512 { U512(uint_full_mul_reg!(U256, 4, self, other)) } } use criterion::{black_box, Bencher, BenchmarkId, Criterion}; use num_bigint::BigUint; use rug::{integer::Order, Integer}; use std::str::FromStr; criterion_group!( bigint, u256_add, u256_sub, u256_mul, u256_mul_full, u256_div, u512_div_mod, u256_rem, u256_integer_sqrt, u256_bit_and, u256_bit_or, u256_bit_xor, u256_not, u256_ord, u256_shl, u256_shr, u256_from_le, u256_from_be, u512_add, u512_sub, u512_mul, u512_div, u512_rem, u512_integer_sqrt, u512_mul_u32_vs_u64, mulmod_u512_vs_biguint_vs_gmp, conversions, u512_bit_and, u512_bit_or, u512_bit_xor, u512_not, u512_ord, u512_shl, u512_shr, u128_mul, u128_div, from_fixed_array, from_str, ); criterion_main!(bigint); fn to_biguint(x: U256) -> BigUint { let bytes = x.to_little_endian(); BigUint::from_bytes_le(&bytes) } fn from_biguint(x: BigUint) -> U512 { let bytes = x.to_bytes_le(); U512::from_little_endian(&bytes) } fn to_gmp(x: U256) -> Integer { let U256(ref arr) = x; Integer::from_digits(&arr[..], Order::Lsf) } fn from_gmp(x: Integer) -> U512 { let digits = x.to_digits(Order::LsfLe); U512::from_little_endian(&digits) } fn u128_div(c: &mut Criterion) { let mut group = c.benchmark_group("u128_div"); for input in [(0u64, u64::max_value(), 100u64), (u64::max_value(), u64::max_value(), 99), (42, 42, 100500)] { group.bench_with_input(BenchmarkId::from_parameter(input.2), &input, |b, (x, y, z)| { b.iter(|| { let x = black_box(u128::from(*x) << 64 + u128::from(*y)); black_box(x / u128::from(*z)) }) }); } group.finish(); } fn u256_add(c: &mut Criterion) { let mut group = c.benchmark_group("u256_add"); for input in [(0u64, 1u64), (u64::max_value(), 1), (42, 100500)] { group.bench_with_input(BenchmarkId::from_parameter(input.0), &input, |b, (x, y)| { b.iter(|| { let x = U256::from(*x); let y = U256::from(*y); black_box(x.overflowing_add(y).0) }) }); } group.finish(); } fn u256_sub(c: &mut Criterion) { let mut group = c.benchmark_group("hex_to_bytes"); for input in [(U256::MAX, 1u64), (U256::from(3), 2)] { group.bench_with_input(BenchmarkId::from_parameter(input.0), &input, |b, (x, y)| { b.iter(|| { let y = U256::from(*y); black_box(x.overflowing_sub(y).0) }) }); } group.finish(); } fn u256_mul(c: &mut Criterion) { let mut group = c.benchmark_group("u256_mul"); for input in [ (U256::MAX, 1u64), (U256::from(3), u64::max_value()), (U256::from_dec_str("21674844646682989462120101885968193938394323990565507610662749").unwrap(), 173), ] { group.bench_with_input(BenchmarkId::from_parameter(input.1), &input, |b, (x, y)| { b.iter(|| { let y = U256::from(*y); black_box(x.overflowing_mul(y).0) }) }); } group.finish(); } fn u512_div_mod(c: &mut Criterion) { let mut group = c.benchmark_group("u512_div_mod"); for input in [ (U512::MAX, U512::from(1u64)), (U512::from(u64::max_value()), U512::from(u32::max_value())), (U512::from(u64::max_value()), U512::from(u64::max_value() - 1)), ( U512::from_dec_str("3759751734479964094783137206182536765532905409829204647089173492").unwrap(), U512::from_dec_str("21674844646682989462120101885968193938394323990565507610662749").unwrap(), ), ( U512::from_str( "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", ) .unwrap(), U512::from_str( "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0", ) .unwrap(), ), ( U512::from_dec_str( "204586912993508866875824356051724947013540127877691549342705710506008362274387533983037847993622361501550043477868832682875761627559574690771211649025" ).unwrap(), U512::from_dec_str( "452312848583266388373324160190187140051835877600158453279131187530910662640" ).unwrap(), ), ] { group.bench_with_input(BenchmarkId::from_parameter(input.1), &input, |b, (x, y)| { b.iter(|| { let (q, r) = x.div_mod(*y); black_box((q, r)) }) }); } group.finish(); } fn u256_mul_full(c: &mut Criterion) { let mut group = c.benchmark_group("hex_to_bytes"); for input in [(U256::from(42), 1u64), (U256::from(3), u64::max_value())] { group.bench_with_input(BenchmarkId::from_parameter(input.1), &input, |b, (x, y)| { b.iter(|| { let y = *y; let U512(ref u512words) = x.full_mul(U256([y, y, y, y])); black_box(U256([u512words[0], u512words[2], u512words[2], u512words[3]])) }) }); } group.finish(); } fn u256_div(c: &mut Criterion) { let one = U256([12767554894655550452, 16333049135534778834, 140317443000293558, 598963]); let two = U256([2096410819092764509, 8483673822214032535, 36306297304129857, 3453]); c.bench_function("u256_div", move |b| b.iter(|| black_box(one / two))); } fn u256_rem(c: &mut Criterion) { let mut group = c.benchmark_group("u256_rem"); for input in [ (U256::MAX, U256::from(1u64)), (U256::from(u64::max_value()), U256::from(u64::from(u32::max_value()) + 1)), ( U256([12767554894655550452, 16333049135534778834, 140317443000293558, 598963]), U256([2096410819092764509, 8483673822214032535, 36306297304129857, 3453]), ), ( U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(), U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0").unwrap(), ), ] { group.bench_with_input(BenchmarkId::from_parameter(input.0), &input, |b, (x, y)| b.iter(|| black_box(x % y))); } group.finish(); } fn u256_integer_sqrt(c: &mut Criterion) { let mut group = c.benchmark_group("u256_integer_sqrt"); for input in [ U256::from(u64::MAX), U256::from(u128::MAX) + 1, U256::from(u128::MAX - 1) * U256::from(u128::MAX - 1) - 1, U256::MAX, ] { group.bench_with_input(BenchmarkId::from_parameter(input), &input, |b, x| { b.iter(|| black_box(x.integer_sqrt().0)) }); } group.finish(); } fn u512_pairs() -> Vec<(U512, U512)> { vec![ (U512::from(1u64), U512::from(0u64)), (U512::from(u64::max_value()), U512::from(u64::from(u32::max_value()) + 1)), ( U512([12767554894655550452, 16333049135534778834, 140317443000293558, 598963, 0, 0, 0, 0]), U512([0, 0, 0, 0, 2096410819092764509, 8483673822214032535, 36306297304129857, 3453]), ), ( U512::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(), U512::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0").unwrap(), ), ] } fn u512_add(c: &mut Criterion) { let mut group = c.benchmark_group("u512_add"); for input in u512_pairs() { group.bench_with_input(BenchmarkId::from_parameter(input.1), &input, |b, (x, y)| b.iter(|| black_box(x + y))); } group.finish(); } fn u512_sub(c: &mut Criterion) { let mut group = c.benchmark_group("u512_sub"); for input in u512_pairs() { group.bench_with_input(BenchmarkId::from_parameter(input.1), &input, |b, (x, y)| { b.iter(|| black_box(x.overflowing_sub(*y).0)) }); } group.finish(); } fn u512_mul(c: &mut Criterion) { let mut group = c.benchmark_group("u512_mul"); for input in u512_pairs() { group.bench_with_input(BenchmarkId::from_parameter(input.1), &input, |b, (x, y)| { b.iter(|| black_box(x.overflowing_mul(*y).0)) }); } group.finish(); } fn u512_integer_sqrt(c: &mut Criterion) { let mut group = c.benchmark_group("u512_integer_sqrt"); for input in [ U512::from(u32::MAX) + 1, U512::from(u64::MAX), (U512::from(u128::MAX) + 1) * (U512::from(u128::MAX) + 1), U256::MAX.full_mul(U256::MAX) - 1, U512::MAX, ] { group.bench_with_input(BenchmarkId::from_parameter(input), &input, |b, x| { b.iter(|| black_box(x.integer_sqrt().0)) }); } group.finish(); } fn u512_div(c: &mut Criterion) { let one = U512([ 8326634216714383706, 15837136097609390493, 13004317189126203332, 7031796866963419685, 12767554894655550452, 16333049135534778834, 140317443000293558, 598963, ]); let two = U512([ 11707750893627518758, 17679501210898117940, 2472932874039724966, 11177683849610900539, 2096410819092764509, 8483673822214032535, 36306297304129857, 3453, ]); c.bench_function("u512_div", move |b| b.iter(|| black_box(one / two))); } fn u512_rem(c: &mut Criterion) { let one = U512([ 8326634216714383706, 15837136097609390493, 13004317189126203332, 7031796866963419685, 12767554894655550452, 16333049135534778834, 140317443000293558, 598963, ]); let two = U512([ 11707750893627518758, 17679501210898117940, 2472932874039724966, 11177683849610900539, 2096410819092764509, 8483673822214032535, 36306297304129857, 3453, ]); c.bench_function("u512_rem", move |b| b.iter(|| black_box(one % two))); } fn conversions(c: &mut Criterion) { let mut group = c.benchmark_group("conversions biguint vs gmp"); for input in [0, 42, u64::MAX] { group.bench_with_input(BenchmarkId::new("BigUint", input), &input, |b, i| bench_convert_to_biguit(b, *i)); group.bench_with_input(BenchmarkId::new("GMP", input), &input, |b, i| bench_convert_to_gmp(b, *i)); } group.finish(); } fn bench_convert_to_biguit(b: &mut Bencher, i: u64) { let z = U256::from(i); let z512 = U512::from(i); b.iter(|| { let zb = to_biguint(z); assert_eq!(from_biguint(zb), z512); }); } fn bench_convert_to_gmp(b: &mut Bencher, i: u64) { let z = U256::from(i); let z512 = U512::from(i); b.iter(|| { let zb = to_gmp(z); assert_eq!(from_gmp(zb), z512); }); } fn u512_mul_u32_vs_u64(c: &mut Criterion) { let ms = vec![1u32, 42, 10_000_001, u32::MAX]; let mut group = c.benchmark_group("multiply u512 by u32 vs u64"); for input in ms { group.bench_with_input(BenchmarkId::new("u32", input), &input, |b, i| bench_u512_mul_u32(b, *i)); group.bench_with_input(BenchmarkId::new("u64", input), &input, |b, i| bench_u512_mul_u64(b, u64::from(*i))); } group.finish(); } fn bench_u512_mul_u32(b: &mut Bencher, i: u32) { let x = U512::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); b.iter(|| black_box(x * i)); } fn bench_u512_mul_u64(b: &mut Bencher, i: u64) { let x = U512::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); b.iter(|| black_box(x * i)); } fn mulmod_u512_vs_biguint_vs_gmp(c: &mut Criterion) { let mods = vec![ U256::from(1u64), U256::from(10_000_001u64), U256::from(u64::max_value()), U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1").unwrap(), ]; let mut group = c.benchmark_group("mulmod u512 vs biguint vs gmp"); for input in mods { group.bench_with_input(BenchmarkId::new("u512", input), &input, |b, i| bench_u512_mulmod(b, *i)); group.bench_with_input(BenchmarkId::new("BigUint", input), &input, |b, i| bench_biguint_mulmod(b, *i)); group.bench_with_input(BenchmarkId::new("GMP", input), &input, |b, i| bench_gmp_mulmod(b, *i)); } group.finish(); } fn bench_biguint_mulmod(b: &mut Bencher, z: U256) { let x = U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); let y = U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); b.iter(|| { let w = to_biguint(x) * to_biguint(y); black_box(from_biguint(w % to_biguint(z))) }); } fn bench_gmp_mulmod(b: &mut Bencher, z: U256) { let x = U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); let y = U256::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); b.iter(|| { let w = to_gmp(x) * to_gmp(y); black_box(from_gmp(w % to_gmp(z))) }); } fn bench_u512_mulmod(b: &mut Bencher, z: U256) { let x = U512::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); let y = U512::from_str("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap(); let z = U512([z.0[0], z.0[1], z.0[2], z.0[3], 0, 0, 0, 0]); b.iter(|| { let w = x.overflowing_mul(y).0; black_box(w % z) }); } // NOTE: uses native `u128` and does not measure this crates performance, // but might be interesting as a comparison. fn u128_mul(c: &mut Criterion) { c.bench_function("u128_mul", |b| b.iter(|| black_box(12345u128 * u128::from(u64::max_value())))); } fn u256_bit_and(c: &mut Criterion) { let one = U256([12767554894655550452, 16333049135534778834, 140317443000293558, 598963]); let two = U256([2096410819092764509, 8483673822214032535, 36306297304129857, 3453]); c.bench_function("u256_bit_and", move |b| b.iter(|| black_box(one & two))); } fn u512_bit_and(c: &mut Criterion) { let one = U512([ 8326634216714383706, 15837136097609390493, 13004317189126203332, 7031796866963419685, 12767554894655550452, 16333049135534778834, 140317443000293558, 598963, ]); let two = U512([ 11707750893627518758, 17679501210898117940, 2472932874039724966, 11177683849610900539, 2096410819092764509, 8483673822214032535, 36306297304129857, 3453, ]); c.bench_function("u512_bit_and", move |b| b.iter(|| black_box(one & two))); } fn u256_bit_xor(c: &mut Criterion) { let one = U256([12767554894655550452, 16333049135534778834, 140317443000293558, 598963]); let two = U256([2096410819092764509, 8483673822214032535, 36306297304129857, 3453]); c.bench_function("u256_bit_xor", move |b| b.iter(|| black_box(one ^ two))); } fn u512_bit_xor(c: &mut Criterion) { let one = U512([ 8326634216714383706, 15837136097609390493, 13004317189126203332, 7031796866963419685, 12767554894655550452, 16333049135534778834, 140317443000293558, 598963, ]); let two = U512([ 11707750893627518758, 17679501210898117940, 2472932874039724966, 11177683849610900539, 2096410819092764509, 8483673822214032535, 36306297304129857, 3453, ]); c.bench_function("u512_bit_xor", move |b| b.iter(|| black_box(one ^ two))); } fn u256_bit_or(c: &mut Criterion) { let one = U256([12767554894655550452, 16333049135534778834, 140317443000293558, 598963]); let two = U256([2096410819092764509, 8483673822214032535, 36306297304129857, 3453]); c.bench_function("u256_bit_or", move |b| b.iter(|| black_box(one | two))); } fn u512_bit_or(c: &mut Criterion) { let one = U512([ 8326634216714383706, 15837136097609390493, 13004317189126203332, 7031796866963419685, 12767554894655550452, 16333049135534778834, 140317443000293558, 598963, ]); let two = U512([ 11707750893627518758, 17679501210898117940, 2472932874039724966, 11177683849610900539, 2096410819092764509, 8483673822214032535, 36306297304129857, 3453, ]); c.bench_function("u512_bit_or", move |b| b.iter(|| black_box(one | two))); } fn u256_not(c: &mut Criterion) { let one = U256([12767554894655550452, 16333049135534778834, 140317443000293558, 598963]); c.bench_function("u256_not", move |b| b.iter(|| black_box(!one))); } fn u512_not(c: &mut Criterion) { let one = U512([ 8326634216714383706, 15837136097609390493, 13004317189126203332, 7031796866963419685, 12767554894655550452, 16333049135534778834, 140317443000293558, 598963, ]); c.bench_function("u512_not", move |b| b.iter(|| black_box(!one))); } fn u256_shl(c: &mut Criterion) { let one = U256([12767554894655550452, 16333049135534778834, 140317443000293558, 598963]); c.bench_function("u256_shl", move |b| b.iter(|| black_box(one << 128))); } fn u512_shl(c: &mut Criterion) { let one = U512([ 8326634216714383706, 15837136097609390493, 13004317189126203332, 7031796866963419685, 12767554894655550452, 16333049135534778834, 140317443000293558, 598963, ]); c.bench_function("u512_shl", move |b| b.iter(|| black_box(one >> 128))); } fn u256_shr(c: &mut Criterion) { let one = U256([12767554894655550452, 16333049135534778834, 140317443000293558, 598963]); c.bench_function("u256_shr", move |b| b.iter(|| black_box(one >> 128))); } fn u512_shr(c: &mut Criterion) { let one = U512([ 8326634216714383706, 15837136097609390493, 13004317189126203332, 7031796866963419685, 12767554894655550452, 16333049135534778834, 140317443000293558, 598963, ]); c.bench_function("u512_shr", move |b| b.iter(|| black_box(one >> 128))); } fn u256_ord(c: &mut Criterion) { let one = U256([12767554894655550452, 16333049135534778834, 140317443000293558, 598963]); let two = U256([2096410819092764509, 8483673822214032535, 36306297304129857, 3453]); c.bench_function("u256_ord", move |b| b.iter(|| black_box(one) < black_box(two))); } fn u512_ord(c: &mut Criterion) { let one = U512([ 8326634216714383706, 15837136097609390493, 13004317189126203332, 7031796866963419685, 12767554894655550452, 16333049135534778834, 140317443000293558, 598963, ]); let two = U512([ 11707750893627518758, 17679501210898117940, 2472932874039724966, 11177683849610900539, 2096410819092764509, 8483673822214032535, 36306297304129857, 3453, ]); c.bench_function("u512_ord", move |b| b.iter(|| black_box(one) < black_box(two))); } fn u256_from_le(c: &mut Criterion) { c.bench_function("u256_from_le", |b| { b.iter(|| { let raw = black_box([ 1u8, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, ]); black_box(U256::from_little_endian(&raw[..])) }) }); } fn u256_from_be(c: &mut Criterion) { c.bench_function("u256_from_be", |b| { b.iter(|| { let raw = black_box([ 1u8, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, ]); black_box(U256::from_big_endian(&raw[..])) }) }); } fn from_fixed_array(c: &mut Criterion) { let ary512: [u8; 64] = [ 255, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 0, 0, 0, 0, 213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, ]; let ary256: [u8; 32] = [255, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 0, 0, 0, 0, 213, 0, 0, 0, 0, 0, 0]; c.bench_function("from_fixed_array", move |b| { b.iter(|| { let _: U512 = black_box(U512::from_big_endian(black_box(&ary512))); let _: U256 = black_box(U256::from_big_endian(black_box(&ary256))); }) }); } fn from_str(c: &mut Criterion) { c.bench_function("from_str", move |b| { b.iter(|| { black_box(U512::from_str(black_box("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")).unwrap()); black_box(U512::from_str(black_box("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")).unwrap()); black_box(U512::from_str(black_box("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")).unwrap()); }) }); } uint-0.10.0/examples/modular.rs000064400000000000000000000026151046102023000145140ustar 00000000000000// Copyright 2020 Parity Technologies // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[macro_use] extern crate uint; construct_uint! { pub struct U256(4); } fn main() { // Example modular arithmetic using bigint U256 primitives // imagine the field 0..p // where the p is defined below // (it's a prime!) let p = U256::from_dec_str("38873241744847760218045702002058062581688990428170398542849190507947196700873") .expect("p to be a good number in the example"); // then, on this field, // (p-1) + (p+1) = 0 // (p - 1) mod p let p_minus_1 = (p - 1) % p; // (p + 1) mod p let p_plus_1 = (p + 1) % p; // ((p - 1) mod p + (p + 1) mod p) mod p let sum = (p_minus_1 + p_plus_1) % p; assert_eq!(sum, 0.into()); // on this field, // (p-1) + (p-1) = p-2 let p_minus_1 = (p - 1) % p; let sum = (p_minus_1 + p_minus_1) % p; assert_eq!(sum, p - 2); // on this field, // (p-1) * 3 = p-3 let p_minus_1 = (p - 1) % p; // multiplication is a series of additions let multiplicator = 3; let mul = { let mut result = p_minus_1; for _ in 0..multiplicator - 1 { result = (p_minus_1 + result) % p; } result }; assert_eq!(mul, p - 3); } uint-0.10.0/src/lib.rs000064400000000000000000000016411046102023000125660ustar 00000000000000// Copyright 2020 Parity Technologies // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Efficient large, fixed-size big integers and hashes. #![cfg_attr(not(feature = "std"), no_std)] #[doc(hidden)] pub use byteorder; // Re-export libcore using an alias so that the macros can work without // requiring `extern crate core` downstream. #[doc(hidden)] pub use core as core_; #[doc(hidden)] pub use hex; #[cfg(feature = "quickcheck")] #[doc(hidden)] pub use quickcheck; #[cfg(feature = "arbitrary")] #[doc(hidden)] pub use arbitrary; #[doc(hidden)] pub use static_assertions; pub use crunchy::unroll; #[macro_use] #[rustfmt::skip] mod uint; pub use crate::uint::*; uint-0.10.0/src/uint.rs000064400000000000000000001344251046102023000130060ustar 00000000000000// Copyright 2020 Parity Technologies // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Code derived from original work by Andrew Poelstra // Rust Bitcoin Library // Written in 2014 by // Andrew Poelstra // // To the extent possible under law, the author(s) have dedicated all // copyright and related and neighboring rights to this software to // the public domain worldwide. This software is distributed without // any warranty. // // You should have received a copy of the CC0 Public Domain Dedication // along with this software. // If not, see . // //! Big unsigned integer types. //! //! Implementation of a various large-but-fixed sized unsigned integer types. //! The functions here are designed to be fast. There are optional `x86_64` //! implementations for even more speed, hidden behind the `x64_arithmetic` //! feature flag. use core::fmt; /// A list of error categories encountered when parsing numbers. #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] #[non_exhaustive] pub enum FromStrRadixErrKind { /// A character in the input string is not valid for the given radix. InvalidCharacter, /// The input length is not valid for the given radix. InvalidLength, /// The given radix is not supported. UnsupportedRadix, } #[derive(Debug)] enum FromStrRadixErrSrc { Hex(FromHexError), Dec(FromDecStrErr), } impl fmt::Display for FromStrRadixErrSrc { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { FromStrRadixErrSrc::Dec(d) => write!(f, "{}", d), FromStrRadixErrSrc::Hex(h) => write!(f, "{}", h), } } } /// The error type for parsing numbers from strings. #[derive(Debug)] pub struct FromStrRadixErr { kind: FromStrRadixErrKind, source: Option, } impl FromStrRadixErr { #[doc(hidden)] pub fn unsupported() -> Self { Self { kind: FromStrRadixErrKind::UnsupportedRadix, source: None } } /// Returns the corresponding `FromStrRadixErrKind` for this error. pub fn kind(&self) -> FromStrRadixErrKind { self.kind } } impl fmt::Display for FromStrRadixErr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(ref src) = self.source { return write!(f, "{}", src); } match self.kind { FromStrRadixErrKind::UnsupportedRadix => write!(f, "the given radix is not supported"), FromStrRadixErrKind::InvalidCharacter => write!(f, "input contains an invalid character"), FromStrRadixErrKind::InvalidLength => write!(f, "length not supported for radix or type"), } } } #[cfg(feature = "std")] impl std::error::Error for FromStrRadixErr { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self.source { Some(FromStrRadixErrSrc::Dec(ref d)) => Some(d), Some(FromStrRadixErrSrc::Hex(ref h)) => Some(h), None => None, } } } impl From for FromStrRadixErr { fn from(e: FromDecStrErr) -> Self { let kind = match e { FromDecStrErr::InvalidCharacter => FromStrRadixErrKind::InvalidCharacter, FromDecStrErr::InvalidLength => FromStrRadixErrKind::InvalidLength, }; Self { kind, source: Some(FromStrRadixErrSrc::Dec(e)) } } } impl From for FromStrRadixErr { fn from(e: FromHexError) -> Self { let kind = match e.inner { hex::FromHexError::InvalidHexCharacter { .. } => FromStrRadixErrKind::InvalidCharacter, hex::FromHexError::InvalidStringLength => FromStrRadixErrKind::InvalidLength, hex::FromHexError::OddLength => FromStrRadixErrKind::InvalidLength, }; Self { kind, source: Some(FromStrRadixErrSrc::Hex(e)) } } } /// Conversion from decimal string error #[derive(Debug, PartialEq, Eq)] pub enum FromDecStrErr { /// Char not from range 0-9 InvalidCharacter, /// Value does not fit into type InvalidLength, } impl fmt::Display for FromDecStrErr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "{}", match self { FromDecStrErr::InvalidCharacter => "a character is not in the range 0-9", FromDecStrErr::InvalidLength => "the number is too large for the type", } ) } } #[cfg(feature = "std")] impl std::error::Error for FromDecStrErr {} #[derive(Debug)] pub struct FromHexError { inner: hex::FromHexError, } impl fmt::Display for FromHexError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.inner) } } #[cfg(feature = "std")] impl std::error::Error for FromHexError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.inner) } } #[doc(hidden)] impl From for FromHexError { fn from(inner: hex::FromHexError) -> Self { Self { inner } } } #[macro_export] #[doc(hidden)] macro_rules! impl_map_from { ($thing:ident, $from:ty, $to:ty) => { impl From<$from> for $thing { fn from(value: $from) -> $thing { From::from(value as $to) } } }; } #[macro_export] #[doc(hidden)] macro_rules! impl_try_from_for_primitive { ($from:ident, $to:ty) => { impl $crate::core_::convert::TryFrom<$from> for $to { type Error = &'static str; #[inline] fn try_from(u: $from) -> $crate::core_::result::Result<$to, &'static str> { let $from(arr) = u; if !u.fits_word() || arr[0] > <$to>::max_value() as u64 { Err(concat!("integer overflow when casting to ", stringify!($to))) } else { Ok(arr[0] as $to) } } } }; } #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_binop { ($name:ident, $n_words: tt, $self_expr: expr, $other: expr, $fn:expr) => {{ use $crate::core_ as core; let $name(ref me) = $self_expr; let $name(ref you) = $other; let mut ret = [0u64; $n_words]; let mut carry = 0u64; $crate::static_assertions::const_assert!(core::isize::MAX as usize / core::mem::size_of::() > $n_words); // `unroll!` is recursive, but doesn’t use `$crate::unroll`, so we need to ensure that it // is in scope unqualified. use $crate::unroll; unroll! { for i in 0..$n_words { use core::ptr; if carry != 0 { let (res1, overflow1) = ($fn)(me[i], you[i]); let (res2, overflow2) = ($fn)(res1, carry); ret[i] = res2; carry = (overflow1 as u8 + overflow2 as u8) as u64; } else { let (res, overflow) = ($fn)(me[i], you[i]); ret[i] = res; carry = overflow as u64; } } } ($name(ret), carry > 0) }}; } #[macro_export] #[doc(hidden)] macro_rules! uint_full_mul_reg { ($name:ident, 8, $self_expr:expr, $other:expr) => { $crate::uint_full_mul_reg!($name, 8, $self_expr, $other, |a, b| a != 0 || b != 0); }; ($name:ident, $n_words:tt, $self_expr:expr, $other:expr) => { $crate::uint_full_mul_reg!($name, $n_words, $self_expr, $other, |_, _| true); }; ($name:ident, $n_words:tt, $self_expr:expr, $other:expr, $check:expr) => {{ { #![allow(unused_assignments)] let $name(ref me) = $self_expr; let $name(ref you) = $other; let mut ret = [0u64; $n_words * 2]; use $crate::unroll; unroll! { for i in 0..$n_words { let mut carry = 0u64; let b = you[i]; unroll! { for j in 0..$n_words { if $check(me[j], carry) { let a = me[j]; let (hi, low) = Self::split_u128(a as u128 * b as u128); let overflow = { let existing_low = &mut ret[i + j]; let (low, o) = low.overflowing_add(*existing_low); *existing_low = low; o }; carry = { let existing_hi = &mut ret[i + j + 1]; let hi = hi + overflow as u64; let (hi, o0) = hi.overflowing_add(carry); let (hi, o1) = hi.overflowing_add(*existing_hi); *existing_hi = hi; (o0 | o1) as u64 } } } } } } ret } }}; } #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_mul { ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => {{ let ret: [u64; $n_words * 2] = $crate::uint_full_mul_reg!($name, $n_words, $self_expr, $other); // The safety of this is enforced by the compiler let ret: [[u64; $n_words]; 2] = unsafe { $crate::core_::mem::transmute(ret) }; // The compiler WILL NOT inline this if you remove this annotation. #[inline(always)] fn any_nonzero(arr: &[u64; $n_words]) -> bool { use $crate::unroll; unroll! { for i in 0..$n_words { if arr[i] != 0 { return true; } } } false } ($name(ret[0]), any_nonzero(&ret[1])) }}; } #[macro_export] #[doc(hidden)] macro_rules! overflowing { ($op: expr, $overflow: expr) => {{ let (overflow_x, overflow_overflow) = $op; $overflow |= overflow_overflow; overflow_x }}; ($op: expr) => {{ let (overflow_x, _overflow_overflow) = $op; overflow_x }}; } #[macro_export] #[doc(hidden)] macro_rules! panic_on_overflow { ($name: expr) => { if $name { panic!("arithmetic operation overflow") } }; } #[macro_export] #[doc(hidden)] macro_rules! impl_mul_from { ($name: ty, $other: ident) => { impl $crate::core_::ops::Mul<$other> for $name { type Output = $name; fn mul(self, other: $other) -> $name { let bignum: $name = other.into(); let (result, overflow) = self.overflowing_mul(bignum); $crate::panic_on_overflow!(overflow); result } } impl<'a> $crate::core_::ops::Mul<&'a $other> for $name { type Output = $name; fn mul(self, other: &'a $other) -> $name { let bignum: $name = (*other).into(); let (result, overflow) = self.overflowing_mul(bignum); $crate::panic_on_overflow!(overflow); result } } impl<'a> $crate::core_::ops::Mul<&'a $other> for &'a $name { type Output = $name; fn mul(self, other: &'a $other) -> $name { let bignum: $name = (*other).into(); let (result, overflow) = self.overflowing_mul(bignum); $crate::panic_on_overflow!(overflow); result } } impl<'a> $crate::core_::ops::Mul<$other> for &'a $name { type Output = $name; fn mul(self, other: $other) -> $name { let bignum: $name = other.into(); let (result, overflow) = self.overflowing_mul(bignum); $crate::panic_on_overflow!(overflow); result } } impl $crate::core_::ops::MulAssign<$other> for $name { fn mul_assign(&mut self, other: $other) { let result = *self * other; *self = result } } }; } #[macro_export] #[doc(hidden)] macro_rules! impl_mul_for_primitive { ($name: ty, $other: ident) => { impl $crate::core_::ops::Mul<$other> for $name { type Output = $name; fn mul(self, other: $other) -> $name { let (result, carry) = self.overflowing_mul_u64(other as u64); $crate::panic_on_overflow!(carry > 0); result } } impl<'a> $crate::core_::ops::Mul<&'a $other> for $name { type Output = $name; fn mul(self, other: &'a $other) -> $name { let (result, carry) = self.overflowing_mul_u64(*other as u64); $crate::panic_on_overflow!(carry > 0); result } } impl<'a> $crate::core_::ops::Mul<&'a $other> for &'a $name { type Output = $name; fn mul(self, other: &'a $other) -> $name { let (result, carry) = self.overflowing_mul_u64(*other as u64); $crate::panic_on_overflow!(carry > 0); result } } impl<'a> $crate::core_::ops::Mul<$other> for &'a $name { type Output = $name; fn mul(self, other: $other) -> $name { let (result, carry) = self.overflowing_mul_u64(other as u64); $crate::panic_on_overflow!(carry > 0); result } } impl $crate::core_::ops::MulAssign<$other> for $name { fn mul_assign(&mut self, other: $other) { let result = *self * (other as u64); *self = result } } }; } #[macro_export] macro_rules! construct_uint { ( $(#[$attr:meta])* $visibility:vis struct $name:ident (1); ) => { $crate::construct_uint!{ @construct $(#[$attr])* $visibility struct $name (1); } }; ( $(#[$attr:meta])* $visibility:vis struct $name:ident ( $n_words:tt ); ) => { $crate::construct_uint! { @construct $(#[$attr])* $visibility struct $name ($n_words); } impl $crate::core_::convert::From for $name { fn from(value: u128) -> $name { let mut ret = [0; $n_words]; ret[0] = value as u64; ret[1] = (value >> 64) as u64; $name(ret) } } impl $crate::core_::convert::From for $name { fn from(value: i128) -> $name { match value >= 0 { true => From::from(value as u128), false => { panic!("Unsigned integer can't be created from negative value"); } } } } impl $name { /// Low 2 words (u128) #[inline] pub const fn low_u128(&self) -> u128 { let &$name(ref arr) = self; ((arr[1] as u128) << 64) + arr[0] as u128 } /// Conversion to u128 with overflow checking /// /// # Panics /// /// Panics if the number is larger than 2^128. #[inline] pub fn as_u128(&self) -> u128 { let &$name(ref arr) = self; for i in 2..$n_words { if arr[i] != 0 { panic!("Integer overflow when casting to u128") } } self.low_u128() } } impl $crate::core_::convert::TryFrom<$name> for u128 { type Error = &'static str; #[inline] fn try_from(u: $name) -> $crate::core_::result::Result { let $name(arr) = u; for i in 2..$n_words { if arr[i] != 0 { return Err("integer overflow when casting to u128"); } } Ok(((arr[1] as u128) << 64) + arr[0] as u128) } } impl $crate::core_::convert::TryFrom<$name> for i128 { type Error = &'static str; #[inline] fn try_from(u: $name) -> $crate::core_::result::Result { let err_str = "integer overflow when casting to i128"; let i = u128::try_from(u).map_err(|_| err_str)?; if i > i128::max_value() as u128 { Err(err_str) } else { Ok(i as i128) } } } }; ( @construct $(#[$attr:meta])* $visibility:vis struct $name:ident ( $n_words:tt ); ) => { /// Little-endian large integer type #[repr(C)] $(#[$attr])* #[derive(Copy, Clone, Eq, PartialEq, Hash)] $visibility struct $name (pub [u64; $n_words]); /// Get a reference to the underlying little-endian words. impl AsRef<[u64]> for $name { #[inline] fn as_ref(&self) -> &[u64] { &self.0 } } impl<'a> From<&'a $name> for $name { fn from(x: &'a $name) -> $name { *x } } impl $name { const WORD_BITS: usize = 64; /// Maximum value. pub const MAX: $name = $name([u64::max_value(); $n_words]); /// Converts a string slice in a given base to an integer. Only supports radixes of 10 /// and 16. pub fn from_str_radix(txt: &str, radix: u32) -> Result { let parsed = match radix { 10 => Self::from_dec_str(txt)?, 16 => core::str::FromStr::from_str(txt)?, _ => return Err($crate::FromStrRadixErr::unsupported()), }; Ok(parsed) } /// Convert from a decimal string. pub fn from_dec_str(value: &str) -> $crate::core_::result::Result { let mut res = Self::default(); for b in value.bytes().map(|b| b.wrapping_sub(b'0')) { if b > 9 { return Err($crate::FromDecStrErr::InvalidCharacter) } let (r, overflow) = res.overflowing_mul_u64(10); if overflow > 0 { return Err($crate::FromDecStrErr::InvalidLength); } let (r, overflow) = r.overflowing_add(b.into()); if overflow { return Err($crate::FromDecStrErr::InvalidLength); } res = r; } Ok(res) } /// Conversion to u32 #[inline] pub const fn low_u32(&self) -> u32 { let &$name(ref arr) = self; arr[0] as u32 } /// Low word (u64) #[inline] pub const fn low_u64(&self) -> u64 { let &$name(ref arr) = self; arr[0] } /// Conversion to u32 with overflow checking /// /// # Panics /// /// Panics if the number is larger than 2^32. #[inline] pub fn as_u32(&self) -> u32 { let &$name(ref arr) = self; if !self.fits_word() || arr[0] > u32::max_value() as u64 { panic!("Integer overflow when casting to u32") } self.as_u64() as u32 } /// Conversion to u64 with overflow checking /// /// # Panics /// /// Panics if the number is larger than u64::max_value(). #[inline] pub fn as_u64(&self) -> u64 { let &$name(ref arr) = self; if !self.fits_word() { panic!("Integer overflow when casting to u64") } arr[0] } /// Conversion to usize with overflow checking /// /// # Panics /// /// Panics if the number is larger than usize::max_value(). #[inline] pub fn as_usize(&self) -> usize { let &$name(ref arr) = self; if !self.fits_word() || arr[0] > usize::max_value() as u64 { panic!("Integer overflow when casting to usize") } arr[0] as usize } /// Whether this is zero. #[inline] pub const fn is_zero(&self) -> bool { let &$name(ref arr) = self; let mut i = 0; while i < $n_words { if arr[i] != 0 { return false; } else { i += 1; } } return true; } // Whether this fits u64. #[inline] fn fits_word(&self) -> bool { let &$name(ref arr) = self; for i in 1..$n_words { if arr[i] != 0 { return false; } } return true; } /// Return the least number of bits needed to represent the number #[inline] pub fn bits(&self) -> usize { let &$name(ref arr) = self; for i in 1..$n_words { if arr[$n_words - i] > 0 { return (0x40 * ($n_words - i + 1)) - arr[$n_words - i].leading_zeros() as usize; } } 0x40 - arr[0].leading_zeros() as usize } /// Return if specific bit is set. /// /// # Panics /// /// Panics if `index` exceeds the bit width of the number. #[inline] pub const fn bit(&self, index: usize) -> bool { let &$name(ref arr) = self; arr[index / 64] & (1 << (index % 64)) != 0 } /// Returns the number of leading zeros in the binary representation of self. pub fn leading_zeros(&self) -> u32 { let mut r = 0; for i in 0..$n_words { let w = self.0[$n_words - i - 1]; if w == 0 { r += 64; } else { r += w.leading_zeros(); break; } } r } /// Returns the number of trailing zeros in the binary representation of self. pub fn trailing_zeros(&self) -> u32 { let mut r = 0; for i in 0..$n_words { let w = self.0[i]; if w == 0 { r += 64; } else { r += w.trailing_zeros(); break; } } r } /// Return specific byte. Byte 0 is the least significant value (ie~ little endian). /// /// # Panics /// /// Panics if `index` exceeds the byte width of the number. #[inline] pub const fn byte(&self, index: usize) -> u8 { let &$name(ref arr) = self; (arr[index / 8] >> (((index % 8)) * 8)) as u8 } /// Convert to big-endian bytes. #[inline] pub fn to_big_endian(&self) -> [u8; $n_words * 8] { let mut bytes = [0u8; $n_words * 8]; self.write_as_big_endian(&mut bytes); bytes } /// Write to the slice in big-endian format. #[inline] pub fn write_as_big_endian(&self, bytes: &mut [u8]) { use $crate::byteorder::{ByteOrder, BigEndian}; debug_assert!($n_words * 8 == bytes.len()); for i in 0..$n_words { BigEndian::write_u64(&mut bytes[8 * i..], self.0[$n_words - i - 1]); } } /// Convert to little-endian bytes. #[inline] pub fn to_little_endian(&self) -> [u8; $n_words * 8] { let mut bytes = [0u8; $n_words * 8]; self.write_as_little_endian(&mut bytes); bytes } #[inline] pub fn write_as_little_endian(&self, bytes: &mut [u8]) { use $crate::byteorder::{ByteOrder, LittleEndian}; debug_assert!($n_words * 8 == bytes.len()); for i in 0..$n_words { LittleEndian::write_u64(&mut bytes[8 * i..], self.0[i]); } } /// Create `10**n` as this type. /// /// # Panics /// /// Panics if the result overflows the type. #[inline] pub fn exp10(n: usize) -> Self { match n { 0 => Self::from(1u64), _ => Self::exp10(n - 1) * 10u32 } } /// Zero (additive identity) of this type. #[inline] pub const fn zero() -> Self { Self([0; $n_words]) } /// One (multiplicative identity) of this type. #[inline] pub const fn one() -> Self { let mut words = [0; $n_words]; words[0] = 1u64; Self(words) } /// The maximum value which can be inhabited by this type. #[inline] pub const fn max_value() -> Self { Self::MAX } fn full_shl(self, shift: u32) -> [u64; $n_words + 1] { debug_assert!(shift < Self::WORD_BITS as u32); let mut u = [0u64; $n_words + 1]; let u_lo = self.0[0] << shift; let u_hi = self >> (Self::WORD_BITS as u32 - shift); u[0] = u_lo; u[1..].copy_from_slice(&u_hi.0[..]); u } fn full_shr(u: [u64; $n_words + 1], shift: u32) -> Self { debug_assert!(shift < Self::WORD_BITS as u32); let mut res = Self::zero(); for i in 0..$n_words { res.0[i] = u[i] >> shift; } // carry if shift > 0 { for i in 1..=$n_words { res.0[i - 1] |= u[i] << (Self::WORD_BITS as u32 - shift); } } res } fn full_mul_u64(self, by: u64) -> [u64; $n_words + 1] { let (prod, carry) = self.overflowing_mul_u64(by); let mut res = [0u64; $n_words + 1]; res[..$n_words].copy_from_slice(&prod.0[..]); res[$n_words] = carry; res } fn div_mod_small(mut self, other: u64) -> (Self, Self) { let mut rem = 0u64; self.0.iter_mut().rev().for_each(|d| { let (q, r) = Self::div_mod_word(rem, *d, other); *d = q; rem = r; }); (self, rem.into()) } // See Knuth, TAOCP, Volume 2, section 4.3.1, Algorithm D. fn div_mod_knuth(self, mut v: Self, n: usize, m: usize) -> (Self, Self) { debug_assert!(self.bits() >= v.bits() && !v.fits_word()); debug_assert!(n + m <= $n_words); // D1. // Make sure 64th bit in v's highest word is set. // If we shift both self and v, it won't affect the quotient // and the remainder will only need to be shifted back. let shift = v.0[n - 1].leading_zeros(); v <<= shift; // u will store the remainder (shifted) let mut u = self.full_shl(shift); // quotient let mut q = Self::zero(); let v_n_1 = v.0[n - 1]; let v_n_2 = v.0[n - 2]; // D2. D7. // iterate from m downto 0 for j in (0..=m).rev() { let u_jn = u[j + n]; // D3. // q_hat is our guess for the j-th quotient digit // q_hat = min(b - 1, (u_{j+n} * b + u_{j+n-1}) / v_{n-1}) // b = 1 << WORD_BITS // Theorem B: q_hat >= q_j >= q_hat - 2 let mut q_hat = if u_jn < v_n_1 { let (mut q_hat, mut r_hat) = Self::div_mod_word(u_jn, u[j + n - 1], v_n_1); // this loop takes at most 2 iterations loop { // check if q_hat * v_{n-2} > b * r_hat + u_{j+n-2} let (hi, lo) = Self::split_u128(u128::from(q_hat) * u128::from(v_n_2)); if (hi, lo) <= (r_hat, u[j + n - 2]) { break; } // then iterate till it doesn't hold q_hat -= 1; let (new_r_hat, overflow) = r_hat.overflowing_add(v_n_1); r_hat = new_r_hat; // if r_hat overflowed, we're done if overflow { break; } } q_hat } else { // here q_hat >= q_j >= q_hat - 1 u64::max_value() }; // ex. 20: // since q_hat * v_{n-2} <= b * r_hat + u_{j+n-2}, // either q_hat == q_j, or q_hat == q_j + 1 // D4. // let's assume optimistically q_hat == q_j // subtract (q_hat * v) from u[j..] let q_hat_v = v.full_mul_u64(q_hat); // u[j..] -= q_hat_v; let c = Self::sub_slice(&mut u[j..], &q_hat_v[..n + 1]); // D6. // actually, q_hat == q_j + 1 and u[j..] has overflowed // highly unlikely ~ (1 / 2^63) if c { q_hat -= 1; // add v to u[j..] let c = Self::add_slice(&mut u[j..], &v.0[..n]); u[j + n] = u[j + n].wrapping_add(u64::from(c)); } // D5. q.0[j] = q_hat; } // D8. let remainder = Self::full_shr(u, shift); (q, remainder) } // Returns the least number of words needed to represent the nonzero number fn words(bits: usize) -> usize { debug_assert!(bits > 0); 1 + (bits - 1) / Self::WORD_BITS } /// Returns a pair `(self / other, self % other)`. /// /// # Panics /// /// Panics if `other` is zero. pub fn div_mod(mut self, mut other: Self) -> (Self, Self) { use $crate::core_::cmp::Ordering; let my_bits = self.bits(); let your_bits = other.bits(); assert!(your_bits != 0, "division by zero"); // Early return in case we are dividing by a larger number than us if my_bits < your_bits { return (Self::zero(), self); } if your_bits <= Self::WORD_BITS { return self.div_mod_small(other.low_u64()); } let (n, m) = { let my_words = Self::words(my_bits); let your_words = Self::words(your_bits); (your_words, my_words - your_words) }; self.div_mod_knuth(other, n, m) } /// Compute the highest `n` such that `n * n <= self`. pub fn integer_sqrt(&self) -> Self { let one = Self::one(); if self <= &one { return *self; } // the implementation is based on: // https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Set the initial guess to something higher than √self. let shift: u32 = (self.bits() as u32 + 1) / 2; let mut x_prev = one << shift; loop { let x = (x_prev + self / x_prev) >> 1; if x >= x_prev { return x_prev; } x_prev = x; } } /// Fast exponentiation by squaring /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring /// /// # Panics /// /// Panics if the result overflows the type. pub fn pow(self, expon: Self) -> Self { if expon.is_zero() { return Self::one() } let is_even = |x : &Self| x.low_u64() & 1 == 0; let u_one = Self::one(); let mut y = u_one; let mut n = expon; let mut x = self; while n > u_one { if is_even(&n) { x = x * x; n >>= 1usize; } else { y = x * y; x = x * x; // to reduce odd number by 1 we should just clear the last bit n.0[$n_words-1] &= (!0u64)>>1; n >>= 1usize; } } x * y } /// Fast exponentiation by squaring. Returns result and overflow flag. pub fn overflowing_pow(self, expon: Self) -> (Self, bool) { if expon.is_zero() { return (Self::one(), false) } let is_even = |x : &Self| x.low_u64() & 1 == 0; let u_one = Self::one(); let mut y = u_one; let mut n = expon; let mut x = self; let mut overflow = false; while n > u_one { if is_even(&n) { x = $crate::overflowing!(x.overflowing_mul(x), overflow); n >>= 1usize; } else { y = $crate::overflowing!(x.overflowing_mul(y), overflow); x = $crate::overflowing!(x.overflowing_mul(x), overflow); n = (n - u_one) >> 1usize; } } let res = $crate::overflowing!(x.overflowing_mul(y), overflow); (res, overflow) } /// Checked exponentiation. Returns `None` if overflow occurred. pub fn checked_pow(self, expon: $name) -> Option<$name> { match self.overflowing_pow(expon) { (_, true) => None, (val, _) => Some(val), } } /// Addition which overflows and returns a flag if it does. #[inline(always)] pub fn overflowing_add(self, other: $name) -> ($name, bool) { $crate::uint_overflowing_binop!( $name, $n_words, self, other, u64::overflowing_add ) } /// Addition which saturates at the maximum value (Self::MAX). pub fn saturating_add(self, other: $name) -> $name { match self.overflowing_add(other) { (_, true) => $name::MAX, (val, false) => val, } } /// Checked addition. Returns `None` if overflow occurred. pub fn checked_add(self, other: $name) -> Option<$name> { match self.overflowing_add(other) { (_, true) => None, (val, _) => Some(val), } } /// Subtraction which underflows and returns a flag if it does. #[inline(always)] pub fn overflowing_sub(self, other: $name) -> ($name, bool) { $crate::uint_overflowing_binop!( $name, $n_words, self, other, u64::overflowing_sub ) } /// Subtraction which saturates at zero. pub fn saturating_sub(self, other: $name) -> $name { match self.overflowing_sub(other) { (_, true) => $name::zero(), (val, false) => val, } } /// Checked subtraction. Returns `None` if overflow occurred. pub fn checked_sub(self, other: $name) -> Option<$name> { match self.overflowing_sub(other) { (_, true) => None, (val, _) => Some(val), } } /// Computes the absolute difference between self and other. pub fn abs_diff(self, other: $name) -> $name { if self > other { self.overflowing_sub(other).0 } else { other.overflowing_sub(self).0 } } /// Multiply with overflow, returning a flag if it does. #[inline(always)] pub fn overflowing_mul(self, other: $name) -> ($name, bool) { $crate::uint_overflowing_mul!($name, $n_words, self, other) } /// Multiplication which saturates at the maximum value.. pub fn saturating_mul(self, other: $name) -> $name { match self.overflowing_mul(other) { (_, true) => $name::MAX, (val, false) => val, } } /// Checked multiplication. Returns `None` if overflow occurred. pub fn checked_mul(self, other: $name) -> Option<$name> { match self.overflowing_mul(other) { (_, true) => None, (val, _) => Some(val), } } /// Checked division. Returns `None` if `other == 0`. pub fn checked_div(self, other: $name) -> Option<$name> { if other.is_zero() { None } else { Some(self / other) } } /// Checked modulus. Returns `None` if `other == 0`. pub fn checked_rem(self, other: $name) -> Option<$name> { if other.is_zero() { None } else { Some(self % other) } } /// Negation with overflow. pub fn overflowing_neg(self) -> ($name, bool) { if self.is_zero() { (self, false) } else { (!self + 1, true) } } /// Checked negation. Returns `None` unless `self == 0`. pub fn checked_neg(self) -> Option<$name> { match self.overflowing_neg() { (_, true) => None, (zero, false) => Some(zero), } } #[inline(always)] fn div_mod_word(hi: u64, lo: u64, y: u64) -> (u64, u64) { debug_assert!(hi < y); let x = (u128::from(hi) << 64) + u128::from(lo); let y = u128::from(y); ((x / y) as u64, (x % y) as u64) } #[inline(always)] fn add_slice(a: &mut [u64], b: &[u64]) -> bool { Self::binop_slice(a, b, u64::overflowing_add) } #[inline(always)] fn sub_slice(a: &mut [u64], b: &[u64]) -> bool { Self::binop_slice(a, b, u64::overflowing_sub) } #[inline(always)] fn binop_slice(a: &mut [u64], b: &[u64], binop: impl Fn(u64, u64) -> (u64, bool) + Copy) -> bool { let mut c = false; a.iter_mut().zip(b.iter()).for_each(|(x, y)| { let (res, carry) = Self::binop_carry(*x, *y, c, binop); *x = res; c = carry; }); c } #[inline(always)] fn binop_carry(a: u64, b: u64, c: bool, binop: impl Fn(u64, u64) -> (u64, bool)) -> (u64, bool) { let (res1, overflow1) = b.overflowing_add(u64::from(c)); let (res2, overflow2) = binop(a, res1); (res2, overflow1 || overflow2) } #[inline(always)] const fn mul_u64(a: u64, b: u64, carry: u64) -> (u64, u64) { let (hi, lo) = Self::split_u128(a as u128 * b as u128 + carry as u128); (lo, hi) } #[inline(always)] const fn split(a: u64) -> (u64, u64) { (a >> 32, a & 0xFFFF_FFFF) } #[inline(always)] const fn split_u128(a: u128) -> (u64, u64) { ((a >> 64) as _, (a & 0xFFFFFFFFFFFFFFFF) as _) } /// Overflowing multiplication by u64. /// Returns the result and carry. fn overflowing_mul_u64(mut self, other: u64) -> (Self, u64) { let mut carry = 0u64; for d in self.0.iter_mut() { let (res, c) = Self::mul_u64(*d, other, carry); *d = res; carry = c; } (self, carry) } /// Converts from big endian representation bytes in memory. pub fn from_big_endian(slice: &[u8]) -> Self { use $crate::byteorder::{ByteOrder, BigEndian}; assert!($n_words * 8 >= slice.len()); let mut padded = [0u8; $n_words * 8]; padded[$n_words * 8 - slice.len() .. $n_words * 8].copy_from_slice(&slice); let mut ret = [0; $n_words]; for i in 0..$n_words { ret[$n_words - i - 1] = BigEndian::read_u64(&padded[8 * i..]); } $name(ret) } /// Converts from little endian representation bytes in memory. pub fn from_little_endian(slice: &[u8]) -> Self { use $crate::byteorder::{ByteOrder, LittleEndian}; assert!($n_words * 8 >= slice.len()); let mut padded = [0u8; $n_words * 8]; padded[0..slice.len()].copy_from_slice(&slice); let mut ret = [0; $n_words]; for i in 0..$n_words { ret[i] = LittleEndian::read_u64(&padded[8 * i..]); } $name(ret) } fn fmt_hex(&self, f: &mut $crate::core_::fmt::Formatter, is_lower: bool) -> $crate::core_::fmt::Result { let &$name(ref data) = self; // special case. if self.is_zero() { return f.pad_integral(true, "0x", "0"); } let mut latch = false; let mut buf = [0_u8; $n_words * 16]; let mut i = 0; for ch in data.iter().rev() { for x in 0..16 { // nibble < 16 let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64); if !latch { latch = nibble != 0; } if latch { // nibble is `'0'..'9' 'a'..'f' 'A'..'F'` because nibble < 16 let nibble = match nibble { 0..=9 => nibble as u8 + b'0', _ if is_lower => nibble as u8 - 10 + b'a', _ => nibble as u8 - 10 + b'A', }; buf[i] = nibble; i += 1; } } } // sequence of `'0'..'9' 'a'..'f' 'A'..'F'` chars is guaranteed to be a valid UTF8 string let s = unsafe { $crate::core_::str::from_utf8_unchecked(&buf[0..i]) }; f.pad_integral(true, "0x", s) } } impl $crate::core_::default::Default for $name { fn default() -> Self { $name::zero() } } impl $crate::core_::convert::From for $name { fn from(value: u64) -> $name { let mut ret = [0; $n_words]; ret[0] = value; $name(ret) } } $crate::impl_map_from!($name, u8, u64); $crate::impl_map_from!($name, u16, u64); $crate::impl_map_from!($name, u32, u64); $crate::impl_map_from!($name, usize, u64); impl $crate::core_::convert::From for $name { fn from(value: i64) -> $name { match value >= 0 { true => From::from(value as u64), false => { panic!("Unsigned integer can't be created from negative value"); } } } } $crate::impl_map_from!($name, i8, i64); $crate::impl_map_from!($name, i16, i64); $crate::impl_map_from!($name, i32, i64); $crate::impl_map_from!($name, isize, i64); $crate::impl_try_from_for_primitive!($name, u8); $crate::impl_try_from_for_primitive!($name, u16); $crate::impl_try_from_for_primitive!($name, u32); $crate::impl_try_from_for_primitive!($name, usize); $crate::impl_try_from_for_primitive!($name, u64); $crate::impl_try_from_for_primitive!($name, i8); $crate::impl_try_from_for_primitive!($name, i16); $crate::impl_try_from_for_primitive!($name, i32); $crate::impl_try_from_for_primitive!($name, isize); $crate::impl_try_from_for_primitive!($name, i64); impl $crate::core_::ops::Add for $name where T: Into<$name> { type Output = $name; fn add(self, other: T) -> $name { let (result, overflow) = self.overflowing_add(other.into()); $crate::panic_on_overflow!(overflow); result } } impl<'a, T> $crate::core_::ops::Add for &'a $name where T: Into<$name> { type Output = $name; fn add(self, other: T) -> $name { *self + other } } impl $crate::core_::ops::AddAssign<$name> for $name { fn add_assign(&mut self, other: $name) { let (result, overflow) = self.overflowing_add(other); $crate::panic_on_overflow!(overflow); *self = result } } impl $crate::core_::ops::Sub for $name where T: Into<$name> { type Output = $name; #[inline] fn sub(self, other: T) -> $name { let (result, overflow) = self.overflowing_sub(other.into()); $crate::panic_on_overflow!(overflow); result } } impl<'a, T> $crate::core_::ops::Sub for &'a $name where T: Into<$name> { type Output = $name; fn sub(self, other: T) -> $name { *self - other } } impl $crate::core_::ops::SubAssign<$name> for $name { fn sub_assign(&mut self, other: $name) { let (result, overflow) = self.overflowing_sub(other); $crate::panic_on_overflow!(overflow); *self = result } } // all other impls $crate::impl_mul_from!($name, $name); $crate::impl_mul_for_primitive!($name, u8); $crate::impl_mul_for_primitive!($name, u16); $crate::impl_mul_for_primitive!($name, u32); $crate::impl_mul_for_primitive!($name, u64); $crate::impl_mul_for_primitive!($name, usize); $crate::impl_mul_for_primitive!($name, i8); $crate::impl_mul_for_primitive!($name, i16); $crate::impl_mul_for_primitive!($name, i32); $crate::impl_mul_for_primitive!($name, i64); $crate::impl_mul_for_primitive!($name, isize); impl $crate::core_::ops::Div for $name where T: Into<$name> { type Output = $name; fn div(self, other: T) -> $name { let other: Self = other.into(); self.div_mod(other).0 } } impl<'a, T> $crate::core_::ops::Div for &'a $name where T: Into<$name> { type Output = $name; fn div(self, other: T) -> $name { *self / other } } impl $crate::core_::ops::DivAssign for $name where T: Into<$name> { fn div_assign(&mut self, other: T) { *self = *self / other.into(); } } impl $crate::core_::ops::Rem for $name where T: Into<$name> + Copy { type Output = $name; fn rem(self, other: T) -> $name { let mut sub_copy = self; sub_copy %= other; sub_copy } } impl<'a, T> $crate::core_::ops::Rem for &'a $name where T: Into<$name> + Copy { type Output = $name; fn rem(self, other: T) -> $name { *self % other } } impl $crate::core_::ops::RemAssign for $name where T: Into<$name> + Copy { fn rem_assign(&mut self, other: T) { let other: Self = other.into(); let rem = self.div_mod(other).1; *self = rem; } } impl $crate::core_::ops::BitAnd<$name> for $name { type Output = $name; #[inline] fn bitand(self, other: $name) -> $name { let $name(ref arr1) = self; let $name(ref arr2) = other; let mut ret = [0u64; $n_words]; for i in 0..$n_words { ret[i] = arr1[i] & arr2[i]; } $name(ret) } } impl $crate::core_::ops::BitAndAssign<$name> for $name { fn bitand_assign(&mut self, rhs: $name) { *self = *self & rhs; } } impl $crate::core_::ops::BitXor<$name> for $name { type Output = $name; #[inline] fn bitxor(self, other: $name) -> $name { let $name(ref arr1) = self; let $name(ref arr2) = other; let mut ret = [0u64; $n_words]; for i in 0..$n_words { ret[i] = arr1[i] ^ arr2[i]; } $name(ret) } } impl $crate::core_::ops::BitXorAssign<$name> for $name { fn bitxor_assign(&mut self, rhs: $name) { *self = *self ^ rhs; } } impl $crate::core_::ops::BitOr<$name> for $name { type Output = $name; #[inline] fn bitor(self, other: $name) -> $name { let $name(ref arr1) = self; let $name(ref arr2) = other; let mut ret = [0u64; $n_words]; for i in 0..$n_words { ret[i] = arr1[i] | arr2[i]; } $name(ret) } } impl $crate::core_::ops::BitOrAssign<$name> for $name { fn bitor_assign(&mut self, rhs: $name) { *self = *self | rhs; } } impl $crate::core_::ops::Not for $name { type Output = $name; #[inline] fn not(self) -> $name { let $name(ref arr) = self; let mut ret = [0u64; $n_words]; for i in 0..$n_words { ret[i] = !arr[i]; } $name(ret) } } impl $crate::core_::ops::Shl for $name where T: Into<$name> { type Output = $name; fn shl(self, shift: T) -> $name { let shift = shift.into().as_usize(); let $name(ref original) = self; let mut ret = [0u64; $n_words]; let word_shift = shift / 64; let bit_shift = shift % 64; // shift for i in word_shift..$n_words { ret[i] = original[i - word_shift] << bit_shift; } // carry if bit_shift > 0 { for i in word_shift+1..$n_words { ret[i] += original[i - 1 - word_shift] >> (64 - bit_shift); } } $name(ret) } } impl<'a, T> $crate::core_::ops::Shl for &'a $name where T: Into<$name> { type Output = $name; fn shl(self, shift: T) -> $name { *self << shift } } impl $crate::core_::ops::ShlAssign for $name where T: Into<$name> { fn shl_assign(&mut self, shift: T) { *self = *self << shift; } } impl $crate::core_::ops::Shr for $name where T: Into<$name> { type Output = $name; fn shr(self, shift: T) -> $name { let shift = shift.into().as_usize(); let $name(ref original) = self; let mut ret = [0u64; $n_words]; let word_shift = shift / 64; let bit_shift = shift % 64; // shift for i in word_shift..$n_words { ret[i - word_shift] = original[i] >> bit_shift; } // Carry if bit_shift > 0 { for i in word_shift+1..$n_words { ret[i - word_shift - 1] += original[i] << (64 - bit_shift); } } $name(ret) } } impl<'a, T> $crate::core_::ops::Shr for &'a $name where T: Into<$name> { type Output = $name; fn shr(self, shift: T) -> $name { *self >> shift } } impl $crate::core_::ops::ShrAssign for $name where T: Into<$name> { fn shr_assign(&mut self, shift: T) { *self = *self >> shift; } } impl $crate::core_::cmp::Ord for $name { fn cmp(&self, other: &$name) -> $crate::core_::cmp::Ordering { self.as_ref().iter().rev().cmp(other.as_ref().iter().rev()) } } impl $crate::core_::cmp::PartialOrd for $name { fn partial_cmp(&self, other: &$name) -> Option<$crate::core_::cmp::Ordering> { Some(self.cmp(other)) } } impl $crate::core_::fmt::Debug for $name { fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result { $crate::core_::fmt::Display::fmt(self, f) } } impl $crate::core_::fmt::Display for $name { fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result { if self.is_zero() { return $crate::core_::write!(f, "0"); } let mut buf = [0_u8; $n_words*20]; let mut i = buf.len() - 1; let mut current = *self; let ten = $name::from(10); loop { let digit = (current % ten).low_u64() as u8; buf[i] = digit + b'0'; current /= ten; if current.is_zero() { break; } i -= 1; } // sequence of `'0'..'9'` chars is guaranteed to be a valid UTF8 string let s = unsafe { $crate::core_::str::from_utf8_unchecked(&buf[i..]) }; f.pad_integral(true, "", s) } } impl $crate::core_::fmt::LowerHex for $name { fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result { self.fmt_hex(f, true) } } impl $crate::core_::fmt::UpperHex for $name { fn fmt(&self, f: &mut $crate::core_::fmt::Formatter) -> $crate::core_::fmt::Result { self.fmt_hex(f, false) } } impl $crate::core_::str::FromStr for $name { type Err = $crate::FromHexError; fn from_str(value: &str) -> $crate::core_::result::Result<$name, Self::Err> { let value = value.strip_prefix("0x").unwrap_or(value); const BYTES_LEN: usize = $n_words * 8; const MAX_ENCODED_LEN: usize = BYTES_LEN * 2; let mut bytes = [0_u8; BYTES_LEN]; let encoded = value.as_bytes(); if encoded.len() > MAX_ENCODED_LEN { return Err($crate::hex::FromHexError::InvalidStringLength.into()); } if encoded.len() % 2 == 0 { let out = &mut bytes[BYTES_LEN - encoded.len() / 2..]; $crate::hex::decode_to_slice(encoded, out).map_err(Self::Err::from)?; } else { // Prepend '0' by overlaying our value on a scratch buffer filled with '0' characters. let mut s = [b'0'; MAX_ENCODED_LEN]; s[MAX_ENCODED_LEN - encoded.len()..].copy_from_slice(encoded); let encoded = &s[MAX_ENCODED_LEN - encoded.len() - 1..]; let out = &mut bytes[BYTES_LEN - encoded.len() / 2..]; $crate::hex::decode_to_slice(encoded, out).map_err(Self::Err::from)?; } Ok(Self::from_big_endian(&bytes)) } } impl $crate::core_::convert::From<&'static str> for $name { fn from(s: &'static str) -> Self { s.parse().unwrap() } } // `$n_words * 8` because macro expects bytes and // uints use 64 bit (8 byte) words $crate::impl_quickcheck_arbitrary_for_uint!($name, ($n_words * 8)); $crate::impl_arbitrary_for_uint!($name, ($n_words * 8)); } } #[cfg(feature = "quickcheck")] #[macro_export] #[doc(hidden)] macro_rules! impl_quickcheck_arbitrary_for_uint { ($uint: ty, $n_bytes: tt) => { impl $crate::quickcheck::Arbitrary for $uint { fn arbitrary(g: &mut $crate::quickcheck::Gen) -> Self { let p = usize::arbitrary(g) % 100; // make it more likely to generate smaller numbers that // don't use up the full $n_bytes let range = // 10% chance to generate number that uses up to $n_bytes if p < 10 { $n_bytes // 10% chance to generate number that uses up to $n_bytes / 2 } else if p < 20 { $n_bytes / 2 // 80% chance to generate number that uses up to $n_bytes / 5 } else { $n_bytes / 5 }; let range = $crate::core_::cmp::max(range, 1); let size: usize = usize::arbitrary(g) % range; let res: [u8; $n_bytes] = $crate::core_::array::from_fn(|i| { if i > size { 0 } else { u8::arbitrary(g) } }); Self::from_big_endian(res.as_ref()) } } }; } #[cfg(not(feature = "quickcheck"))] #[macro_export] #[doc(hidden)] macro_rules! impl_quickcheck_arbitrary_for_uint { ($uint: ty, $n_bytes: tt) => {}; } #[cfg(feature = "arbitrary")] #[macro_export] #[doc(hidden)] macro_rules! impl_arbitrary_for_uint { ($uint: ty, $n_bytes: tt) => { impl $crate::arbitrary::Arbitrary<'_> for $uint { fn arbitrary(u: &mut $crate::arbitrary::Unstructured<'_>) -> $crate::arbitrary::Result { let mut res = [0u8; $n_bytes]; u.fill_buffer(&mut res)?; Ok(Self::from_big_endian(&res)) } } }; } #[cfg(not(feature = "arbitrary"))] #[macro_export] #[doc(hidden)] macro_rules! impl_arbitrary_for_uint { ($uint: ty, $n_bytes: tt) => {}; } uint-0.10.0/tests/uint_tests.rs000064400000000000000000001254231046102023000146010ustar 00000000000000// Copyright 2020 Parity Technologies // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use core::{convert::TryInto, str::FromStr, u64::MAX}; use crunchy::unroll; use uint::{construct_uint, overflowing, FromDecStrErr}; construct_uint! { pub struct U256(4); } construct_uint! { pub struct U512(8); } #[cfg(feature = "std")] #[test] fn hash_impl_is_the_same_as_for_a_slice() { use core::hash::{Hash, Hasher as _}; use std::collections::hash_map::DefaultHasher; let uint_hash = { let mut h = DefaultHasher::new(); let uint = U256::from(123u64); Hash::hash(&uint, &mut h); h.finish() }; let slice_hash = { let mut h = DefaultHasher::new(); Hash::hash(&[123u64, 0, 0, 0], &mut h); h.finish() }; assert_eq!(uint_hash, slice_hash); } // https://github.com/paritytech/parity-common/issues/420 #[test] fn const_matching_works() { const ONE: U256 = U256([1, 0, 0, 0]); match U256::zero() { ONE => unreachable!(), _ => {}, } } #[test] fn max() { let max = U256::MAX; assert_eq!(max.0, [0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF]); let max = U512::MAX; assert_eq!( max.0, [ 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF ] ); } #[test] fn one() { let one = U256::one(); assert_eq!(one.0, [1, 0, 0, 0]); let one = U512::one(); assert_eq!(one.0, [1, 0, 0, 0, 0, 0, 0, 0]); let any = U256::from(123456789); assert_eq!(any * U256::one(), any); let any = U512::from(123456789); assert_eq!(any * U512::one(), any); } #[test] #[allow(deprecated)] fn max_value() { let max = U256::max_value(); assert_eq!(max.0, [0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF]); let max = U512::max_value(); assert_eq!( max.0, [ 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF ] ); } #[test] fn u128_conversions() { let mut a = U256::from(u128::max_value()); assert_eq!(a.low_u128(), u128::max_value()); a += 2u128.into(); assert_eq!(a.low_u128(), 1u128); a -= 3u128.into(); assert_eq!(a.low_u128(), u128::max_value() - 1); } #[test] fn uint256_checked_ops() { let z = U256::from(0); let a = U256::from(10); let b = !U256::from(1); assert_eq!(U256::from(10).checked_pow(U256::from(0)), Some(U256::from(1))); assert_eq!(U256::from(10).checked_pow(U256::from(1)), Some(U256::from(10))); assert_eq!(U256::from(10).checked_pow(U256::from(2)), Some(U256::from(100))); assert_eq!(U256::from(10).checked_pow(U256::from(3)), Some(U256::from(1000))); assert_eq!(U256::from(10).checked_pow(U256::from(20)), Some(U256::exp10(20))); assert_eq!(U256::from(2).checked_pow(U256::from(0x100)), None); assert_eq!(U256::MAX.checked_pow(U256::from(2)), None); assert_eq!(a.checked_add(b), None); assert_eq!(a.checked_add(a), Some(20.into())); assert_eq!(a.checked_sub(b), None); assert_eq!(a.checked_sub(a), Some(0.into())); assert_eq!(a.checked_mul(b), None); assert_eq!(a.checked_mul(a), Some(100.into())); assert_eq!(a.checked_div(z), None); assert_eq!(a.checked_div(a), Some(1.into())); assert_eq!(a.checked_rem(z), None); assert_eq!(a.checked_rem(a), Some(0.into())); assert_eq!(a.checked_neg(), None); assert_eq!(z.checked_neg(), Some(z)); } #[test] fn uint256_abs_diff() { let zero = U256::zero(); let max = U256::MAX; assert_eq!(zero.abs_diff(zero), zero); assert_eq!(max.abs_diff(max), zero); assert_eq!(zero.abs_diff(max), max); assert_eq!(max.abs_diff(zero), max); } #[test] fn uint256_from() { let e = U256([10, 0, 0, 0]); // test unsigned initialization let ua = U256::from(10u8); let ub = U256::from(10u16); let uc = U256::from(10u32); let ud = U256::from(10u64); assert_eq!(e, ua); assert_eq!(e, ub); assert_eq!(e, uc); assert_eq!(e, ud); // test initialization from bytes let va = U256::from_big_endian(&[10u8][..]); assert_eq!(e, va); // more tests for initialization from bytes assert_eq!(U256([0x1010, 0, 0, 0]), U256::from_big_endian(&[0x10u8, 0x10][..])); assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_big_endian(&[0x12u8, 0xf0][..])); assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_big_endian(&[0, 0x12u8, 0xf0][..])); assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_big_endian(&[0, 0, 0, 0, 0, 0, 0, 0x12u8, 0xf0][..])); assert_eq!(U256([0x12f0, 1, 0, 0]), U256::from_big_endian(&[1, 0, 0, 0, 0, 0, 0, 0x12u8, 0xf0][..])); assert_eq!( U256([0x12f0, 1, 0x0910203040506077, 0x8090a0b0c0d0e0f0]), U256::from_big_endian( &[ 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x77, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x12u8, 0xf0 ][..] ) ); assert_eq!( U256([0x00192437100019fa, 0x243710, 0, 0]), U256::from_big_endian(&[0x24u8, 0x37, 0x10, 0, 0x19, 0x24, 0x37, 0x10, 0, 0x19, 0xfa][..]) ); // test initializtion from string let sa = U256::from_str("0a").unwrap(); let sa2 = U256::from_str("0x0a").unwrap(); assert_eq!(sa2, sa); assert_eq!(e, sa); assert_eq!(U256([0, 0, 0, 0]), U256::from_str("").unwrap()); assert_eq!(U256([0x1, 0, 0, 0]), U256::from_str("1").unwrap()); assert_eq!(U256([0x101, 0, 0, 0]), U256::from_str("101").unwrap()); assert_eq!(U256([0x1010, 0, 0, 0]), U256::from_str("1010").unwrap()); assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("0000000012f0").unwrap()); assert_eq!(U256([0x12f0, 1, 0, 0]), U256::from_str("0100000000000012f0").unwrap()); assert_eq!( U256([0x12f0, 1, 0x0910203040506077, 0x8090a0b0c0d0e0f0]), U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap() ); // This string contains more bits than what fits in a U256. assert!(U256::from_str("000000000000000000000000000000000000000000000000000000000000000000").is_err()); assert!(U256::from_str("100000000000000000000000000000000000000000000000000000000000000000").is_err()); } #[test] fn uint256_try_into_primitives() { macro_rules! try_into_uint_primitive_ok { ($primitive: ty) => { assert_eq!(U256::from(10).try_into() as Result<$primitive, _>, Ok(<$primitive>::from(10u8))); }; } try_into_uint_primitive_ok!(u8); try_into_uint_primitive_ok!(u16); try_into_uint_primitive_ok!(u32); try_into_uint_primitive_ok!(usize); try_into_uint_primitive_ok!(u64); try_into_uint_primitive_ok!(u128); macro_rules! try_into_iint_primitive_ok { ($primitive: ty) => { assert_eq!(U256::from(10).try_into() as Result<$primitive, _>, Ok(<$primitive>::from(10i8))); }; } try_into_iint_primitive_ok!(i8); try_into_iint_primitive_ok!(i16); try_into_iint_primitive_ok!(i32); try_into_iint_primitive_ok!(isize); try_into_iint_primitive_ok!(i64); try_into_iint_primitive_ok!(i128); macro_rules! try_into_primitive_err { ($small: ty, $big: ty) => { assert_eq!( U256::from(<$small>::max_value() as $big + 1).try_into() as Result<$small, _>, Err(concat!("integer overflow when casting to ", stringify!($small))) ); }; } try_into_primitive_err!(u8, u16); try_into_primitive_err!(u16, u32); try_into_primitive_err!(u32, u64); try_into_primitive_err!(usize, u128); try_into_primitive_err!(u64, u128); assert_eq!(U256([0, 0, 1, 0]).try_into() as Result, Err("integer overflow when casting to u128")); try_into_primitive_err!(i8, i16); try_into_primitive_err!(i16, i32); try_into_primitive_err!(i32, i64); try_into_primitive_err!(isize, i128); try_into_primitive_err!(i64, i128); try_into_primitive_err!(i128, u128); assert_eq!(U256([0, 0, 1, 0]).try_into() as Result, Err("integer overflow when casting to i128")); } #[test] fn uint256_to() { let hex = "8090a0b0c0d0e0f00910203040506077583a2cf8264910e1436bda32571012f0"; let uint = U256::from_str(hex).unwrap(); let bytes = uint.to_big_endian(); let uint2 = U256::from_big_endian(&bytes[..]); assert_eq!(uint, uint2); } #[test] fn uint256_bits_test() { assert_eq!(U256::from(0u64).bits(), 0); assert_eq!(U256::from(255u64).bits(), 8); assert_eq!(U256::from(256u64).bits(), 9); assert_eq!(U256::from(300u64).bits(), 9); assert_eq!(U256::from(60000u64).bits(), 16); assert_eq!(U256::from(70000u64).bits(), 17); //// Try to read the following lines out loud quickly let mut shl = U256::from(70000u64); shl = shl << 100; assert_eq!(shl.bits(), 117); shl = shl << 100; assert_eq!(shl.bits(), 217); shl = shl << 100; assert_eq!(shl.bits(), 0); //// Bit set check //// 01010 assert!(!U256::from(10u8).bit(0)); assert!(U256::from(10u8).bit(1)); assert!(!U256::from(10u8).bit(2)); assert!(U256::from(10u8).bit(3)); assert!(!U256::from(10u8).bit(4)); //// byte check assert_eq!(U256::from(10u8).byte(0), 10); assert_eq!(U256::from(0xffu64).byte(0), 0xff); assert_eq!(U256::from(0xffu64).byte(1), 0); assert_eq!(U256::from(0x01ffu64).byte(0), 0xff); assert_eq!(U256::from(0x01ffu64).byte(1), 0x1); assert_eq!(U256([0u64, 0xfc, 0, 0]).byte(8), 0xfc); assert_eq!(U256([0u64, 0, 0, u64::max_value()]).byte(31), 0xff); assert_eq!(U256([0u64, 0, 0, (u64::max_value() >> 8) + 1]).byte(31), 0x01); } #[test] fn uint256_comp_test() { let small = U256([10u64, 0, 0, 0]); let big = U256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]); let bigger = U256([0x9C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]); let biggest = U256([0x5C8C3EE70C644118u64, 0x0209E7378231E632, 0, 1]); assert!(small < big); assert!(big < bigger); assert!(bigger < biggest); assert!(bigger <= biggest); assert!(biggest <= biggest); assert!(bigger >= big); assert!(bigger >= small); assert!(small <= small); assert_eq!(small, small); assert_eq!(biggest, biggest); assert_ne!(big, biggest); assert_ne!(big, bigger); } #[test] fn uint256_arithmetic_test() { let init = U256::from(0xDEADBEEFDEADBEEFu64); let copy = init; let add = init + copy; assert_eq!(add, U256([0xBD5B7DDFBD5B7DDEu64, 1, 0, 0])); // Bitshifts let shl = add << 88; assert_eq!(shl, U256([0u64, 0xDFBD5B7DDE000000, 0x1BD5B7D, 0])); let shr = shl >> 40; assert_eq!(shr, U256([0x7DDE000000000000u64, 0x0001BD5B7DDFBD5B, 0, 0])); // Increment let incr = shr + U256::from(1u64); assert_eq!(incr, U256([0x7DDE000000000001u64, 0x0001BD5B7DDFBD5B, 0, 0])); // Subtraction let sub = overflowing!(incr.overflowing_sub(init)); assert_eq!(sub, U256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0])); // Multiplication let mult = sub * 300u32; assert_eq!(mult, U256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0])); // Division assert_eq!(U256::from(105u8) / U256::from(5u8), U256::from(21u8)); let div = mult / U256::from(300u16); assert_eq!(div, U256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0])); let a = U256::from_str("ff000000000000000000000000000000000000000000000000000000000000d1").unwrap(); let b = U256::from_str("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2e").unwrap(); println!("{:x}", a); println!("{:x}", b); assert_eq!(!a, b); assert_eq!(a, !b); } #[test] fn uint256_simple_mul() { let a = U256::from_str("10000000000000000").unwrap(); let b = U256::from_str("10000000000000000").unwrap(); let c = U256::from_str("100000000000000000000000000000000").unwrap(); println!("Multiplying"); let result = a.overflowing_mul(b); println!("Got result"); assert_eq!(result, (c, false)) } #[test] fn uint256_extreme_bitshift_test() { //// Shifting a u64 by 64 bits gives an undefined value, so make sure that //// we're doing the Right Thing here let init = U256::from(0xDEADBEEFDEADBEEFu64); assert_eq!(init << 64, U256([0, 0xDEADBEEFDEADBEEF, 0, 0])); let add = (init << 64) + init; assert_eq!(add, U256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); assert_eq!(add >> 0, U256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); assert_eq!(add << 0, U256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); assert_eq!(add >> 64, U256([0xDEADBEEFDEADBEEF, 0, 0, 0])); assert_eq!(add << 64, U256([0, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0])); } #[test] fn uint256_exp10() { assert_eq!(U256::exp10(0), U256::from(1u64)); println!("\none: {:?}", U256::from(1u64)); println!("ten: {:?}", U256::from(10u64)); assert_eq!(U256::from(2u64) * U256::from(10u64), U256::from(20u64)); assert_eq!(U256::exp10(1), U256::from(10u64)); assert_eq!(U256::exp10(2), U256::from(100u64)); assert_eq!(U256::exp10(5), U256::from(100000u64)); } #[test] fn uint256_mul32() { assert_eq!(U256::from(0u64) * 2u32, U256::from(0u64)); assert_eq!(U256::from(1u64) * 2u32, U256::from(2u64)); assert_eq!(U256::from(10u64) * 2u32, U256::from(20u64)); assert_eq!(U256::from(10u64) * 5u32, U256::from(50u64)); assert_eq!(U256::from(1000u64) * 50u32, U256::from(50000u64)); } #[test] fn uint256_pow() { assert_eq!(U256::from(10).pow(U256::from(0)), U256::from(1)); assert_eq!(U256::from(10).pow(U256::from(1)), U256::from(10)); assert_eq!(U256::from(10).pow(U256::from(2)), U256::from(100)); assert_eq!(U256::from(10).pow(U256::from(3)), U256::from(1000)); assert_eq!(U256::from(10).pow(U256::from(20)), U256::exp10(20)); } #[test] #[should_panic] fn uint256_pow_overflow_panic() { U256::from(2).pow(U256::from(0x100)); } #[test] fn should_format_and_debug_correctly() { let test = |x: usize, hex: &'static str, display: &'static str| { assert_eq!(format!("{}", U256::from(x)), display); // TODO: proper impl for Debug so we get this to pass: assert_eq!(format!("{:?}", U256::from(x)), format!("0x{}", hex)); assert_eq!(format!("{:?}", U256::from(x)), display); assert_eq!(format!("{:x}", U256::from(x)), hex); assert_eq!(format!("{:#x}", U256::from(x)), format!("0x{}", hex)); }; test(0x1, "1", "1"); test(0xf, "f", "15"); test(0x10, "10", "16"); test(0xff, "ff", "255"); test(0x100, "100", "256"); test(0xfff, "fff", "4095"); test(0x1000, "1000", "4096"); } #[test] pub fn display_u256() { let expected = "115792089237316195423570985008687907853269984665640564039457584007913129639935"; let value = U256::MAX; assert_eq!(format!("{}", value), expected); assert_eq!(format!("{:?}", value), expected); } #[test] pub fn display_u512() { let expected = "13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095"; let value = U512::MAX; assert_eq!(format!("{}", value), expected); assert_eq!(format!("{:?}", value), expected); } #[test] fn uint256_overflowing_pow() { assert_eq!( U256::from(2).overflowing_pow(U256::from(0xff)), (U256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap(), false) ); assert_eq!(U256::from(2).overflowing_pow(U256::from(0x100)), (U256::zero(), true)); } #[test] fn uint256_mul1() { assert_eq!(U256::from(1u64) * U256::from(10u64), U256::from(10u64)); } #[test] fn uint256_mul2() { let a = U512::from_str("10000000000000000fffffffffffffffe").unwrap(); let b = U512::from_str("ffffffffffffffffffffffffffffffff").unwrap(); assert_eq!(a * b, U512::from_str("10000000000000000fffffffffffffffcffffffffffffffff0000000000000002").unwrap()); } #[test] fn uint256_overflowing_mul() { assert_eq!( U256::from_str("100000000000000000000000000000000") .unwrap() .overflowing_mul(U256::from_str("100000000000000000000000000000000").unwrap()), (U256::zero(), true) ); } #[test] fn uint512_mul() { assert_eq!( U512::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() * U512::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(), U512::from_str("3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001").unwrap() ); } #[test] fn uint256_mul_overflow() { assert_eq!( U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") .unwrap() .overflowing_mul( U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() ), (U256::from_str("1").unwrap(), true) ); } #[test] #[should_panic] #[allow(unused_must_use)] fn uint256_mul_overflow_panic() { U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() * U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(); } #[test] fn uint256_sub_overflow() { assert_eq!( U256::from_str("0").unwrap().overflowing_sub(U256::from_str("1").unwrap()), (U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(), true) ); } #[test] fn uint256_neg_overflow() { assert_eq!(U256::from_str("0").unwrap().overflowing_neg(), (U256::from_str("0").unwrap(), false)); assert_eq!( U256::from_str("1").unwrap().overflowing_neg(), (U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(), true) ); assert_eq!( U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") .unwrap() .overflowing_neg(), (U256::from_str("1").unwrap(), true) ); assert_eq!( U256::from_str("8000000000000000000000000000000000000000000000000000000000000000") .unwrap() .overflowing_neg(), (U256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap(), true) ); assert_eq!( U256::from_str("ffffffffffffffff0000000000000000ffffffffffffffff0000000000000000") .unwrap() .overflowing_neg(), (U256::from_str("0000000000000000ffffffffffffffff00000000000000010000000000000000").unwrap(), true) ); assert_eq!( U256::from_str("0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff") .unwrap() .overflowing_neg(), (U256::from_str("ffffffffffffffff0000000000000000ffffffffffffffff0000000000000001").unwrap(), true) ); } #[test] #[should_panic] #[allow(unused_must_use)] fn uint256_sub_overflow_panic() { U256::from_str("0").unwrap() - U256::from_str("1").unwrap(); } #[test] fn uint256_shl() { assert_eq!( U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() << 4, U256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0").unwrap() ); } #[test] fn uint256_shl_words() { assert_eq!( U256::from_str("0000000000000001ffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() << 64, U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000").unwrap() ); assert_eq!( U256::from_str("0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() << 64, U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000").unwrap() ); } #[test] fn uint256_mul() { assert_eq!( U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() * U256::from_str("2").unwrap(), U256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe").unwrap() ); } #[test] fn uint256_div() { assert_eq!(U256::from(10u64) / U256::from(1u64), U256::from(10u64)); assert_eq!(U256::from(10u64) / U256::from(2u64), U256::from(5u64)); assert_eq!(U256::from(10u64) / U256::from(3u64), U256::from(3u64)); } #[test] fn uint256_rem() { assert_eq!(U256::from(10u64) % U256::from(1u64), U256::from(0u64)); assert_eq!(U256::from(10u64) % U256::from(3u64), U256::from(1u64)); } #[test] fn uint256_from_dec_str() { assert_eq!(U256::from_dec_str("10").unwrap(), U256::from(10u64)); assert_eq!(U256::from_dec_str("1024").unwrap(), U256::from(1024u64)); assert_eq!( U256::from_dec_str("115792089237316195423570985008687907853269984665640564039457584007913129639936"), Err(FromDecStrErr::InvalidLength) ); assert_eq!(U256::from_dec_str("0x11"), Err(FromDecStrErr::InvalidCharacter)); } #[test] fn display_uint() { let s = U256::from_dec_str("12345678987654321023456789").unwrap(); assert_eq!(format!("{}", s), "12345678987654321023456789"); assert_eq!(format!("{:x}", s), "a364c995584f929f39615"); assert_eq!(format!("{:X}", s), "A364C995584F929F39615"); assert_eq!(format!("{:032}", s), "00000012345678987654321023456789"); assert_eq!(format!("{:032x}", s), "00000000000a364c995584f929f39615"); assert_eq!(format!("{:032X}", s), "00000000000A364C995584F929F39615"); assert_eq!(format!("{:#032x}", s), "0x000000000a364c995584f929f39615"); assert_eq!(format!("{:#032X}", s), "0x000000000A364C995584F929F39615"); } #[test] fn display_uint_zero() { let s = U256::from(0); assert_eq!(format!("{}", s), "0"); assert_eq!(format!("{:x}", s), "0"); assert_eq!(format!("{:X}", s), "0"); assert_eq!(format!("{:032x}", s), "00000000000000000000000000000000"); assert_eq!(format!("{:032X}", s), "00000000000000000000000000000000"); assert_eq!(format!("{:#032x}", s), "0x000000000000000000000000000000"); assert_eq!(format!("{:#032X}", s), "0x000000000000000000000000000000"); } #[test] fn u512_multi_adds() { let (result, _) = U512([0, 0, 0, 0, 0, 0, 0, 0]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, 0])); assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 0, 0])); let (result, _) = U512([1, 0, 0, 0, 0, 0, 0, 1]).overflowing_add(U512([1, 0, 0, 0, 0, 0, 0, 1])); assert_eq!(result, U512([2, 0, 0, 0, 0, 0, 0, 2])); let (result, _) = U512([0, 0, 0, 0, 0, 0, 0, 1]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, 1])); assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 0, 2])); let (result, _) = U512([0, 0, 0, 0, 0, 0, 2, 1]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 3, 1])); assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 5, 2])); let (result, _) = U512([1, 2, 3, 4, 5, 6, 7, 8]).overflowing_add(U512([9, 10, 11, 12, 13, 14, 15, 16])); assert_eq!(result, U512([10, 12, 14, 16, 18, 20, 22, 24])); let (_, overflow) = U512([0, 0, 0, 0, 0, 0, 2, 1]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 3, 1])); assert!(!overflow); let (_, overflow) = U512([MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX]).overflowing_add(U512([MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX])); assert!(overflow); let (_, overflow) = U512([0, 0, 0, 0, 0, 0, 0, MAX]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, MAX])); assert!(overflow); let (_, overflow) = U512([0, 0, 0, 0, 0, 0, 0, MAX]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, 0])); assert!(!overflow); } #[test] fn u256_multi_adds() { let (result, _) = U256([0, 0, 0, 0]).overflowing_add(U256([0, 0, 0, 0])); assert_eq!(result, U256([0, 0, 0, 0])); let (result, _) = U256([0, 0, 0, 1]).overflowing_add(U256([0, 0, 0, 1])); assert_eq!(result, U256([0, 0, 0, 2])); let (result, overflow) = U256([0, 0, 2, 1]).overflowing_add(U256([0, 0, 3, 1])); assert_eq!(result, U256([0, 0, 5, 2])); assert!(!overflow); let (_, overflow) = U256([MAX, MAX, MAX, MAX]).overflowing_add(U256([MAX, MAX, MAX, MAX])); assert!(overflow); let (_, overflow) = U256([0, 0, 0, MAX]).overflowing_add(U256([0, 0, 0, MAX])); assert!(overflow); } #[test] fn u256_multi_subs() { let (result, _) = U256([0, 0, 0, 0]).overflowing_sub(U256([0, 0, 0, 0])); assert_eq!(result, U256([0, 0, 0, 0])); let (result, _) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 0, 1])); assert_eq!(result, U256([0, 0, 0, 0])); let (_, overflow) = U256([0, 0, 2, 1]).overflowing_sub(U256([0, 0, 3, 1])); assert!(overflow); let (result, overflow) = U256([MAX, MAX, MAX, MAX]).overflowing_sub(U256([MAX / 2, MAX / 2, MAX / 2, MAX / 2])); assert!(!overflow); assert_eq!(U256([MAX / 2 + 1, MAX / 2 + 1, MAX / 2 + 1, MAX / 2 + 1]), result); let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 1, 0])); assert!(!overflow); assert_eq!(U256([0, 0, MAX, 0]), result); let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([1, 0, 0, 0])); assert!(!overflow); assert_eq!(U256([MAX, MAX, MAX, 0]), result); } #[test] fn u512_multi_subs() { let (result, _) = U512([0, 0, 0, 0, 0, 0, 0, 0]).overflowing_sub(U512([0, 0, 0, 0, 0, 0, 0, 0])); assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 0, 0])); let (result, _) = U512([10, 9, 8, 7, 6, 5, 4, 3]).overflowing_sub(U512([9, 8, 7, 6, 5, 4, 3, 2])); assert_eq!(result, U512([1, 1, 1, 1, 1, 1, 1, 1])); let (_, overflow) = U512([10, 9, 8, 7, 6, 5, 4, 3]).overflowing_sub(U512([9, 8, 7, 6, 5, 4, 3, 2])); assert!(!overflow); let (_, overflow) = U512([9, 8, 7, 6, 5, 4, 3, 2]).overflowing_sub(U512([10, 9, 8, 7, 6, 5, 4, 3])); assert!(overflow); } #[test] fn u256_multi_carry_all() { let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); assert_eq!(U256([1, MAX - 1, 0, 0]), result); let (result, _) = U256([0, MAX, 0, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); assert_eq!(U256([0, 1, MAX - 1, 0]), result); let (result, _) = U256([MAX, MAX, 0, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); assert_eq!(U256([1, MAX, MAX - 1, 0]), result); let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul(U256([MAX, MAX, 0, 0])); assert_eq!(U256([1, MAX, MAX - 1, 0]), result); let (result, _) = U256([MAX, MAX, 0, 0]).overflowing_mul(U256([MAX, MAX, 0, 0])); assert_eq!(U256([1, 0, MAX - 1, MAX]), result); let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul(U256([MAX, MAX, MAX, 0])); assert_eq!(U256([1, MAX, MAX, MAX - 1]), result); let (result, _) = U256([MAX, MAX, MAX, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); assert_eq!(U256([1, MAX, MAX, MAX - 1]), result); let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul(U256([MAX, MAX, MAX, MAX])); assert_eq!(U256([1, MAX, MAX, MAX]), result); let (result, _) = U256([MAX, MAX, MAX, MAX]).overflowing_mul(U256([MAX, 0, 0, 0])); assert_eq!(U256([1, MAX, MAX, MAX]), result); let (result, _) = U256([MAX, MAX, MAX, 0]).overflowing_mul(U256([MAX, MAX, 0, 0])); assert_eq!(U256([1, 0, MAX, MAX - 1]), result); let (result, _) = U256([MAX, MAX, 0, 0]).overflowing_mul(U256([MAX, MAX, MAX, 0])); assert_eq!(U256([1, 0, MAX, MAX - 1]), result); let (result, _) = U256([MAX, MAX, MAX, MAX]).overflowing_mul(U256([MAX, MAX, 0, 0])); assert_eq!(U256([1, 0, MAX, MAX]), result); let (result, _) = U256([MAX, MAX, 0, 0]).overflowing_mul(U256([MAX, MAX, MAX, MAX])); assert_eq!(U256([1, 0, MAX, MAX]), result); let (result, _) = U256([MAX, MAX, MAX, 0]).overflowing_mul(U256([MAX, MAX, MAX, 0])); assert_eq!(U256([1, 0, 0, MAX - 1]), result); let (result, _) = U256([MAX, MAX, MAX, 0]).overflowing_mul(U256([MAX, MAX, MAX, MAX])); assert_eq!(U256([1, 0, 0, MAX]), result); let (result, _) = U256([MAX, MAX, MAX, MAX]).overflowing_mul(U256([MAX, MAX, MAX, 0])); assert_eq!(U256([1, 0, 0, MAX]), result); let (result, _) = U256([0, 0, 0, MAX]).overflowing_mul(U256([0, 0, 0, MAX])); assert_eq!(U256([0, 0, 0, 0]), result); let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); assert_eq!(U256([0, 0, 0, MAX]), result); let (result, _) = U256([MAX, MAX, MAX, MAX]).overflowing_mul(U256([MAX, MAX, MAX, MAX])); assert_eq!(U256([1, 0, 0, 0]), result); } #[test] fn u256_multi_muls() { let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); assert_eq!(U256([0, 0, 0, 0]), result); let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([1, 0, 0, 0])); assert_eq!(U256([1, 0, 0, 0]), result); let (result, _) = U256([5, 0, 0, 0]).overflowing_mul(U256([5, 0, 0, 0])); assert_eq!(U256([25, 0, 0, 0]), result); let (result, _) = U256([0, 5, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); assert_eq!(U256([0, 0, 25, 0]), result); let (result, _) = U256([0, 0, 0, 1]).overflowing_mul(U256([1, 0, 0, 0])); assert_eq!(U256([0, 0, 0, 1]), result); let (result, _) = U256([0, 0, 0, 5]).overflowing_mul(U256([2, 0, 0, 0])); assert_eq!(U256([0, 0, 0, 10]), result); let (result, _) = U256([0, 0, 1, 0]).overflowing_mul(U256([0, 5, 0, 0])); assert_eq!(U256([0, 0, 0, 5]), result); let (result, _) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); assert_eq!(U256([0, 0, 0, 0]), result); let (result, _) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); assert_eq!(U256([0, 10, 0, 0]), result); let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); assert_eq!(U256([0, 0, 0, MAX]), result); } #[test] fn u256_multi_muls_overflow() { let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); assert!(!overflow); let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); assert!(!overflow); let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); assert!(overflow); let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 1, 0, 0])); assert!(!overflow); let (_, overflow) = U256([0, 1, 0, MAX]).overflowing_mul(U256([0, 1, 0, MAX])); assert!(overflow); let (_, overflow) = U256([0, MAX, 0, 0]).overflowing_mul(U256([0, MAX, 0, 0])); assert!(!overflow); let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([10, 0, 0, 0])); assert!(!overflow); let (_, overflow) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX / 2])); assert!(!overflow); let (_, overflow) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); assert!(overflow); } #[test] fn u512_div() { let fuzz_data = [ 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0x7, 0x0, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ]; let a = U512::from_little_endian(&fuzz_data[..64]); let b = U512::from_little_endian(&fuzz_data[64..]); let (x, y) = (a / b, a % b); let (q, r) = a.div_mod(b); assert_eq!((x, y), (q, r)); } #[test] fn big_endian() { let source = U256([1, 0, 0, 0]); let mut target = vec![0u8; 32]; assert_eq!(source, U256::from(1)); source.write_as_big_endian(&mut target); assert_eq!( vec![ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8 ], target ); let source = U256([512, 0, 0, 0]); let mut target = vec![0u8; 32]; source.write_as_big_endian(&mut target); assert_eq!( vec![ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8 ], target ); let source = U256([0, 512, 0, 0]); let mut target = vec![0u8; 32]; source.write_as_big_endian(&mut target); assert_eq!( vec![ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8 ], target ); let source = U256::from_str("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20").unwrap(); source.write_as_big_endian(&mut target); assert_eq!( vec![ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 ], target ); } #[test] fn u256_multi_muls2() { let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); assert_eq!(U256([0, 0, 0, 0]), result); let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([1, 0, 0, 0])); assert_eq!(U256([1, 0, 0, 0]), result); let (result, _) = U256([5, 0, 0, 0]).overflowing_mul(U256([5, 0, 0, 0])); assert_eq!(U256([25, 0, 0, 0]), result); let (result, _) = U256([0, 5, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); assert_eq!(U256([0, 0, 25, 0]), result); let (result, _) = U256([0, 0, 0, 1]).overflowing_mul(U256([1, 0, 0, 0])); assert_eq!(U256([0, 0, 0, 1]), result); let (result, _) = U256([0, 0, 0, 5]).overflowing_mul(U256([2, 0, 0, 0])); assert_eq!(U256([0, 0, 0, 10]), result); let (result, _) = U256([0, 0, 1, 0]).overflowing_mul(U256([0, 5, 0, 0])); assert_eq!(U256([0, 0, 0, 5]), result); let (result, _) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); assert_eq!(U256([0, 0, 0, 0]), result); let (result, _) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); assert_eq!(U256([0, 10, 0, 0]), result); let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, u64::max_value()])); assert_eq!(U256([0, 0, 0, u64::max_value()]), result); let x1: U256 = "0000000000000000000000000000000000000000000000000000012365124623".into(); let x2sqr_right: U256 = "000000000000000000000000000000000000000000014baeef72e0378e2328c9".into(); let x1sqr = x1 * x1; assert_eq!(x2sqr_right, x1sqr); let x1cube = x1sqr * x1; let x1cube_right: U256 = "0000000000000000000000000000000001798acde139361466f712813717897b".into(); assert_eq!(x1cube_right, x1cube); let x1quad = x1cube * x1; let x1quad_right: U256 = "000000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1".into(); assert_eq!(x1quad_right, x1quad); let x1penta = x1quad * x1; let x1penta_right: U256 = "00000000000001e92875ac24be246e1c57e0507e8c46cc8d233b77f6f4c72993".into(); assert_eq!(x1penta_right, x1penta); let x1septima = x1penta * x1; let x1septima_right: U256 = "00022cca1da3f6e5722b7d3cc5bbfb486465ebc5a708dd293042f932d7eee119".into(); assert_eq!(x1septima_right, x1septima); } #[test] fn example() { let mut val: U256 = 1023.into(); for _ in 0..200 { val = val * U256::from(2) } assert_eq!(&format!("{}", val), "1643897619276947051879427220465009342380213662639797070513307648"); } #[test] fn little_endian() { let number: U256 = "00022cca1da3f6e5722b7d3cc5bbfb486465ebc5a708dd293042f932d7eee119".into(); let expected = [ 0x19, 0xe1, 0xee, 0xd7, 0x32, 0xf9, 0x42, 0x30, 0x29, 0xdd, 0x08, 0xa7, 0xc5, 0xeb, 0x65, 0x64, 0x48, 0xfb, 0xbb, 0xc5, 0x3c, 0x7d, 0x2b, 0x72, 0xe5, 0xf6, 0xa3, 0x1d, 0xca, 0x2c, 0x02, 0x00, ]; let mut result = [0u8; 32]; number.write_as_little_endian(&mut result); assert_eq!(expected, result); } #[test] fn slice_roundtrip() { let raw = [ 1u8, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, ]; let u256 = U256::from_big_endian(&raw[..]); let mut new_raw = [0u8; 32]; u256.write_as_big_endian(&mut new_raw); assert_eq!(&raw, &new_raw); } #[test] fn slice_roundtrip_le() { let raw = [ 1u8, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, ]; let u256 = U256::from_little_endian(&raw[..]); let mut new_raw = [0u8; 32]; u256.write_as_little_endian(&mut new_raw); assert_eq!(&raw, &new_raw); } #[test] fn slice_roundtrip_le2() { let raw = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, ]; let u256 = U256::from_little_endian(&raw[..]); let mut new_raw = [0u8; 32]; u256.write_as_little_endian(&mut new_raw); assert_eq!(&raw, &new_raw[..31]); } #[test] fn from_little_endian() { let source: [u8; 32] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let number = U256::from_little_endian(&source[..]); assert_eq!(U256::from(1), number); } #[test] fn from_big_endian() { let source: [u8; 32] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; let number = U256::from_big_endian(&source[..]); assert_eq!(U256::from(1), number); let number = U256::from_big_endian(&[]); assert_eq!(U256::zero(), number); let number = U256::from_big_endian(&[1]); assert_eq!(U256::from(1), number); } #[test] fn into_fixed_array() { let expected: [u8; 32] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; let ary: [u8; 32] = U256::from(1).to_big_endian(); assert_eq!(ary, expected); } #[test] fn test_u256_from_fixed_array() { let ary = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 123]; let num = U256::from_big_endian(&ary); assert_eq!(num, U256::from(core::u64::MAX) + 1 + 123); let a_ref = &U256::from_big_endian(&ary); assert_eq!(a_ref, &(U256::from(core::u64::MAX) + 1 + 123)); } #[test] fn test_from_ref_to_fixed_array() { let ary: &[u8; 32] = &[1, 0, 1, 2, 1, 0, 1, 2, 3, 0, 3, 4, 3, 0, 3, 4, 5, 0, 5, 6, 5, 0, 5, 6, 7, 0, 7, 8, 7, 0, 7, 8]; let big = U256::from_big_endian(ary); // the numbers are each row of 8 bytes reversed and cast to u64 assert_eq!(big, U256([504410889324070664, 360293493601469702, 216176097878868740, 72058702156267778u64])); } #[test] fn test_u512_from_fixed_array() { let ary = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, ]; let num = U512::from_big_endian(&ary); assert_eq!(num, U512::from(123)); let a_ref = U512::from_big_endian(&ary); assert_eq!(a_ref, U512::from(123)); } #[test] fn leading_zeros() { assert_eq!(U256::from("000000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1").leading_zeros(), 95); assert_eq!(U256::from("f00000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1").leading_zeros(), 0); assert_eq!(U256::from("0000000000000000000000000000000000000000000000000000000000000001").leading_zeros(), 255); assert_eq!(U256::from("0000000000000000000000000000000000000000000000000000000000000000").leading_zeros(), 256); } #[test] fn issue_507_roundtrip() { let mut b32 = <[u8; 32]>::default(); let a = U256::from(10); a.write_as_little_endian(&mut b32); let b = U256::from_little_endian(&b32[..]); assert_eq!(a, b); } #[test] fn trailing_zeros() { assert_eq!(U256::from("1adbdd6bd6ff027485484b97f8a6a4c7129756dd100000000000000000000000").trailing_zeros(), 92); assert_eq!(U256::from("1adbdd6bd6ff027485484b97f8a6a4c7129756dd10000000000000000000000f").trailing_zeros(), 0); assert_eq!(U256::from("8000000000000000000000000000000000000000000000000000000000000000").trailing_zeros(), 255); assert_eq!(U256::from("0000000000000000000000000000000000000000000000000000000000000000").trailing_zeros(), 256); } #[test] fn bit_assign() { fn check(a: U256, b: U256) { // and { let mut x = a; x &= b; assert_eq!(x, a & b); } // or { let mut x = a; x |= b; assert_eq!(x, a | b); } // xor { let mut x = a; x ^= b; assert_eq!(x, a ^ b); } // shr { let mut x = a; x >>= b; assert_eq!(x, a >> b); } // shl { let mut x = a; x <<= b; assert_eq!(x, a << b); } } check(U256::from(9), U256::from(999999)); check(U256::from(0), U256::from(0)); check(U256::from(23432), U256::from(u32::MAX)); check(U256::MAX, U256::zero()); } #[cfg(feature = "quickcheck")] pub mod laws { use super::construct_uint; macro_rules! uint_laws { ($mod_name:ident, $uint_ty:ident) => { mod $mod_name { use quickcheck::{TestResult, quickcheck}; use super::$uint_ty; quickcheck! { fn associative_add(x: $uint_ty, y: $uint_ty, z: $uint_ty) -> TestResult { if x.overflowing_add(y).1 || y.overflowing_add(z).1 || (x + y).overflowing_add(z).1 { return TestResult::discard(); } TestResult::from_bool( (x + y) + z == x + (y + z) ) } } quickcheck! { fn associative_mul(x: $uint_ty, y: $uint_ty, z: $uint_ty) -> TestResult { if x.overflowing_mul(y).1 || y.overflowing_mul(z).1 || (x * y).overflowing_mul(z).1 { return TestResult::discard(); } TestResult::from_bool( (x * y) * z == x * (y * z) ) } } quickcheck! { fn commutative_add(x: $uint_ty, y: $uint_ty) -> TestResult { if x.overflowing_add(y).1 { return TestResult::discard(); } TestResult::from_bool( x + y == y + x ) } } quickcheck! { fn commutative_mul(x: $uint_ty, y: $uint_ty) -> TestResult { if x.overflowing_mul(y).1 { return TestResult::discard(); } TestResult::from_bool( x * y == y * x ) } } quickcheck! { fn identity_add(x: $uint_ty) -> bool { x + $uint_ty::zero() == x } } quickcheck! { fn identity_mul(x: $uint_ty) -> bool { x * $uint_ty::one() == x } } quickcheck! { fn identity_div(x: $uint_ty) -> bool { x / $uint_ty::one() == x } } quickcheck! { fn absorbing_rem(x: $uint_ty) -> bool { x % $uint_ty::one() == $uint_ty::zero() } } quickcheck! { fn absorbing_sub(x: $uint_ty) -> bool { x - x == $uint_ty::zero() } } quickcheck! { fn absorbing_mul(x: $uint_ty) -> bool { x * $uint_ty::zero() == $uint_ty::zero() } } quickcheck! { fn distributive_mul_over_add(x: $uint_ty, y: $uint_ty, z: $uint_ty) -> TestResult { if y.overflowing_add(z).1 || x.overflowing_mul(y + z).1 || x.overflowing_add(y).1 || (x + y).overflowing_mul(z).1 { return TestResult::discard(); } TestResult::from_bool( (x * (y + z) == (x * y + x * z)) && (((x + y) * z) == (x * z + y * z)) ) } } quickcheck! { fn isqrt(x: $uint_ty) -> TestResult { let s = x.integer_sqrt(); let higher = s + 1; if let Some(y) = higher.checked_mul(higher) { TestResult::from_bool( (s * s <= x) && (y > x) ) } else { TestResult::from_bool( s * s <= x ) } } } quickcheck! { fn pow_mul(x: $uint_ty) -> TestResult { if x.overflowing_pow($uint_ty::from(2)).1 || x.overflowing_pow($uint_ty::from(3)).1 { // On overflow `checked_pow` should return `None`. assert_eq!(x.checked_pow($uint_ty::from(2)), None); assert_eq!(x.checked_pow($uint_ty::from(3)), None); return TestResult::discard(); } TestResult::from_bool( x.pow($uint_ty::from(2)) == x * x && x.pow($uint_ty::from(3)) == x * x * x ) } } quickcheck! { fn add_increases(x: $uint_ty, y: $uint_ty) -> TestResult { if y.is_zero() || x.overflowing_add(y).1 { return TestResult::discard(); } TestResult::from_bool( x + y > x ) } } quickcheck! { fn mul_increases(x: $uint_ty, y: $uint_ty) -> TestResult { if y.is_zero() || x.overflowing_mul(y).1 { return TestResult::discard(); } TestResult::from_bool( x * y >= x ) } } quickcheck! { fn div_decreases_dividend(x: $uint_ty, y: $uint_ty) -> TestResult { if y.is_zero() { return TestResult::discard(); } TestResult::from_bool( x / y <= x ) } } quickcheck! { fn rem_decreases_divisor(x: $uint_ty, y: $uint_ty) -> TestResult { if y.is_zero() { return TestResult::discard(); } TestResult::from_bool( x % y < y ) } } } } } construct_uint! { pub struct U64(1); } construct_uint! { pub struct U256(4); } construct_uint! { pub struct U512(8); } construct_uint! { pub struct U1024(16); } uint_laws!(u64, U64); uint_laws!(u256, U256); uint_laws!(u512, U512); uint_laws!(u1024, U1024); }