Minor tweaks: parallel lookup & FloatOrd impl

This commit is contained in:
Cian Hughes
2023-11-13 14:02:17 +00:00
parent a9b671986e
commit 1793be1439
17 changed files with 569 additions and 206 deletions

279
Cargo.lock generated
View File

@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "aho-corasick"
version = "1.0.2"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab"
dependencies = [
"memchr",
]
@@ -19,9 +19,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstyle"
version = "1.0.1"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46"
[[package]]
name = "autocfg"
@@ -40,15 +40,15 @@ dependencies = [
[[package]]
name = "bitflags"
version = "2.3.3"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
[[package]]
name = "bumpalo"
version = "3.13.0"
version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]]
name = "cast"
@@ -58,9 +58,12 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.0.79"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
@@ -97,18 +100,18 @@ dependencies = [
[[package]]
name = "clap"
version = "4.3.15"
version = "4.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f644d0dac522c8b05ddc39aaaccc5b136d5dc4ff216610c5641e3be5becf56c"
checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.3.15"
version = "4.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af410122b9778e024f9e0fb35682cc09cc3f85cad5e8d3ba8f47a9702df6e73d"
checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56"
dependencies = [
"anstyle",
"clap_lex",
@@ -116,9 +119,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.5.0"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
[[package]]
name = "colored"
@@ -167,16 +170,6 @@ dependencies = [
"itertools",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.3"
@@ -211,16 +204,22 @@ dependencies = [
]
[[package]]
name = "either"
version = "1.8.1"
name = "deranged"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
[[package]]
name = "either"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "errno"
version = "0.3.1"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd"
dependencies = [
"errno-dragonfly",
"libc",
@@ -245,7 +244,9 @@ dependencies = [
"criterion",
"log",
"num-traits",
"once_cell",
"phf",
"phf_codegen",
"rayon",
"serde",
"serde_json",
"simple_logger",
@@ -259,9 +260,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]]
name = "hermit-abi"
version = "0.3.2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
[[package]]
name = "is-terminal"
@@ -306,27 +307,27 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.147"
version = "0.2.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
[[package]]
name = "linux-raw-sys"
version = "0.4.3"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"
[[package]]
name = "log"
version = "0.4.19"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "memchr"
version = "2.5.0"
version = "2.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
[[package]]
name = "memoffset"
@@ -339,23 +340,13 @@ dependencies = [
[[package]]
name = "num-traits"
version = "0.2.15"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "num_threads"
version = "0.1.6"
@@ -377,6 +368,44 @@ version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "phf"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
dependencies = [
"phf_generator",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_shared"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
dependencies = [
"siphasher",
]
[[package]]
name = "plotters"
version = "0.3.5"
@@ -407,27 +436,42 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.66"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.31"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.7.0"
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
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"
[[package]]
name = "rayon"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
dependencies = [
"either",
"rayon-core",
@@ -435,21 +479,19 @@ dependencies = [
[[package]]
name = "rayon-core"
version = "1.11.0"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
name = "regex"
version = "1.9.1"
version = "1.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47"
dependencies = [
"aho-corasick",
"memchr",
@@ -459,9 +501,9 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.3.3"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
dependencies = [
"aho-corasick",
"memchr",
@@ -470,15 +512,15 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.7.4"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
[[package]]
name = "rustix"
version = "0.38.4"
version = "0.38.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5"
checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f"
dependencies = [
"bitflags",
"errno",
@@ -510,18 +552,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.171"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.171"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
@@ -530,9 +572,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.106"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cc66a619ed80bf7a0f6b17dd063a84b88f6dea1813737cf469aef1d081142c2"
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [
"itoa",
"ryu",
@@ -552,10 +594,16 @@ dependencies = [
]
[[package]]
name = "syn"
version = "2.0.26"
name = "siphasher"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970"
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]]
name = "syn"
version = "2.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
dependencies = [
"proc-macro2",
"quote",
@@ -564,10 +612,11 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.23"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446"
checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48"
dependencies = [
"deranged",
"itoa",
"libc",
"num_threads",
@@ -584,9 +633,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
[[package]]
name = "time-macros"
version = "0.2.10"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4"
checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572"
dependencies = [
"time-core",
]
@@ -603,15 +652,15 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.11"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "walkdir"
version = "2.3.3"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
dependencies = [
"same-file",
"winapi-util",
@@ -699,9 +748,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
@@ -738,17 +787,17 @@ dependencies = [
[[package]]
name = "windows-targets"
version = "0.48.1"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.0",
"windows_aarch64_msvc 0.48.0",
"windows_i686_gnu 0.48.0",
"windows_i686_msvc 0.48.0",
"windows_x86_64_gnu 0.48.0",
"windows_x86_64_gnullvm 0.48.0",
"windows_x86_64_msvc 0.48.0",
"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]]
@@ -759,9 +808,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
@@ -771,9 +820,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
@@ -783,9 +832,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
@@ -795,9 +844,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
@@ -807,9 +856,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
@@ -819,9 +868,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
@@ -831,6 +880,6 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"

View File

@@ -9,13 +9,16 @@ edition = "2021"
bincode = "1.3.3"
log = "0.4.19"
num-traits = "0.2.15"
once_cell = "1.18.0"
serde = {version = "1.0.171", features = ["derive"] }
rayon = "1.7.0"
simple_logger = "4.2.0"
phf = "0.11.2"
[build-dependencies]
bincode = "1.3.3"
num-traits = "0.2.15"
phf = "0.11.2"
phf_codegen = "0.11.2"
serde = {version = "1.0.171", features = ["derive"] }
[lib]
@@ -28,11 +31,14 @@ bench = true
name = "bench"
harness = false
[[bench]]
name = "devbench"
harness = false
# [[bench]]
# name = "devbench"
# harness = false
# [profile.release]
# debug = true
[dev-dependencies]
criterion = "0.5.1"
serde = "1.0.171"
serde = {version = "1.0.171", features = ["derive"] }
serde_json = "1.0.106"

View File

@@ -1,6 +1,7 @@
#![allow(unused_imports)]
extern crate fastmath;
use rayon::prelude::*;
use fastmath::*;
use criterion::{Criterion, BenchmarkGroup, measurement::WallTime};
use criterion::{black_box, criterion_group, criterion_main};
@@ -44,21 +45,70 @@ fn cos_benchmarks(group: &mut BenchmarkGroup<WallTime>, x_f64: &[f64], x_f32: &[
group.bench_function("f64_fast", |b| {
b.iter(|| x_f64.iter().map(|&x| black_box(x).fast_cos()).collect::<Vec<f64>>())
});
group.bench_function("f64_fast_par", |b| {
b.iter(|| x_f64.par_iter().map(|&x| black_box(x).fast_cos()).collect::<Vec<f64>>())
});
group.bench_function("f64_lookup", |b| {
b.iter(|| x_f64.iter().map(|&x| black_box(x).lookup_cos()).collect::<Vec<f64>>())
});
group.bench_function("f64_lookup_map", |b| {
let inputs = x_f64.par_iter().map(|&x| black_box(x)).collect::<Vec<f64>>();
b.iter(|| inputs.clone().lookup_cos())
});
group.bench_function("f64_lookup_par_map", |b| {
let inputs = x_f64.par_iter().map(|&x| black_box(x)).collect::<Vec<f64>>();
b.iter(|| inputs.clone().par_lookup_cos())
});
group.bench_function("f64_builtin", |b| {
b.iter(|| x_f64.iter().map(|&x| exact::f64::cos(black_box(x))).collect::<Vec<f64>>())
});
group.bench_function("f64_builtin_par", |b| {
b.iter(|| x_f64.par_iter().map(|&x| exact::f64::cos(black_box(x))).collect::<Vec<f64>>())
});
group.bench_function("f32_fast", |b| {
b.iter(|| x_f32.iter().map(|&x| black_box(x).fast_cos()).collect::<Vec<f32>>())
});
group.bench_function("f32_fast_par", |b| {
b.iter(|| x_f32.par_iter().map(|&x| black_box(x).fast_cos()).collect::<Vec<f32>>())
});
group.bench_function("f32_lookup", |b| {
b.iter(|| x_f32.iter().map(|&x| black_box(x).lookup_cos()).collect::<Vec<f32>>())
});
group.bench_function("f32_lookup_map", |b| {
let inputs = x_f32.par_iter().map(|&x| black_box(x)).collect::<Vec<f32>>();
b.iter(|| inputs.clone().lookup_cos())
});
group.bench_function("f32_lookup_par_map", |b| {
let inputs = x_f32.par_iter().map(|&x| black_box(x)).collect::<Vec<f32>>();
b.iter(|| inputs.clone().par_lookup_cos())
});
group.bench_function("f32_builtin", |b| {
b.iter(|| x_f32.iter().map(|&x| exact::f32::cos(black_box(x))).collect::<Vec<f32>>())
});
group.bench_function("f32_builtin_par", |b| {
b.iter(|| x_f32.par_iter().map(|&x| exact::f32::cos(black_box(x))).collect::<Vec<f32>>())
});
}
fn sin_benchmarks(group: &mut BenchmarkGroup<WallTime>, x_f64: &[f64], x_f32: &[f32]) {
group.bench_function("f64_fast", |b| {
b.iter(|| x_f64.iter().map(|&x| black_box(x).fast_sin()).collect::<Vec<f64>>())
});
group.bench_function("f64_lookup", |b| {
b.iter(|| x_f64.iter().map(|&x| black_box(x).lookup_sin()).collect::<Vec<f64>>())
});
group.bench_function("f64_builtin", |b| {
b.iter(|| x_f64.iter().map(|&x| exact::f64::sin(black_box(x))).collect::<Vec<f64>>())
});
group.bench_function("f32_fast", |b| {
b.iter(|| x_f32.iter().map(|&x| black_box(x).fast_sin()).collect::<Vec<f32>>())
});
group.bench_function("f32_lookup", |b| {
b.iter(|| x_f32.iter().map(|&x| black_box(x).lookup_sin()).collect::<Vec<f32>>())
});
group.bench_function("f32_builtin", |b| {
b.iter(|| x_f32.iter().map(|&x| exact::f32::sin(black_box(x))).collect::<Vec<f32>>())
});
}
fn sigmoid_benchmarks(group: &mut BenchmarkGroup<WallTime>, x_f64: &[f64], x_f32: &[f32]) {
@@ -93,6 +143,10 @@ fn criterion_benchmark(c: &mut Criterion) {
cos_benchmarks(&mut group, &X_F64, &X_F32);
group.finish();
let mut group = c.benchmark_group("sin");
sin_benchmarks(&mut group, &X_F64, &X_F32);
group.finish();
let mut group = c.benchmark_group("sigmoid");
sigmoid_benchmarks(&mut group, &X_F64, &X_F32);
group.finish();

View File

@@ -13,11 +13,10 @@ pub mod exact {
}
include!("../src/tests/accuracy/x.rs");
#[inline]
fn dev_cos(x: f64) -> f64 {
const ONE: f64 = 1.0;
let v = ((((x + f64_consts::PI).abs()) % f64_consts::TAU) - f64_consts::PI).abs();
let qpprox = ONE - f64_consts::FRAC_2_PI * v;
qpprox + f64_consts::FRAC_PI_6 * qpprox * (ONE - qpprox * qpprox)
let qpprox = 1.0 - f64_consts::FRAC_2_PI * (((x + f64_consts::PI) % f64_consts::TAU) - f64_consts::PI).abs();
(qpprox * (1.0 + f64_consts::FRAC_PI_6)) - (qpprox.powi(3) * f64_consts::FRAC_PI_6)
}
fn devbench(group: &mut BenchmarkGroup<WallTime>) {

View File

@@ -13,13 +13,13 @@ mod precalculate_lookup_tables {
let step: f32 = f32_consts::FRAC_PI_2 / TABLE_SIZE as f32;
let half_step: f32 = step / 2.0;
let keys: [FloatOrd<f32>; TABLE_SIZE] = (0..TABLE_SIZE).map(|i| {
FloatOrd( (step * (i as f32)) - half_step )
}).collect::<Vec<FloatOrd<f32>>>().try_into().unwrap_or([FloatOrd::new(); TABLE_SIZE]);
let keys: [f32; TABLE_SIZE] = (0..TABLE_SIZE).map(|i| {
(step * (i as f32)) - half_step
}).collect::<Vec<f32>>().try_into().unwrap_or([0.0f32; TABLE_SIZE]);
let values: [f32; TABLE_SIZE] = (0..TABLE_SIZE).map(|i| {
(step * (i as f32)).sin()
}).collect::<Vec<f32>>().try_into().unwrap_or([0.0f32; TABLE_SIZE]);
let data = format!("pub(crate) const SIN_F32_KEYS: [FloatOrd<f32>; {}] = {:?};\npub const SIN_F32_VALUES: [f32; {}] = {:?};\n", TABLE_SIZE, keys, TABLE_SIZE, values);
let data = format!("pub(crate) const SIN_F32_KEYS: [f32; {}] = {:?};\npub const SIN_F32_VALUES: [f32; {}] = {:?};\n", TABLE_SIZE, keys, TABLE_SIZE, values);
let mut file = File::create("src/lookup/data/sin_f32.rs")?;
file.write_all(data.as_bytes())?;
@@ -27,13 +27,13 @@ mod precalculate_lookup_tables {
let step: f64 = f64_consts::FRAC_PI_2 / TABLE_SIZE as f64;
let half_step: f64 = step / 2.0;
let keys: [FloatOrd<f64>; TABLE_SIZE] = (0..TABLE_SIZE).map(|i| {
FloatOrd( (step * (i as f64)) - half_step )
}).collect::<Vec<FloatOrd<f64>>>().try_into().unwrap_or([FloatOrd::new(); TABLE_SIZE]);
let keys: [f64; TABLE_SIZE] = (0..TABLE_SIZE).map(|i| {
(step * (i as f64)) - half_step
}).collect::<Vec<f64>>().try_into().unwrap_or([0.0f64; TABLE_SIZE]);
let values: [f64; TABLE_SIZE] = (0..TABLE_SIZE).map(|i| {
(step * (i as f64)).sin()
}).collect::<Vec<f64>>().try_into().unwrap_or([0.0f64; TABLE_SIZE]);
let data = format!("pub const SIN_F64_KEYS: [FloatOrd<f64>; {}] = {:?};\npub const SIN_F64_VALUES: [f64; {}] = {:?};\n", TABLE_SIZE, keys, TABLE_SIZE, values);
let data = format!("pub const SIN_F64_KEYS: [f64; {}] = {:?};\npub const SIN_F64_VALUES: [f64; {}] = {:?};\n", TABLE_SIZE, keys, TABLE_SIZE, values);
let mut file = File::create("src/lookup/data/sin_f64.rs")?;
file.write_all(data.as_bytes())?;
@@ -83,9 +83,7 @@ mod precalculate_test_tables {
pub fn generate() -> Result<(), Box<dyn std::error::Error>> {
create_dir_all("src/tests/accuracy")?;
precalculate_test_tables!();
Ok(())
}
}

View File

@@ -1,10 +1,12 @@
//! A collection of fast (often approximate) mathematical functions for accelerating mathematical functions
// Optimisation note: lookup tables become faster when calculation takes > ~400us
use std::f32::consts as f32_consts;
use std::f64::consts as f64_consts;
use crate::lookup::{EndoCosLookupTable, EndoSinLookupTable};
use crate::lookup::{
EndoCosLookupTable, EndoSinLookupTable,
ToIterator, ToParallelIterator,
};
const SIN_LOOKUP_F32: EndoSinLookupTable<f32> = EndoSinLookupTable::<f32>::new();
const SIN_LOOKUP_F64: EndoSinLookupTable<f64> = EndoSinLookupTable::<f64>::new();
@@ -55,6 +57,42 @@ impl LookupCos for f32 {
COS_LOOKUP_F32.lookup(self)
}
}
impl LookupCos for Vec<f64>
{
#[inline]
fn lookup_cos(self: Self) -> Vec<f64> {
// Look up the value in the table
COS_LOOKUP_F64.map_lookups(self).collect::<Vec<f64>>()
}
}
impl LookupCos for Vec<f32>
{
#[inline]
fn lookup_cos(self: Self) -> Vec<f32> {
// Look up the value in the table
COS_LOOKUP_F32.map_lookups(self).collect::<Vec<f32>>()
}
}
pub trait ParallelLookupCos {
fn par_lookup_cos(self: Self) -> Self;
}
use rayon::prelude::*;
impl ParallelLookupCos for Vec<f64> {
#[inline]
fn par_lookup_cos(self: Self) -> Vec<f64> {
// Look up the value in the table
COS_LOOKUP_F64.par_map_lookups(self).collect::<Vec<f64>>()
}
}
impl ParallelLookupCos for Vec<f32> {
#[inline]
fn par_lookup_cos(self: Self) -> Vec<f32> {
// Look up the value in the table
COS_LOOKUP_F32.par_map_lookups(self).collect::<Vec<f32>>()
}
}
pub trait FastCos {
fn fast_cos(self: Self) -> Self;
@@ -62,19 +100,41 @@ pub trait FastCos {
impl FastCos for f32 {
#[inline]
fn fast_cos(self: Self) -> f32 {
const ONE: f32 = 1.0;
let v = ((((self + f32_consts::PI).abs()) % f32_consts::TAU) - f32_consts::PI).abs();
let qpprox = ONE - f32_consts::FRAC_2_PI * v;
qpprox + f32_consts::FRAC_PI_6 * qpprox * (ONE - qpprox * qpprox)
let qpprox =
1.0 - f32_consts::FRAC_2_PI *
((((self + f32_consts::PI).abs()) % f32_consts::TAU) - f32_consts::PI).abs();
(qpprox * (1.0 + f32_consts::FRAC_PI_6)) - (qpprox.powi(3) * f32_consts::FRAC_PI_6)
}
}
impl FastCos for f64 {
#[inline]
fn fast_cos(self: Self) -> f64 {
const ONE: f64 = 1.0;
let v = ((((self + f64_consts::PI).abs()) % f64_consts::TAU) - f64_consts::PI).abs();
let qpprox = ONE - f64_consts::FRAC_2_PI * v;
qpprox + f64_consts::FRAC_PI_6 * qpprox * (ONE - qpprox * qpprox)
let qpprox =
1.0 - f64_consts::FRAC_2_PI *
((((self + f64_consts::PI).abs()) % f64_consts::TAU) - f64_consts::PI).abs();
(qpprox * (1.0 + f64_consts::FRAC_PI_6)) - (qpprox.powi(3) * f64_consts::FRAC_PI_6)
}
}
pub trait FastSin {
fn fast_sin(self: Self) -> Self;
}
impl FastSin for f32 {
#[inline]
fn fast_sin(self: Self) -> f32 {
let qpprox =
1.0 - f32_consts::FRAC_2_PI *
((((self + f32_consts::FRAC_PI_2).abs()) % f32_consts::TAU) - f32_consts::PI).abs();
(qpprox * (1.0 + f32_consts::FRAC_PI_6)) - (qpprox.powi(3) * f32_consts::FRAC_PI_6)
}
}
impl FastSin for f64 {
#[inline]
fn fast_sin(self: Self) -> f64 {
let qpprox =
1.0 - f64_consts::FRAC_2_PI *
((((self + f64_consts::FRAC_PI_2).abs()) % f64_consts::TAU) - f64_consts::PI).abs();
(qpprox * (1.0 + f64_consts::FRAC_PI_6)) - (qpprox.powi(3) * f64_consts::FRAC_PI_6)
}
}
@@ -128,14 +188,12 @@ pub trait FastSigmoid {
impl FastSigmoid for f32 {
#[inline]
fn fast_sigmoid(self: Self) -> f32 {
const ONE: f32 = 1.0;
(ONE + (-self).fast_exp()).recip()
(1.0 + (-self).fast_exp()).recip()
}
}
impl FastSigmoid for f64 {
#[inline]
fn fast_sigmoid(self: Self) -> f64 {
const ONE: f64 = 1.0;
(ONE + (-self).fast_exp()).recip()
(1.0 + (-self).fast_exp()).recip()
}
}

View File

@@ -1,4 +1,4 @@
//lib.rs
// lib.rs
#![allow(unused_imports)]
pub mod lookup;
@@ -8,4 +8,4 @@ mod fastmath;
pub use fastmath::*;
#[cfg(test)]
pub(crate) mod tests;
pub mod tests;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,60 +4,117 @@ use std::cmp::Ordering;
use num_traits::identities::One;
use num_traits::ops::wrapping::WrappingSub;
use num_traits::float::{Float, FloatConst};
use rayon::iter::{ParallelIterator, IntoParallelIterator};
use crate::{
impl_fbitfbit_lookup_table,
impl_cycling_fbitfbit_lookup_table,
};
use crate::lookup::TABLE_SIZE;
use crate::lookup::ordinal_float::FloatOrd;
use crate::lookup::const_tables::*;
// TODO: Test phf for lookup tables
pub trait ToIterator<T>: IntoIterator<Item = T> {}
impl<T, I> ToIterator<T> for I where I: IntoIterator<Item = T> {}
pub trait ToParallelIterator<T>: IntoParallelIterator<Item = T> {}
impl<T, I> ToParallelIterator<T> for I where I: IntoParallelIterator<Item = T> {}
pub trait ToIndex {
fn to_index(&self) -> usize;
}
impl ToIndex for f32 {
fn to_index(&self) -> usize {
*self as usize
}
}
impl ToIndex for f64 {
fn to_index(&self) -> usize {
*self as usize
}
}
pub trait FromIndex {
fn from_index(index: usize) -> Self;
}
impl FromIndex for f32 {
fn from_index(index: usize) -> Self {
index as f32
}
}
impl FromIndex for f64 {
fn from_index(index: usize) -> Self {
index as f64
}
}
#[derive(Debug, Clone)]
pub struct FloatLookupTable<T1, T2>
where
T1: Float,
T2: Float,
FloatOrd<T1>: Ord,
{
keys: [FloatOrd<T1>; TABLE_SIZE],
keys: [T1; TABLE_SIZE],
max_key: T1,
values: [T2; TABLE_SIZE],
}
impl<T1, T2> FloatLookupTable<T1, T2>
where
T1: Float,
T2: Float,
FloatOrd<T1>: Ord,
T1: Float + std::marker::Send + std::marker::Sync,
T1: ToIndex,
f64: From<T1>,
T2: Float + std::marker::Send + std::marker::Sync,
{
pub fn new(keys: [T1; TABLE_SIZE], values: [T2; TABLE_SIZE]) -> Self {
FloatLookupTable {
keys: keys.map(|key| FloatOrd(key)),
values,
keys: keys,
max_key: keys[TABLE_SIZE - 1],
values: values,
}
}
pub fn get_next(&self, key: T1) -> T2
{
let ord_key = FloatOrd(key);
let mut lower_bound = 0;
let mut upper_bound = self.keys.len() - 1;
let mut mid: usize;
while lower_bound < upper_bound {
mid = lower_bound + (upper_bound - lower_bound) / 2;
if self.keys[mid] < ord_key {
lower_bound = mid + 1;
} else {
upper_bound = mid;
// Find value at the nearest key, using interpolative search
// This assumes evenly distributed keys
let max_index: T1 = T1::from(self.keys.len() - 1).unwrap();
let index: usize = (key * max_index / self.max_key).ceil().to_index();
// Ensure value cannot be out of bounds
*self.values.get(index).unwrap_or_else(
|| -> &T2 {
if index >= self.values.len() {
self.values.last().unwrap()
} else {
panic!("NaN or Inf received or in lookup table")
}
}
}
self.values[upper_bound]
)
}
pub fn key_to_index(&self, key: T1) -> usize
{
(key * T1::from(self.keys.len() - 1).unwrap() / self.max_key).ceil().to_index()
}
pub fn lookup(&self, key: T1) -> T2 {
self.get_next(key)
}
pub fn map_lookups<'a, I>(&'a self, keys: I) -> impl Iterator<Item=T2> + 'a
where
I: ToIterator<T1> + 'a,
{
keys.into_iter().map(move |key| self.lookup(key))
}
pub fn par_map_lookups<'a, I>(&'a self, keys: I) -> impl ParallelIterator<Item=T2> + 'a
where
I: ToParallelIterator<T1> + 'a,
{
keys.into_par_iter().map(move |key| self.lookup(key))
}
}
impl_fbitfbit_lookup_table!(f32, f32);
impl_fbitfbit_lookup_table!(f64, f64);
@@ -68,9 +125,9 @@ impl_fbitfbit_lookup_table!(f64, f32);
#[derive(Debug, Clone)]
pub struct CyclingFloatLookupTable<T1, T2>
where
T1: Float,
T2: Float,
FloatOrd<T1>: Ord,
T1: Float + std::marker::Send + std::marker::Sync,
T2: Float + std::marker::Send + std::marker::Sync,
T1: ToIndex,
{
lookup_table: FloatLookupTable<T1, T2>,
lower_bound: T1,
@@ -78,9 +135,10 @@ where
}
impl<T1, T2> CyclingFloatLookupTable<T1, T2>
where
T1: Float,
T2: Float,
FloatOrd<T1>: Ord,
T1: Float + std::marker::Send + std::marker::Sync,
T1: ToIndex,
f64: From<T1>,
T2: Float + std::marker::Send + std::marker::Sync,
{
pub fn new(keys: [T1; TABLE_SIZE], values: [T2; TABLE_SIZE], lower_bound: T1, upper_bound: T1) -> Self {
CyclingFloatLookupTable {
@@ -95,6 +153,20 @@ where
(key % self.range) + self.lower_bound
)
}
pub fn map_lookups<'a, I>(&'a self, keys: I) -> impl Iterator<Item=T2> + 'a
where
I: ToIterator<T1> + 'a,
{
self.lookup_table.map_lookups(keys)
}
pub fn par_map_lookups<'a, I>(&'a self, keys: I) -> impl ParallelIterator<Item=T2> + 'a
where
I: ToParallelIterator<T1> + 'a,
{
self.lookup_table.par_map_lookups(keys)
}
}
impl_cycling_fbitfbit_lookup_table!(f32, f32);
impl_cycling_fbitfbit_lookup_table!(f64, f64);
@@ -105,29 +177,69 @@ impl_cycling_fbitfbit_lookup_table!(f64, f32);
#[derive(Debug, Clone)]
pub struct EndoSinLookupTable<T>
where
T: Float + FloatConst,
FloatOrd<T>: Ord,
T: Float + FloatConst + std::marker::Send + std::marker::Sync,
T: ToIndex,
{
lookup_table: CyclingFloatLookupTable<T, T>,
}
impl<T> EndoSinLookupTable<T>
where
T: Float + FloatConst,
FloatOrd<T>: Ord,
T: Float + FloatConst + std::marker::Send + std::marker::Sync,
T: ToIndex,
f64: From<T>,
{
pub fn key_to_value(&self, key: T) -> T {
const STEP_SIZE: f64 = f64_consts::FRAC_PI_2 / TABLE_SIZE as f64;
let lookup_key = (key / (T::from(STEP_SIZE)).unwrap()).trunc().to_usize().unwrap();
self.lookup_table.lookup_table.values[lookup_key]
}
fn direct_lookup(&self, key: T) -> T {
self.lookup_table.lookup_table.get_next(key)
}
pub fn lookup(&self, key: T) -> T {
if key < T::zero() {
-self.lookup(-key)
} else if key < T::FRAC_PI_2() {
self.lookup_table.lookup(key)
} else if key < T::PI() {
self.lookup_table.lookup(T::PI() - key)
} else if key < T::TAU() { // obviously, mod is slow so we want to avoid it until this would start recursing deeply
-self.lookup(key - T::PI())
} else {
-self.lookup(key % T::PI())
let mut abs_key = key.abs();
let comparisons: [T; 4] = [T::FRAC_PI_2(), T::PI(), T::PI() + T::FRAC_PI_2(), T::TAU()];
let quadrant: usize =
comparisons
.iter()
.position(|&x: &T| -> bool { abs_key < x })
.unwrap_or_else(
|| -> usize {
abs_key = abs_key % T::TAU();
comparisons
.iter()
.position(|&x: &T| -> bool { abs_key < x })
.expect("This should literally be mathematically impossible")
}
);
match (key.is_sign_negative(), quadrant) {
(true, 0) => self.direct_lookup(abs_key).neg(),
(true, 1) => self.direct_lookup(T::PI() - abs_key).neg(),
(true, 2) => self.direct_lookup(abs_key - T::PI()),
(true, 3) => self.direct_lookup(T::TAU() - abs_key),
(false, 0) => self.direct_lookup(abs_key),
(false, 1) => self.direct_lookup(T::PI() - abs_key),
(false, 2) => self.direct_lookup(abs_key - T::PI()).neg(),
(false, 3) => self.direct_lookup(T::TAU() - abs_key).neg(),
_ => panic!("Something very strange has happened"),
}
}
pub fn map_lookups<'a, I>(&'a self, keys: I) -> impl Iterator<Item=T> + 'a
where
I: ToIterator<T> + 'a,
{
keys.into_iter().map(move |key| self.lookup(key))
}
pub fn par_map_lookups<'a, I>(&'a self, keys: I) -> impl ParallelIterator<Item=T> + 'a
where
I: ToParallelIterator<T> + 'a,
{
keys.into_par_iter().map(move |key| self.lookup(key))
}
}
impl EndoSinLookupTable<f32>
{
@@ -154,23 +266,51 @@ impl EndoSinLookupTable<f64>
#[derive(Debug, Clone)]
pub struct EndoCosLookupTable<T>
where
T: Float + FloatConst,
T: Float + FloatConst + std::marker::Send + std::marker::Sync,
T: ToIndex,
{
lookup_table: EndoSinLookupTable<T>,
}
impl<T> EndoCosLookupTable<T>
where
T: Float + FloatConst,
T: Float + FloatConst + std::marker::Send + std::marker::Sync,
T: ToIndex,
f64: From<T>,
{
pub fn lookup(&self, key: T) -> T {
pub fn lookup(&self, key: T) -> T
{
self.lookup_table.lookup(key + T::FRAC_PI_2())
}
pub fn map_lookups<I>(self, keys: I) -> impl Iterator<Item=T>
where
I: ToIterator<T>,
{
keys.into_iter().map(move |key| self.lookup(key))
}
pub fn par_map_lookups<I>(self, keys: I) -> impl ParallelIterator<Item=T>
where
I: ToParallelIterator<T>,
{
keys.into_par_iter().map(move |key| self.lookup(key))
}
}
impl EndoCosLookupTable<f32>
{
pub const fn new() -> Self {
EndoCosLookupTable {
lookup_table: EndoSinLookupTable::<f32>::new(),
lookup_table: EndoSinLookupTable::<f32>{
lookup_table: CyclingFloatLookupTable::<f32, f32>{
lookup_table: FloatLookupTable::<f32, f32>{
keys: SIN_F32_KEYS,
max_key: f32_consts::FRAC_PI_2,
values: SIN_F32_VALUES,
},
lower_bound: 0.0,
range: f32_consts::PI,
},
},
}
}
}
@@ -178,7 +318,17 @@ impl EndoCosLookupTable<f64>
{
pub const fn new() -> Self {
EndoCosLookupTable {
lookup_table: EndoSinLookupTable::<f64>::new(),
lookup_table: EndoSinLookupTable::<f64>{
lookup_table: CyclingFloatLookupTable::<f64, f64>{
lookup_table: FloatLookupTable::<f64, f64>{
keys: SIN_F64_KEYS,
max_key: f64_consts::FRAC_PI_2,
values: SIN_F64_VALUES,
},
lower_bound: 0.0,
range: f64_consts::PI,
},
},
}
}
}

View File

@@ -1,6 +1,6 @@
pub mod const_tables;
pub mod lookup_table;
pub(crate) mod ordinal_float;
pub mod ordinal_float;
pub use lookup_table::*;

View File

@@ -3,9 +3,10 @@ mod lookup_table {
macro_rules! impl_fbitfbit_lookup_table {
($key_type:ty, $value_type:ty) => {
impl FloatLookupTable<$key_type, $value_type> {
pub const fn new_const(keys: [FloatOrd<$key_type>; TABLE_SIZE], values: [$value_type; TABLE_SIZE]) -> Self {
pub const fn new_const(keys: [$key_type; TABLE_SIZE], values: [$value_type; TABLE_SIZE]) -> Self {
FloatLookupTable {
keys: keys,
max_key: keys[TABLE_SIZE - 1],
values: values,
}
}
@@ -17,7 +18,7 @@ mod lookup_table {
macro_rules! impl_cycling_fbitfbit_lookup_table {
($key_type:ty, $value_type:ty) => {
impl CyclingFloatLookupTable<$key_type, $value_type> {
pub const fn new_const(keys: [FloatOrd<$key_type>; TABLE_SIZE], values: [$value_type; TABLE_SIZE], lower_bound: $key_type, range: $key_type) -> Self {
pub const fn new_const(keys: [$key_type; TABLE_SIZE], values: [$value_type; TABLE_SIZE], lower_bound: $key_type, range: $key_type) -> Self {
CyclingFloatLookupTable {
lookup_table: FloatLookupTable::<$key_type, $value_type>::new_const(keys, values),
lower_bound: lower_bound,

View File

@@ -1,12 +1,14 @@
use fastmath::LookupCos;
use std::hint::black_box;
fn main() {
let x = (-10000..10000)
.map(|a| (a as f64) / 1000.)
let x = (-10000000..10000000)
.map(|a| (a as f64) / 1000000.)
.collect::<Vec<f64>>();
let y = x.iter().map(|&x| x.lookup_cos()).collect::<Vec<f64>>();
let y = x.iter().map(|&x| black_box(x).lookup_cos()).collect::<Vec<f64>>();
// to ensure the compiler doesn't optimize away the function call, we print the result
println!("{:?}", y);
black_box(y);
println!("DONE!");
}

View File

@@ -72,6 +72,22 @@ pub mod f64 {
panic_if_nan_or_print!(percentage_error, "lookup_cos<f64> percentage error")
}
pub fn sin() -> Result<f64, Box<dyn std::error::Error>> {
let percentage_error = calculate_percentage_error(
&X_F64.iter().map(|&x| x.fast_sin()).collect::<Vec<f64>>(),
&X_F64.iter().map(|&x| exact::f64::sin(x)).collect::<Vec<f64>>()
);
panic_if_nan_or_print!(percentage_error, "fast_sin<f64> percentage error")
}
pub fn sin_lookup() -> Result<f64, Box<dyn std::error::Error>> {
let percentage_error = calculate_percentage_error(
&X_F64.iter().map(|&x| x.lookup_sin()).collect::<Vec<f64>>(),
&X_F64.iter().map(|&x| exact::f64::sin(x)).collect::<Vec<f64>>()
);
panic_if_nan_or_print!(percentage_error, "lookup_sin<f64> percentage error")
}
pub fn sigmoid() -> Result<f64, Box<dyn std::error::Error>> {
let percentage_error = calculate_percentage_error(
&X_F64.iter().map(|&x| x.fast_sigmoid()).collect::<Vec<f64>>(),
@@ -120,6 +136,22 @@ pub mod f32 {
panic_if_nan_or_print!(percentage_error, "lookup_cos<f32> percentage error")
}
pub fn sin() -> Result<f32, Box<dyn std::error::Error>> {
let percentage_error = calculate_percentage_error(
&X_F32.iter().map(|&x| x.fast_sin()).collect::<Vec<f32>>(),
&X_F32.iter().map(|&x| exact::f32::sin(x)).collect::<Vec<f32>>()
);
panic_if_nan_or_print!(percentage_error, "fast_sin<f32> percentage error")
}
pub fn sin_lookup() -> Result<f32, Box<dyn std::error::Error>> {
let percentage_error = calculate_percentage_error(
&X_F32.iter().map(|&x| x.lookup_sin()).collect::<Vec<f32>>(),
&X_F32.iter().map(|&x| exact::f32::sin(x)).collect::<Vec<f32>>()
);
panic_if_nan_or_print!(percentage_error, "lookup_sin<f32> percentage error")
}
pub fn sigmoid() -> Result<f32, Box<dyn std::error::Error>> {
let percentage_error = calculate_percentage_error(
&X_F32.iter().map(|&x| x.fast_sigmoid()).collect::<Vec<f32>>(),

View File

@@ -11,6 +11,10 @@ pub mod f64 {
n.cos()
}
pub fn sin(n: f64) -> f64 {
n.sin()
}
pub fn sigmoid(n: f64) -> f64 {
(1. + (-n).exp()).recip()
}
@@ -29,6 +33,10 @@ pub mod f32 {
n.cos()
}
pub fn sin(n: f32) -> f32 {
n.sin()
}
pub fn sigmoid(n: f32) -> f32 {
(1. + (-n).exp()).recip()
}

View File

@@ -3,5 +3,7 @@
"exp_fast": 2.0,
"cos_fast": 1.0,
"cos_lk": 1.0,
"sin_fast": 1.0,
"sin_lk": 1.0,
"sigmoid_fast": 1.0
}

View File

@@ -19,7 +19,7 @@ macro_rules! test_within_tolerance {
($function:ident, $t:ty, $test_name:ident) => {
#[test]
fn $test_name() -> Result<(), Box<dyn std::error::Error>> {
let tolerance: $t = get_tolerance::<$t>(stringify!($test_name))?;
let tolerance: $t = get_tolerance::<$t>(stringify!($test_name)).unwrap_or_else(|_| panic!("Invalid tolerance for {}", stringify!($test_name)));
let percentage_error: $t = $function()?;
assert!(percentage_error < tolerance);
Ok(())
@@ -35,6 +35,8 @@ mod f64 {
test_within_tolerance!(exp, f64, exp_fast);
test_within_tolerance!(cos, f64, cos_fast);
test_within_tolerance!(cos_lookup, f64, cos_lk);
test_within_tolerance!(sin, f64, sin_fast);
test_within_tolerance!(sin_lookup, f64, sin_lk);
test_within_tolerance!(sigmoid, f64, sigmoid_fast);
}
@@ -46,5 +48,7 @@ mod f32 {
test_within_tolerance!(exp, f32, exp_fast);
test_within_tolerance!(cos, f32, cos_fast);
test_within_tolerance!(cos_lookup, f32, cos_lk);
test_within_tolerance!(sin, f32, sin_fast);
test_within_tolerance!(sin_lookup, f32, sin_lk);
test_within_tolerance!(sigmoid, f32, sigmoid_fast);
}