lexical-parse-float-0.8.5/.cargo_vcs_info.json0000644000000001610000000000100147000ustar { "git": { "sha1": "86dd62255a2cc3d0839d5272c8f30aec2c3b3791" }, "path_in_vcs": "lexical-parse-float" }lexical-parse-float-0.8.5/CODE_OF_CONDUCT.md000064400000000000000000000230620072674642500163240ustar 00000000000000# Code of Conduct ## When Something Happens If you see a Code of Conduct violation, follow these steps: 1. Let the person know that what they did is not appropriate and ask them to stop and/or edit their message(s) or commits. 2. That person should immediately stop the behavior and correct the issue. 3. If this doesn’t happen, or if you're uncomfortable speaking up, [contact the maintainers](#contacting-maintainers). 4. As soon as available, a maintainer will look into the issue, and take [further action (see below)](#further-enforcement), starting with a warning, then temporary block, then long-term repo or organization ban. When reporting, please include any relevant details, links, screenshots, context, or other information that may be used to better understand and resolve the situation. **The maintainer team will prioritize the well-being and comfort of the recipients of the violation over the comfort of the violator.** See [some examples below](#enforcement-examples). ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers of this project pledge to making participation in our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, technical preferences, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language. * Being respectful of differing viewpoints and experiences. * Gracefully accepting constructive feedback. * Focusing on what is best for the community. * Showing empathy and kindness towards other community members. * Encouraging and raising up your peers in the project so you can all bask in hacks and glory. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances, including when simulated online. The only exception to sexual topics is channels/spaces specifically for topics of sexual identity. * Casual mention of slavery or indentured servitude and/or false comparisons of one's occupation or situation to slavery. Please consider using or asking about alternate terminology when referring to such metaphors in technology. * Making light of/making mocking comments about trigger warnings and content warnings. * Trolling, insulting/derogatory comments, and personal or political attacks. * Public or private harassment, deliberate intimidation, or threats. * Publishing others' private information, such as a physical or electronic address, without explicit permission. This includes any sort of "outing" of any aspect of someone's identity without their consent. * Publishing private screenshots or quotes of interactions in the context of this project without all quoted users' *explicit* consent. * Publishing of private communication that doesn't have to do with reporting harrassment. * Any of the above even when [presented as "ironic" or "joking"](https://en.wikipedia.org/wiki/Hipster_racism). * Any attempt to present "reverse-ism" versions of the above as violations. Examples of reverse-isms are "reverse racism", "reverse sexism", "heterophobia", and "cisphobia". * Unsolicited explanations under the assumption that someone doesn't already know it. Ask before you teach! Don't assume what people's knowledge gaps are. * [Feigning or exaggerating surprise](https://www.recurse.com/manual#no-feigned-surprise) when someone admits to not knowing something. * "[Well-actuallies](https://www.recurse.com/manual#no-well-actuallys)" * Other conduct which could reasonably be considered inappropriate in a professional or community setting. ## Scope This Code of Conduct applies both within spaces involving this project and in other spaces involving community members. This includes the repository, its Pull Requests and Issue tracker, private email communications in the context of the project, and any events where members of the project are participating, as well as adjacent communities and venues affecting the project's members. Depending on the violation, the maintainers may decide that violations of this code of conduct that have happened outside of the scope of the community may deem an individual unwelcome, and take appropriate action to maintain the comfort and safety of its members. ### Other Community Standards As a project on GitHub, this project is additionally covered by the [GitHub Community Guidelines](https://help.github.com/articles/github-community-guidelines/). Enforcement of those guidelines after violations overlapping with the above are the responsibility of the entities, and enforcement may happen in any or all of the services/communities. ## Maintainer Enforcement Process Once the maintainers get involved, they will follow a documented series of steps and do their best to preserve the well-being of project members. This section covers actual concrete steps. ### Contacting Maintainers You may get in touch with the maintainer team through any of the following methods: Through email: ahuszagh@gmail.com (Alex Huszagh) ### Further Enforcement If you've already followed the [initial enforcement steps](#enforcement), these are the steps maintainers will take for further enforcement, as needed: 1. Repeat the request to stop. 2. If the person doubles down, they will have offending messages removed or edited by a maintainers given an official warning. The PR or Issue may be locked. 3. If the behavior continues or is repeated later, the person will be blocked from participating for 24 hours. 4. If the behavior continues or is repeated after the temporary block, a long-term (6-12mo) ban will be used. On top of this, maintainers may remove any offending messages, images, contributions, etc, as they deem necessary. Maintainers reserve full rights to skip any of these steps, at their discretion, if the violation is considered to be a serious and/or immediate threat to the health and well-being of members of the community. These include any threats, serious physical or verbal attacks, and other such behavior that would be completely unacceptable in any social setting that puts our members at risk. Members expelled from events or venues with any sort of paid attendance will not be refunded. ### Who Watches the Watchers? Maintainers and other leaders who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. These may include anything from removal from the maintainer team to a permanent ban from the community. Additionally, as a project hosted on both GitHub and npm, [their own Codes of Conducts may be applied against maintainers of this project](#other-community-standards), externally of this project's procedures. ### Enforcement Examples #### The Best Case The vast majority of situations work out like this. This interaction is common, and generally positive. > Alex: "Yeah I used X and it was really crazy!" > Patt (not a maintainer): "Hey, could you not use that word? What about 'ridiculous' instead?" > Alex: "oh sorry, sure." -> edits old comment to say "it was really confusing!" #### The Maintainer Case Sometimes, though, you need to get maintainers involved. Maintainers will do their best to resolve conflicts, but people who were harmed by something **will take priority**. > Patt: "Honestly, sometimes I just really hate using $library and anyone who uses it probably sucks at their job." > Alex: "Whoa there, could you dial it back a bit? There's a CoC thing about attacking folks' tech use like that." > Patt: "I'm not attacking anyone, what's your problem?" > Alex: "@maintainers hey uh. Can someone look at this issue? Patt is getting a bit aggro. I tried to nudge them about it, but nope." > KeeperOfCommitBits: (on issue) "Hey Patt, maintainer here. Could you tone it down? This sort of attack is really not okay in this space." > Patt: "Leave me alone I haven't said anything bad wtf is wrong with you." > KeeperOfCommitBits: (deletes user's comment), "@patt I mean it. Please refer to the CoC over at (URL to this CoC) if you have questions, but you can consider this an actual warning. I'd appreciate it if you reworded your messages in this thread, since they made folks there uncomfortable. Let's try and be kind, yeah?" > Patt: "@keeperofbits Okay sorry. I'm just frustrated and I'm kinda burnt out and I guess I got carried away. I'll DM Alex a note apologizing and edit my messages. Sorry for the trouble." > KeeperOfCommitBits: "@patt Thanks for that. I hear you on the stress. Burnout sucks :/. Have a good one!" #### The Nope Case > PepeTheFrog🐸: "Hi, I am a literal actual nazi and I think white supremacists are quite fashionable." > Patt: "NOOOOPE. OH NOPE NOPE." > Alex: "JFC NO. NOPE. @keeperofbits NOPE NOPE LOOK HERE" > KeeperOfCommitBits: "👀 Nope. NOPE NOPE NOPE. 🔥" > PepeTheFrog🐸 has been banned from all organization or user repositories belonging to KeeperOfCommitBits. ## Attribution This Code of Conduct was generated using [WeAllJS Code of Conduct Generator](https://npm.im/weallbehave), which is based on the [WeAllJS Code of Conduct](https://wealljs.org/code-of-conduct), which is itself based on [Contributor Covenant](http://contributor-covenant.org), version 1.4, available at [http://contributor-covenant.org/version/1/4](http://contributor-covenant.org/version/1/4), and the LGBTQ in Technology Slack [Code of Conduct](http://lgbtq.technology/coc.html). lexical-parse-float-0.8.5/Cargo.toml0000644000000036620000000000100127070ustar # 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 = "2018" name = "lexical-parse-float" version = "0.8.5" authors = ["Alex Huszagh "] exclude = [ "assets/*", "docs/*", "etc/*", "cargo-timing*.html", ] autobenches = false description = "Efficient parsing of floats from strings." readme = "README.md" keywords = [ "parsing", "lexical", "no_std", ] categories = [ "parsing", "no-std", ] license = "MIT/Apache-2.0" repository = "https://github.com/Alexhuszagh/rust-lexical" [package.metadata.docs.rs] features = [ "radix", "format", ] [dependencies.lexical-parse-integer] version = "0.8.5" features = [] default-features = false [dependencies.lexical-util] version = "0.8.5" features = ["parse-floats"] default-features = false [dependencies.static_assertions] version = "1" [dev-dependencies.proptest] version = "0.10.1" [features] compact = [ "lexical-util/compact", "lexical-parse-integer/compact", ] default = ["std"] f128 = ["lexical-util/f128"] f16 = ["lexical-util/f16"] format = [ "lexical-util/format", "lexical-parse-integer/format", ] lint = [ "lexical-util/lint", "lexical-parse-integer/lint", ] nightly = ["lexical-parse-integer/nightly"] power-of-two = [ "lexical-util/power-of-two", "lexical-parse-integer/power-of-two", ] radix = [ "lexical-util/radix", "lexical-parse-integer/radix", "power-of-two", ] safe = ["lexical-parse-integer/safe"] std = [ "lexical-util/std", "lexical-parse-integer/std", ] lexical-parse-float-0.8.5/Cargo.toml.orig000064400000000000000000000045700072674642500164170ustar 00000000000000[package] authors = ["Alex Huszagh "] autobenches = false categories = ["parsing", "no-std"] description = "Efficient parsing of floats from strings." edition = "2018" keywords = ["parsing", "lexical", "no_std"] license = "MIT/Apache-2.0" name = "lexical-parse-float" readme = "README.md" repository = "https://github.com/Alexhuszagh/rust-lexical" version = "0.8.5" exclude = [ "assets/*", "docs/*", "etc/*", "cargo-timing*.html" ] [dependencies.lexical-util] version = "0.8.5" path = "../lexical-util" default-features = false features = ["parse-floats"] [dependencies.lexical-parse-integer] version = "0.8.5" path = "../lexical-parse-integer" default-features = false features = [] [dependencies] static_assertions = "1" [dev-dependencies] # FIXME: Replace back to "1.0.4" once the PR is merged. # There's an issue in quickcheck due to an infinitely repeating shrinker. # Issue: https://github.com/BurntSushi/quickcheck/issues/295 # Fix: https://github.com/BurntSushi/quickcheck/pull/296 quickcheck = { git = "https://github.com/neithernut/quickcheck/", branch = "i32min-shrink-bound" } proptest = "0.10.1" [features] default = ["std"] # Use the standard library. std = [ "lexical-util/std", "lexical-parse-integer/std" ] # Add support for parsing power-of-two float strings. power-of-two = [ "lexical-util/power-of-two", "lexical-parse-integer/power-of-two" ] # Add support for parsing non-decimal float strings. radix = [ "lexical-util/radix", "lexical-parse-integer/radix", "power-of-two" ] # Add support for parsing custom float formats. format = [ "lexical-util/format", "lexical-parse-integer/format" ] # Reduce code size at the cost of performance. compact = [ "lexical-util/compact", "lexical-parse-integer/compact" ] # Ensure only safe indexing is used. This is effectively a no-op, since all # examples of potential memory unsafety are trivial to prove safe. safe = ["lexical-parse-integer/safe"] # Add support for nightly-only features. nightly = ["lexical-parse-integer/nightly"] # Enable support for 16-bit floats. f16 = ["lexical-util/f16"] # Internal only features. # Enable the lint checks. lint = [ "lexical-util/lint", "lexical-parse-integer/lint" ] # Currently unsupported. # Enable support for 128-bit floats. f128 = ["lexical-util/f128"] [package.metadata.docs.rs] features = ["radix", "format"] lexical-parse-float-0.8.5/LICENSE-APACHE000064400000000000000000000251420072674642500154520ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. lexical-parse-float-0.8.5/LICENSE-MIT000064400000000000000000000017770072674642500151720ustar 00000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. lexical-parse-float-0.8.5/LICENSE.md000064400000000000000000000454630072674642500151420ustar 00000000000000# Licensing Lexical is dual licensed under the Apache 2.0 license as well as the MIT license. See the LICENCE-MIT and the LICENCE-APACHE files for the licenses. Other licensing terms may apply, as described in depth below for various features and functionality. All assume use of `lexical` or `lexical-core`. ## `write-floats, not(compact)` `lexical-write-float/src/algorithm.rs` is a direct port of the reference C++ implementation of Dragonbox, found [here](https://github.com/jk-jeon/dragonbox/). This code (used if the `write-floats` feature is enabled and the `compact` feature is disabled) is subject to a [Boost Software License](https://github.com/jk-jeon/dragonbox/blob/71993f55067a89f4b4e27591605e21521f5c61be/LICENSE-Boost) and a modified [Apache2 license](https://github.com/jk-jeon/dragonbox/blob/71993f55067a89f4b4e27591605e21521f5c61be/LICENSE-Apache2-LLVM), shown in the [Boost Software License](#boost-software-license) and [Apache2 With LLVM Exceptions](#apache2-with-llvm-exceptions) sections below. ## `write-floats, compact` `lexical-write-float/src/compact.rs` is a direct port of a C++ implementation of the Grisu algorithm, found [here](https://github.com/night-shift/fpconv/). This code (used if both the `write-floats` and `compact` features are enabled) is subject to a [MIT License](https://github.com/night-shift/fpconv/blob/dfeb7e938fb85fb5eca130b84f856705ced75012/license), shown in the [fpconv License](#fpconv-license) section below. ## `write-floats, radix` `lexical-write-float/src/radix.rs` is adapted from the V8 implementation found [here](). This code (used if both the `parse-floats` and `radix` features are enabled) is subject to a [3-clause BSD license](https://github.com/v8/v8/blob/f80bfeaf0792652bfbc1f174d5a7b8ab8bc0cbbd/LICENSE.v8), shown in the [V8 License](#v8-license) section below. ## `parse-floats, compact` `lexical-parse-float/src/bellerophon.rs` is loosely based off the Golang implementation, found [here](https://github.com/golang/go/blob/b10849fbb97a2244c086991b4623ae9f32c212d0/src/strconv/extfloat.go). This code (used if both the `parse-floats` and `compact` features are enabled) is subject to a [3-clause BSD license](https://github.com/golang/go/blob/b10849fbb97a2244c086991b4623ae9f32c212d0/LICENSE), shown in the [Go License](#go-license) section below. # License Terms This contains complete copies of the licensing terms for the feature-dependent code described above. ## Go License Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## Boost Software License Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Apache2 With LLVM Exceptions _Version 2.0, January 2004_ _<>_ ### Terms and Conditions for use, reproduction, and distribution #### 1. Definitions “License” shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. “Licensor” shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. “Legal Entity” shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, “control” means **(i)** the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the outstanding shares, or **(iii)** beneficial ownership of such entity. “You” (or “Your”) shall mean an individual or Legal Entity exercising permissions granted by this License. “Source” form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. “Object” form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. “Work” shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). “Derivative Works” shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. “Contribution” shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, “submitted” means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as “Not a Contribution.” “Contributor” shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. #### 2. Grant of Copyright License Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. #### 3. Grant of Patent License Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. #### 4. Redistribution You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: * **(a)** You must give any other recipients of the Work or Derivative Works a copy of this License; and * **(b)** You must cause any modified files to carry prominent notices stating that You changed the files; and * **(c)** You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and * **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. #### 5. Submission of Contributions Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. #### 6. Trademarks This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. #### 7. Disclaimer of Warranty Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. #### 8. Limitation of Liability In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. #### 9. Accepting Warranty or Additional Liability While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. _END OF TERMS AND CONDITIONS_ ### APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets `[]` replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same “printed page” as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ### LLVM Exceptions to the Apache 2.0 License As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. ## V8 License Copyright 2014, the V8 project authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## fpconv License The MIT License Copyright (c) 2013 Andreas Samoljuk Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. lexical-parse-float-0.8.5/README.md000064400000000000000000000470760072674642500150170ustar 00000000000000lexical ======= High-performance numeric conversion routines for use in a `no_std` environment. This does not depend on any standard library features, nor a system allocator. **Similar Projects** If you want a minimal, stable, and compile-time friendly version of lexical's float-parsing algorithm, see [minimal-lexical](https://github.com/Alexhuszagh/minimal-lexical). If you want a minimal, performant float parser, recent versions of the Rust standard library should be [sufficient](https://github.com/rust-lang/rust/pull/86761). **Table of Contents** - [Getting Started](#getting-started) - [Partial/Complete Parsers](#partialcomplete-parsers) - [no_std](#no_std) - [Features](#features) - [Customization](#customization) - [Number Format API](#number-format-api) - [Options API](#options-api) - [Documentation](#documentation) - [Validation](#validation) - [Metrics](#metrics) - [Safety](#safety) - [Platform Support](#platform-support) - [Versioning and Version Support](#versioning-and-version-support) - [Changelog](#changelog) - [License](#license) - [Contributing](#contributing) # Getting Started Add lexical to your `Cargo.toml`: ```toml [dependencies] lexical = "^6.0" ``` And get started using lexical: ```rust // Number to string use lexical_core::BUFFER_SIZE; let mut buffer = [b'0'; BUFFER_SIZE]; lexical_core::write(3.0, &mut buffer); // "3.0", always has a fraction suffix, lexical_core::write(3, &mut buffer); // "3" // String to number. let i: i32 = lexical_core::parse("3")?; // Ok(3), auto-type deduction. let f: f32 = lexical_core::parse("3.5")?; // Ok(3.5) let d: f64 = lexical_core::parse("3.5")?; // Ok(3.5), error checking parse. let d: f64 = lexical_core::parse("3a")?; // Err(Error(_)), failed to parse. ``` In order to use lexical in generic code, the trait bounds `FromLexical` (for `parse`) and `ToLexical` (for `to_string`) are provided. ```rust /// Multiply a value in a string by multiplier, and serialize to string. fn mul_2(value: &str, multiplier: T) -> Result where T: lexical_core::ToLexical + lexical_core::FromLexical, { let value: T = lexical_core::parse(value.as_bytes())?; let mut buffer = [b'0'; lexical_core::BUFFER_SIZE]; let bytes = lexical_core::write(value * multiplier, &mut buffer); Ok(std::str::from_utf8(bytes).unwrap()) } ``` # Partial/Complete Parsers Lexical has both partial and complete parsers: the complete parsers ensure the entire buffer is used while parsing, without ignoring trailing characters, while the partial parsers parse as many characters as possible, returning both the parsed value and the number of parsed digits. Upon encountering an error, lexical will return an error indicating both the error type and the index at which the error occurred inside the buffer. **Complete Parsers** ```rust // This will return Err(Error::InvalidDigit(3)), indicating // the first invalid character occurred at the index 3 in the input // string (the space character). let x: i32 = lexical_core::parse(b"123 456")?; ``` **Partial Parsers** ```rust // This will return Ok((123, 3)), indicating that 3 digits were successfully // parsed, and that the returned value is `123`. let (x, count): (i32, usize) = lexical_core::parse_partial(b"123 456")?; ``` # no_std `lexical-core` does not depend on a standard library, nor a system allocator. To use `lexical-core` in a `no_std` environment, add the following to `Cargo.toml`: ```toml [dependencies.lexical-core] version = "0.8.5" default-features = false # Can select only desired parsing/writing features. features = ["write-integers", "write-floats", "parse-integers", "parse-floats"] ``` And get started using lexical: ```rust // A constant for the maximum number of bytes a formatter will write. use lexical_core::BUFFER_SIZE; let mut buffer = [b'0'; BUFFER_SIZE]; // Number to string. The underlying buffer must be a slice of bytes. let count = lexical_core::write(3.0, &mut buffer); assert_eq!(buffer[..count], b"3.0"); let count = lexical_core::write(3i32, &mut buffer); assert_eq!(buffer[..count], b"3"); // String to number. The input must be a slice of bytes. let i: i32 = lexical_core::parse(b"3")?; // Ok(3), auto-type deduction. let f: f32 = lexical_core::parse(b"3.5")?; // Ok(3.5) let d: f64 = lexical_core::parse(b"3.5")?; // Ok(3.5), error checking parse. let d: f64 = lexical_core::parse(b"3a")?; // Err(Error(_)), failed to parse. ``` # Features Lexical feature-gates each numeric conversion routine, resulting in faster compile times if certain numeric conversions. These features can be enabled/disabled for both `lexical-core` (which does not require a system allocator) and `lexical`. By default, all conversions are enabled. - **parse-floats**:   Enable string-to-float conversions. - **parse-integers**:   Enable string-to-integer conversions. - **write-floats**:   Enable float-to-string conversions. - **write-integers**:   Enable integer-to-string conversions. Lexical is highly customizable, and contains numerous other optional features: - **std**:   Enable use of the Rust standard library (enabled by default). - **power-of-two**:   Enable conversions to and from non-decimal strings.
With power_of_two enabled, the radixes {2, 4, 8, 10, 16, and 32} are valid, otherwise, only 10 is valid. This enables common conversions to/from hexadecimal integers/floats, without requiring large pre-computed tables for other radixes.
- **radix**:   Allow conversions to and from non-decimal strings.
With radix enabled, any radix from 2 to 36 (inclusive) is valid, otherwise, only 10 is valid.
- **format**:   Customize acceptable number formats for number parsing and writing.
With format enabled, the number format is dictated through bitflags and masks packed into a u128. These dictate the valid syntax of parsed and written numbers, including enabling digit separators, requiring integer or fraction digits, and toggling case-sensitive exponent characters.
- **compact**:   Optimize for binary size at the expense of performance.
This minimizes the use of pre-computed tables, producing significantly smaller binaries.
- **safe**:   Require all array indexing to be bounds-checked.
This is effectively a no-op for number parsers, since they use safe indexing except where indexing without bounds checking can be trivially shown to be correct. The number writers frequently use unsafe indexing, since we can easily over-estimate the number of digits in the output due to the fixed-length input.
- **f16**:   Add support for numeric conversions to-and-from 16-bit floats.
Adds f16, a half-precision IEEE-754 floating-point type, and bf16, the Brain Float 16 type, and numeric conversions to-and-from these floats. Note that since these are storage formats, and therefore do not have native arithmetic operations, all conversions are done using an intermediate f32.
To ensure the safety when bounds checking is disabled, we extensively fuzz the all numeric conversion routines. See the [Safety](#safety) section below for more information. Lexical also places a heavy focus on code bloat: with algorithms both optimized for performance and size. By default, this focuses on performance, however, using the `compact` feature, you can also opt-in to reduced code size at the cost of performance. The compact algorithms minimize the use of pre-computed tables and other optimizations at the cost of performance. # Customization > ⚠ **WARNING:** If changing the number of significant digits written, disabling the use of exponent notation, or changing exponent notation thresholds, `BUFFER_SIZE` may be insufficient to hold the resulting output. `WriteOptions::buffer_size` will provide a correct upper bound on the number of bytes written. If a buffer of insufficient length is provided, lexical-core will panic. Every language has competing specifications for valid numerical input, meaning a number parser for Rust will incorrectly accept or reject input for different programming or data languages. For example: ```rust // Valid in Rust strings. // Not valid in JSON. let f: f64 = lexical_core::parse(b"3.e7")?; // 3e7 // Let's only accept JSON floats. const JSON: u128 = lexical_core::format::JSON; let options = ParseFloatOptions::new(); let f: f64 = lexical_core::parse_with_options::(b"3.0e7", &options)?; // 3e7 let f: f64 = lexical_core::parse_with_options::(b"3.e7", &options)?; // Errors! ``` Due the high variability in the syntax of numbers in different programming and data languages, we provide 2 different APIs to simplify converting numbers with different syntax requirements. - Number Format API (feature-gated via `format` or `power-of-two`).
This is a packed struct contained flags to specify compile-time syntax rules for number parsing or writing. This includes features such as the radix of the numeric string, digit separators, case-sensitive exponent characters, optional base prefixes/suffixes, and more.
- Options API.
This contains run-time rules for parsing and writing numbers. This includes exponent break points, rounding modes, the exponent and decimal point characters, and the string representation of NaN and Infinity.
A limited subset of functionality is documented in examples below, however, the complete specification can be found in the API reference documentation. ## Number Format API The number format class provides numerous flags to specify number syntax when parsing or writing. When the `power-of-two` feature is enabled, additional flags are added: - The radix for the significant digits (default `10`). - The radix for the exponent base (default `10`). - The radix for the exponent digits (default `10`). When the `format` feature is enabled, numerous other syntax and digit separator flags are enabled, including: - A digit separator character, to group digits for increased legibility. - Whether leading, trailing, internal, and consecutive digit separators are allowed. - Toggling required float components, such as digits before the decimal point. - Toggling whether special floats are allowed or are case-sensitive. Many pre-defined constants therefore exist to simplify common use-cases, including: - JSON, XML, TOML, YAML, SQLite, and many more. - Rust, Python, C#, FORTRAN, COBOL literals and strings, and many more. An example of building a custom number format is as follows: ```rust const FORMAT: u128 = lexical_core::NumberFormatBuilder::new() // Disable exponent notation. .no_exponent_notation(true) // Disable all special numbers, such as Nan and Inf. .no_special(true) .build(); // Due to use in a `const fn`, we can't panic or expect users to unwrap invalid // formats, so it's up to the caller to verify the format. If an invalid format // is provided to a parser or writer, the function will error or panic, respectively. debug_assert!(lexical_core::format_is_valid::()); ``` ## Options API The options API allows customizing number parsing and writing at run-time, such as specifying the maximum number of significant digits, exponent characters, and more. An example of building a custom options struct is as follows: ```rust use std::num; let options = lexical_core::WriteFloatOptions::builder() // Only write up to 5 significant digits, IE, `1.23456` becomes `1.2345`. .max_significant_digits(num::NonZeroUsize::new(5)) // Never write less than 5 significant digits, `1.1` becomes `1.1000`. .min_significant_digits(num::NonZeroUsize::new(5)) // Trim the trailing `.0` from integral float strings. .trim_floats(true) // Use a European-style decimal point. .decimal_point(b',') // Panic if we try to write NaN as a string. .nan_string(None) // Write infinity as "Infinity". .inf_string(Some(b"Infinity")) .build() .unwrap(); ``` # Documentation Lexical's API reference can be found on [docs.rs](https://docs.rs/lexical), as can [lexical-core's](lexical-core). Detailed descriptions of the algorithms used can be found here: - [Parsing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-integer/docs/Algorithm.md) - [Parsing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Algorithm.md) - [Writing Integers](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-integer/docs/Algorithm.md) - [Writing Floats](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-float/docs/Algorithm.md) In addition, descriptions of how lexical handles [digit separators](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/DigitSeparators.md) and implements [big-integer arithmetic](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/BigInteger.md) are also documented. # Validation **Float-Parsing** Float parsing is difficult to do correctly, and major bugs have been found in implementations from [libstdc++'s strtod](https://www.exploringbinary.com/glibc-strtod-incorrectly-converts-2-to-the-negative-1075/) to [Python](https://bugs.python.org/issue7632). In order to validate the accuracy of the lexical, we employ the following external tests: 1. Hrvoje Abraham's [strtod](https://github.com/ahrvoje/numerics/tree/master/strtod) test cases. 2. Rust's [test-float-parse](https://github.com/rust-lang/rust/tree/64185f205dcbd8db255ad6674e43c63423f2369a/src/etc/test-float-parse) unittests. 3. Testbase's [stress tests](https://www.icir.org/vern/papers/testbase-report.pdf) for converting from decimal to binary. 4. Nigel Tao's [tests](https://github.com/nigeltao/parse-number-fxx-test-data) extracted from test suites for Freetype, Google's double-conversion library, IBM's IEEE-754R compliance test, as well as numerous other curated examples. 5. [Various](https://www.exploringbinary.com/glibc-strtod-incorrectly-converts-2-to-the-negative-1075/) [difficult](https://www.exploringbinary.com/how-glibc-strtod-works/) [cases](https://www.exploringbinary.com/how-strtod-works-and-sometimes-doesnt/) reported on blogs. Although lexical may contain bugs leading to rounding error, it is tested against a comprehensive suite of random-data and near-halfway representations, and should be fast and correct for the vast majority of use-cases. # Metrics Various benchmarks, binary sizes, and compile times are shown here: **Build Timings** The compile-times when building with all numeric conversions enabled. For a more fine-tuned breakdown, see [build timings](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/BuildTimings.md). ![Build Timings](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/assets/timings_all_posix.svg) **Binary Size** The binary sizes of stripped binaries compiled at optimization level "2". For a more fine-tuned breakdown, see [binary sizes](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/BinarySize.md). ![Parse Stripped - Optimization Level "2"](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/assets/size_parse_stripped_opt2_posix.svg) ![Write Stripped - Optimization Level "2"](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/assets/size_write_stripped_opt2_posix.svg) **Benchmarks -- Parse Integer** A benchmark on randomly-generated integers uniformly distributed over the entire range. For a more fine-tuned breakdown, see [benchmarks](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-integer/docs/Benchmarks.md). ![Uniform Random Data](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/lexical-parse-integer/assets/random_uniform.svg) **Benchmarks -- Parse Float** A benchmark on parsing floats from various real-world data sets. For a more fine-tuned breakdown, see [benchmarks](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Benchmarks.md). ![Real Data](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/lexical-parse-float/assets/real.svg) **Benchmarks -- Write Integer** A benchmark on writing random integers uniformly distributed over the entire range. For a more fine-tuned breakdown, see [benchmarks](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-integer/docs/Benchmarks.md). ![Uniform Random Data](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/lexical-write-integer/assets/random_uniform.svg) **Benchmarks -- Write Float** A benchmark on writing floats generated via a random-number generator and parsed from a JSON document. For a more fine-tuned breakdown, see [benchmarks](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-write-float/docs/Benchmarks.md). ![Random Data](https://raw.githubusercontent.com/Alexhuszagh/rust-lexical/main/lexical-write-float/assets/json.svg) # Safety Due to the use of memory unsafe code in the integer and float writers, we extensively fuzz our float writers and parsers. The fuzz harnesses may be found under [fuzz](https://github.com/Alexhuszagh/rust-lexical/tree/main/fuzz), and are run continuously. So far, we've parsed and written over 72 billion floats. Due to the simple logic of the integer writers, and the lack of memory safety in the integer parsers, we minimally fuzz both, and test it with edge-cases, which has shown no memory safety issues to date. # Platform Support lexical-core is tested on a wide variety of platforms, including big and small-endian systems, to ensure portable code. Supported architectures include: - x86_64 Linux, Windows, macOS, Android, iOS, FreeBSD, and NetBSD. - x86 Linux, macOS, Android, iOS, and FreeBSD. - aarch64 (ARM8v8-A) Linux, Android, and iOS. - armv7 (ARMv7-A) Linux, Android, and iOS. - arm (ARMv6) Linux, and Android. - mips (MIPS) Linux. - mipsel (MIPS LE) Linux. - mips64 (MIPS64 BE) Linux. - mips64el (MIPS64 LE) Linux. - powerpc (PowerPC) Linux. - powerpc64 (PPC64) Linux. - powerpc64le (PPC64LE) Linux. - s390x (IBM Z) Linux. lexical-core should also work on a wide variety of other architectures and ISAs. If you have any issue compiling lexical-core on any architecture, please file a bug report. # Versioning and Version Support **Version Support** The currently supported versions are: - v0.8.x - v0.7.x (Maintenance) - v0.6.x (Maintenance) **Rustc Compatibility** - v0.8.x supports 1.51+, including stable, beta, and nightly. - v0.7.x supports 1.37+, including stable, beta, and nightly. - v0.6.x supports Rustc 1.24+, including stable, beta, and nightly. Please report any errors compiling a supported lexical-core version on a compatible Rustc version. **Versioning** lexical uses [semantic versioning](https://semver.org/). Removing support for Rustc versions newer than the latest stable Debian or Ubuntu version is considered an incompatible API change, requiring a major version change. # Changelog All changes are documented in [CHANGELOG](https://github.com/Alexhuszagh/rust-lexical/blob/main/CHANGELOG). # License Lexical is dual licensed under the Apache 2.0 license as well as the MIT license. See the [LICENSE.md](LICENSE.md) file for full license details. # Contributing Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in lexical by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. Contributing to the repository means abiding by the [code of conduct](https://github.com/Alexhuszagh/rust-lexical/blob/main/CODE_OF_CONDUCT.md). For the process on how to contribute to lexical, see the [development](https://github.com/Alexhuszagh/rust-lexical/blob/main/docs/Development.md) quick-start guide. lexical-parse-float-0.8.5/src/api.rs000064400000000000000000000051140072674642500154310ustar 00000000000000////! Implements the algorithm in terms of the lexical API. #![doc(hidden)] use crate::options::Options; use crate::parse::ParseFloat; #[cfg(feature = "f16")] use lexical_util::bf16::bf16; use lexical_util::error::Error; #[cfg(feature = "f16")] use lexical_util::f16::f16; use lexical_util::format::{is_valid_options_punctuation, NumberFormat, STANDARD}; use lexical_util::{from_lexical, from_lexical_with_options}; // API const DEFAULT_OPTIONS: Options = Options::new(); /// Implement FromLexical for numeric type. /// /// Need to inline these, otherwise codegen is suboptimal. /// For some reason, it can't determine some of the const evaluations /// can actually be evaluated at compile-time, which causes major branching /// issues. macro_rules! float_from_lexical { ($($t:ident)*) => ($( impl FromLexical for $t { #[cfg_attr(not(feature = "compact"), inline)] fn from_lexical(bytes: &[u8]) -> lexical_util::result::Result { Self::parse_complete::(bytes, &DEFAULT_OPTIONS) } #[cfg_attr(not(feature = "compact"), inline)] fn from_lexical_partial( bytes: &[u8], ) -> lexical_util::result::Result<(Self, usize)> { Self::parse_partial::(bytes, &DEFAULT_OPTIONS) } } impl FromLexicalWithOptions for $t { type Options = Options; #[cfg_attr(not(feature = "compact"), inline)] fn from_lexical_with_options( bytes: &[u8], options: &Self::Options, ) -> lexical_util::result::Result { let format = NumberFormat::<{ FORMAT }> {}; if !format.is_valid() { return Err(format.error()); } else if !is_valid_options_punctuation(FORMAT, options.exponent(), options.decimal_point()) { return Err(Error::InvalidPunctuation); } Self::parse_complete::(bytes, options) } #[cfg_attr(not(feature = "compact"), inline)] fn from_lexical_partial_with_options( bytes: &[u8], options: &Self::Options, ) -> lexical_util::result::Result<(Self, usize)> { Self::parse_partial::(bytes, options) } } )*) } from_lexical! {} from_lexical_with_options! {} float_from_lexical! { f32 f64 } #[cfg(feature = "f16")] float_from_lexical! { bf16 f16 } lexical-parse-float-0.8.5/src/bellerophon.rs000064400000000000000000000333600072674642500171750ustar 00000000000000//! An implementation of Clinger's Bellerophon algorithm. //! //! This is a moderate path algorithm that uses an extended-precision //! float, represented in 80 bits, by calculating the bits of slop //! and determining if those bits could prevent unambiguous rounding. //! //! This algorithm requires less static storage than the Lemire algorithm, //! and has decent performance, and is therefore used when non-decimal, //! non-power-of-two strings need to be parsed. Clinger's algorithm //! is described in depth in "How to Read Floating Point Numbers Accurately.", //! available online [here](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.45.4152&rep=rep1&type=pdf). //! //! This implementation is loosely based off the Golang implementation, //! found [here](https://github.com/golang/go/blob/b10849fbb97a2244c086991b4623ae9f32c212d0/src/strconv/extfloat.go). //! This code is therefore subject to a 3-clause BSD license. #![cfg(any(feature = "compact", feature = "radix"))] #![doc(hidden)] use crate::float::{ExtendedFloat80, RawFloat}; use crate::mask::{lower_n_halfway, lower_n_mask}; use crate::number::Number; use crate::shared; use crate::table::bellerophon_powers; use lexical_util::format::NumberFormat; // ALGORITHM // --------- /// Core implementation of the Bellerophon algorithm. /// /// Create an extended-precision float, scale it to the proper radix power, /// calculate the bits of slop, and return the representation. The value /// will always be guaranteed to be within 1 bit, rounded-down, of the real /// value. If a negative exponent is returned, this represents we were /// unable to unambiguously round the significant digits. /// /// This has been modified to return a biased, rather than unbiased exponent. pub fn bellerophon(num: &Number, lossy: bool) -> ExtendedFloat80 { let format = NumberFormat::<{ FORMAT }> {}; debug_assert!(!matches!(format.radix(), 2 | 4 | 8 | 16 | 32)); debug_assert!(format.mantissa_radix() == format.exponent_base()); let fp_zero = ExtendedFloat80 { mant: 0, exp: 0, }; let fp_inf = ExtendedFloat80 { mant: 0, exp: F::INFINITE_POWER, }; // Early short-circuit, in case of literal 0 or infinity. // This allows us to avoid narrow casts causing numeric overflow, // and is a quick check for any radix. if num.mantissa == 0 || num.exponent <= -0x1000 { return fp_zero; } else if num.exponent >= 0x1000 { return fp_inf; } // Calculate our indexes for our extended-precision multiplication. let powers = bellerophon_powers(format.radix()); // This narrowing cast is safe, since exponent must be in a valid range. let exponent = num.exponent as i32 + powers.bias; let small_index = exponent % powers.step; let large_index = exponent / powers.step; if exponent < 0 { // Guaranteed underflow (assign 0). return fp_zero; } if large_index as usize >= powers.large.len() { // Overflow (assign infinity) return fp_inf; } // Within the valid exponent range, multiply by the large and small // exponents and return the resulting value. // Track errors to as a factor of unit in last-precision. let mut errors: u32 = 0; if num.many_digits { errors += error_halfscale(); } // Multiply by the small power. // Check if we can directly multiply by an integer, if not, // use extended-precision multiplication. let mut fp = ExtendedFloat80 { mant: num.mantissa, exp: 0, }; match fp.mant.overflowing_mul(powers.get_small_int(small_index as usize)) { // Overflow, multiplication unsuccessful, go slow path. (_, true) => { normalize(&mut fp); fp = mul(&fp, &powers.get_small(small_index as usize)); errors += error_halfscale(); }, // No overflow, multiplication successful. (mant, false) => { fp.mant = mant; normalize(&mut fp); }, } // Multiply by the large power. fp = mul(&fp, &powers.get_large(large_index as usize)); if errors > 0 { errors += 1; } errors += error_halfscale(); // Normalize the floating point (and the errors). let shift = normalize(&mut fp); errors <<= shift; fp.exp += F::EXPONENT_BIAS; // Check for literal overflow, even with halfway cases. if -fp.exp + 1 > 65 { return fp_zero; } // Too many errors accumulated, return an error. if !lossy && !error_is_accurate::(errors, &fp) { // Bias the exponent so we know it's invalid. fp.exp += shared::INVALID_FP; return fp; } // Check if we have a literal 0 or overflow here. // If we have an exponent of -63, we can still have a valid shift, // giving a case where we have too many errors and need to round-up. if -fp.exp + 1 == 65 { // Have more than 64 bits below the minimum exponent, must be 0. return fp_zero; } shared::round::(&mut fp, |f, s| { shared::round_nearest_tie_even(f, s, |is_odd, is_halfway, is_above| { is_above || (is_odd && is_halfway) }); }); fp } // ERRORS // ------ // Calculate if the errors in calculating the extended-precision float. // // Specifically, we want to know if we are close to a halfway representation, // or halfway between `b` and `b+1`, or `b+h`. The halfway representation // has the form: // SEEEEEEEHMMMMMMMMMMMMMMMMMMMMMMM100... // where: // S = Sign Bit // E = Exponent Bits // H = Hidden Bit // M = Mantissa Bits // // The halfway representation has a bit set 1-after the mantissa digits, // and no bits set immediately afterward, making it impossible to // round between `b` and `b+1` with this representation. /// Get the full error scale. #[inline(always)] const fn error_scale() -> u32 { 8 } /// Get the half error scale. #[inline(always)] const fn error_halfscale() -> u32 { error_scale() / 2 } /// Determine if the number of errors is tolerable for float precision. #[cfg_attr(not(feature = "compact"), inline)] fn error_is_accurate(errors: u32, fp: &ExtendedFloat80) -> bool { // Check we can't have a literal 0 denormal float. debug_assert!(fp.exp >= -64); // Determine if extended-precision float is a good approximation. // If the error has affected too many units, the float will be // inaccurate, or if the representation is too close to halfway // that any operations could affect this halfway representation. // See the documentation for dtoa for more information. // This is always a valid u32, since `fp.exp >= -64` // will always be positive and the significand size is {23, 52}. let mantissa_shift = 64 - F::MANTISSA_SIZE - 1; // The unbiased exponent checks is `unbiased_exp <= F::MANTISSA_SIZE // - F::EXPONENT_BIAS -64 + 1`, or `biased_exp <= F::MANTISSA_SIZE - 63`, // or `biased_exp <= mantissa_shift`. let extrabits = match fp.exp <= -mantissa_shift { // Denormal, since shifting to the hidden bit still has a negative exponent. // The unbiased check calculation for bits is `1 - F::EXPONENT_BIAS - unbiased_exp`, // or `1 - biased_exp`. true => 1 - fp.exp, false => 64 - F::MANTISSA_SIZE - 1, }; // Our logic is as follows: we want to determine if the actual // mantissa and the errors during calculation differ significantly // from the rounding point. The rounding point for round-nearest // is the halfway point, IE, this when the truncated bits start // with b1000..., while the rounding point for the round-toward // is when the truncated bits are equal to 0. // To do so, we can check whether the rounding point +/- the error // are >/< the actual lower n bits. // // For whether we need to use signed or unsigned types for this // analysis, see this example, using u8 rather than u64 to simplify // things. // // # Comparisons // cmp1 = (halfway - errors) < extra // cmp1 = extra < (halfway + errors) // // # Large Extrabits, Low Errors // // extrabits = 8 // halfway = 0b10000000 // extra = 0b10000010 // errors = 0b00000100 // halfway - errors = 0b01111100 // halfway + errors = 0b10000100 // // Unsigned: // halfway - errors = 124 // halfway + errors = 132 // extra = 130 // cmp1 = true // cmp2 = true // Signed: // halfway - errors = 124 // halfway + errors = -124 // extra = -126 // cmp1 = false // cmp2 = true // // # Conclusion // // Since errors will always be small, and since we want to detect // if the representation is accurate, we need to use an **unsigned** // type for comparisons. let maskbits = extrabits as u64; let errors = errors as u64; // Round-to-nearest, need to use the halfway point. if extrabits > 64 { // Underflow, we have a shift larger than the mantissa. // Representation is valid **only** if the value is close enough // overflow to the next bit within errors. If it overflows, // the representation is **not** valid. !fp.mant.overflowing_add(errors).1 } else { let mask = lower_n_mask(maskbits); let extra = fp.mant & mask; // Round-to-nearest, need to check if we're close to halfway. // IE, b10100 | 100000, where `|` signifies the truncation point. let halfway = lower_n_halfway(maskbits); let cmp1 = halfway.wrapping_sub(errors) < extra; let cmp2 = extra < halfway.wrapping_add(errors); // If both comparisons are true, we have significant rounding error, // and the value cannot be exactly represented. Otherwise, the // representation is valid. !(cmp1 && cmp2) } } // MATH // ---- /// Normalize float-point number. /// /// Shift the mantissa so the number of leading zeros is 0, or the value /// itself is 0. /// /// Get the number of bytes shifted. #[cfg_attr(not(feature = "compact"), inline)] pub fn normalize(fp: &mut ExtendedFloat80) -> i32 { // Note: // Using the ctlz intrinsic via leading_zeros is way faster (~10x) // than shifting 1-bit at a time, via while loop, and also way // faster (~2x) than an unrolled loop that checks at 32, 16, 4, // 2, and 1 bit. // // Using a modulus of pow2 (which will get optimized to a bitwise // and with 0x3F or faster) is slightly slower than an if/then, // however, removing the if/then will likely optimize more branched // code as it removes conditional logic. // Calculate the number of leading zeros, and then zero-out // any overflowing bits, to avoid shl overflow when self.mant == 0. if fp.mant != 0 { let shift = fp.mant.leading_zeros() as i32; fp.mant <<= shift; fp.exp -= shift; shift } else { 0 } } /// Multiply two normalized extended-precision floats, as if by `a*b`. /// /// The precision is maximal when the numbers are normalized, however, /// decent precision will occur as long as both values have high bits /// set. The result is not normalized. /// /// Algorithm: /// 1. Non-signed multiplication of mantissas (requires 2x as many bits as input). /// 2. Normalization of the result (not done here). /// 3. Addition of exponents. #[cfg_attr(not(feature = "compact"), inline)] pub fn mul(x: &ExtendedFloat80, y: &ExtendedFloat80) -> ExtendedFloat80 { // Logic check, values must be decently normalized prior to multiplication. debug_assert!(x.mant >> 32 != 0); debug_assert!(y.mant >> 32 != 0); // Extract high-and-low masks. const LOMASK: u64 = u32::MAX as u64; let x1 = x.mant >> 32; let x0 = x.mant & LOMASK; let y1 = y.mant >> 32; let y0 = y.mant & LOMASK; // Get our products let x1_y0 = x1 * y0; let x0_y1 = x0 * y1; let x0_y0 = x0 * y0; let x1_y1 = x1 * y1; let mut tmp = (x1_y0 & LOMASK) + (x0_y1 & LOMASK) + (x0_y0 >> 32); // round up tmp += 1 << (32 - 1); ExtendedFloat80 { mant: x1_y1 + (x1_y0 >> 32) + (x0_y1 >> 32) + (tmp >> 32), exp: x.exp + y.exp + 64, } } // POWERS // ------ /// Precalculated powers of base N for the Bellerophon algorithm. pub struct BellerophonPowers { // Pre-calculated small powers. pub small: &'static [u64], // Pre-calculated large powers. pub large: &'static [u64], /// Pre-calculated small powers as 64-bit integers pub small_int: &'static [u64], // Step between large powers and number of small powers. pub step: i32, // Exponent bias for the large powers. pub bias: i32, /// ceil(log2(radix)) scaled as a multiplier. pub log2: i64, /// Bitshift for the log2 multiplier. pub log2_shift: i32, } /// Allow indexing of values without bounds checking impl BellerophonPowers { #[inline] pub const fn get_small(&self, index: usize) -> ExtendedFloat80 { let mant = self.small[index]; let exp = (1 - 64) + ((self.log2 * index as i64) >> self.log2_shift); ExtendedFloat80 { mant, exp: exp as i32, } } #[inline] pub const fn get_large(&self, index: usize) -> ExtendedFloat80 { let mant = self.large[index]; let biased_e = index as i64 * self.step as i64 - self.bias as i64; let exp = (1 - 64) + ((self.log2 * biased_e) >> self.log2_shift); ExtendedFloat80 { mant, exp: exp as i32, } } #[inline] pub const fn get_small_int(&self, index: usize) -> u64 { self.small_int[index] } } lexical-parse-float-0.8.5/src/bigint.rs000064400000000000000000001366400072674642500161450ustar 00000000000000//! A simple big-integer type for slow path algorithms. //! //! This includes minimal stackvector for use in big-integer arithmetic. #![doc(hidden)] #[cfg(feature = "radix")] use crate::float::ExtendedFloat80; use crate::float::RawFloat; use crate::limits::{u32_power_limit, u64_power_limit}; #[cfg(not(feature = "compact"))] use crate::table::get_large_int_power; use core::{cmp, mem, ops, ptr, slice}; // BIGINT // ------ /// Number of bits in a Bigint. /// /// This needs to be at least the number of bits required to store /// a Bigint, which is `log2(radix**digits)`. /// ≅ 5600 for base-36, rounded-up. #[cfg(feature = "radix")] const BIGINT_BITS: usize = 6000; /// ≅ 3600 for base-10, rounded-up. #[cfg(not(feature = "radix"))] const BIGINT_BITS: usize = 4000; /// The number of limbs for the bigint. const BIGINT_LIMBS: usize = BIGINT_BITS / LIMB_BITS; /// Storage for a big integer type. /// /// This is used for algorithms when we have a finite number of digits. /// Specifically, it stores all the significant digits scaled to the /// proper exponent, as an integral type, and then directly compares /// these digits. /// /// This requires us to store the number of significant bits, plus the /// number of exponent bits (required) since we scale everything /// to the same exponent. #[derive(Clone, PartialEq, Eq)] pub struct Bigint { /// Significant digits for the float, stored in a big integer in LE order. /// /// This is pretty much the same number of digits for any radix, since the /// significant digits balances out the zeros from the exponent: /// 1. Decimal is 1091 digits, 767 mantissa digits + 324 exponent zeros. /// 2. Base 6 is 1097 digits, or 680 mantissa digits + 417 exponent zeros. /// 3. Base 36 is 1086 digits, or 877 mantissa digits + 209 exponent zeros. /// /// However, the number of bytes required is larger for large radixes: /// for decimal, we need `log2(10**1091) ≅ 3600`, while for base 36 /// we need `log2(36**1086) ≅ 5600`. Since we use uninitialized data, /// we avoid a major performance hit from the large buffer size. pub data: StackVec, } impl Bigint { /// Construct a bigfloat representing 0. #[inline(always)] pub const fn new() -> Self { Self { data: StackVec::new(), } } /// Construct a bigfloat from an integer. #[inline(always)] pub fn from_u32(value: u32) -> Self { Self { data: StackVec::from_u32(value), } } /// Construct a bigfloat from an integer. #[inline(always)] pub fn from_u64(value: u64) -> Self { Self { data: StackVec::from_u64(value), } } #[inline(always)] pub fn hi64(&self) -> (u64, bool) { self.data.hi64() } /// Multiply and assign as if by exponentiation by a power. #[inline] pub fn pow(&mut self, base: u32, exp: u32) -> Option<()> { let (odd, shift) = split_radix(base); if odd != 0 { pow::(&mut self.data, odd, exp)?; } if shift != 0 { shl(&mut self.data, (exp * shift) as usize)?; } Some(()) } /// Calculate the bit-length of the big-integer. #[inline] pub fn bit_length(&self) -> u32 { bit_length(&self.data) } } impl ops::MulAssign<&Bigint> for Bigint { fn mul_assign(&mut self, rhs: &Bigint) { self.data *= &rhs.data; } } /// Number of bits in a Bigfloat. /// /// This needs to be at least the number of bits required to store /// a Bigint, which is `F::EXPONENT_BIAS + F::BITS`. /// Bias ≅ 1075, with 64 extra for the digits. #[cfg(feature = "radix")] const BIGFLOAT_BITS: usize = 1200; /// The number of limbs for the Bigfloat. #[cfg(feature = "radix")] const BIGFLOAT_LIMBS: usize = BIGFLOAT_BITS / LIMB_BITS; /// Storage for a big floating-point type. /// /// This is used for the algorithm with a non-finite digit count, which creates /// a representation of `b+h` and the float scaled into the range `[1, radix)`. #[cfg(feature = "radix")] #[derive(Clone, PartialEq, Eq)] pub struct Bigfloat { /// Significant digits for the float, stored in a big integer in LE order. /// /// This only needs ~1075 bits for the exponent, and ~64 more for the /// significant digits, since it's based on a theoretical representation /// of the halfway point. This means we can have a significantly smaller /// representation. The largest 64-bit exponent in magnitude is 2^1074, /// which will produce the same number of bits in any radix. pub data: StackVec, /// Binary exponent for the float type. pub exp: i32, } #[cfg(feature = "radix")] impl Bigfloat { /// Construct a bigfloat representing 0. #[inline(always)] pub const fn new() -> Self { Self { data: StackVec::new(), exp: 0, } } /// Construct a bigfloat from an extended-precision float. #[inline(always)] pub fn from_float(fp: ExtendedFloat80) -> Self { Self { data: StackVec::from_u64(fp.mant), exp: fp.exp, } } /// Construct a bigfloat from an integer. #[inline(always)] pub fn from_u32(value: u32) -> Self { Self { data: StackVec::from_u32(value), exp: 0, } } /// Construct a bigfloat from an integer. #[inline(always)] pub fn from_u64(value: u64) -> Self { Self { data: StackVec::from_u64(value), exp: 0, } } /// Multiply and assign as if by exponentiation by a power. #[inline] pub fn pow(&mut self, base: u32, exp: u32) -> Option<()> { let (odd, shift) = split_radix(base); if odd != 0 { pow::(&mut self.data, odd, exp)?; } if shift != 0 { self.exp += (exp * shift) as i32; } Some(()) } /// Shift-left the entire buffer n bits, where bits is less than the limb size. #[inline] pub fn shl_bits(&mut self, n: usize) -> Option<()> { shl_bits(&mut self.data, n) } /// Shift-left the entire buffer n limbs. #[inline] pub fn shl_limbs(&mut self, n: usize) -> Option<()> { shl_limbs(&mut self.data, n) } /// Shift-left the entire buffer n bits. #[inline] pub fn shl(&mut self, n: usize) -> Option<()> { shl(&mut self.data, n) } /// Get number of leading zero bits in the storage. /// Assumes the value is normalized. #[inline] pub fn leading_zeros(&self) -> u32 { leading_zeros(&self.data) } } #[cfg(feature = "radix")] impl ops::MulAssign<&Bigfloat> for Bigfloat { #[inline] #[allow(clippy::suspicious_op_assign_impl)] fn mul_assign(&mut self, rhs: &Bigfloat) { large_mul(&mut self.data, &rhs.data).unwrap(); self.exp += rhs.exp; } } // VEC // --- /// Simple stack vector implementation. #[derive(Clone)] pub struct StackVec { /// The raw buffer for the elements. data: [mem::MaybeUninit; SIZE], /// The number of elements in the array (we never need more than u16::MAX). length: u16, } /// Extract the hi bits from the buffer. macro_rules! hi { // # Safety // // Safe as long as the `stackvec.len() >= 1`. (@1 $self:ident, $rview:ident, $t:ident, $fn:ident) => {{ $fn(unsafe { index_unchecked!($rview[0]) as $t }) }}; // # Safety // // Safe as long as the `stackvec.len() >= 2`. (@2 $self:ident, $rview:ident, $t:ident, $fn:ident) => {{ let r0 = unsafe { index_unchecked!($rview[0]) as $t }; let r1 = unsafe { index_unchecked!($rview[1]) as $t }; $fn(r0, r1) }}; // # Safety // // Safe as long as the `stackvec.len() >= 2`. (@nonzero2 $self:ident, $rview:ident, $t:ident, $fn:ident) => {{ let (v, n) = hi!(@2 $self, $rview, $t, $fn); (v, n || unsafe { nonzero($self, 2 ) }) }}; // # Safety // // Safe as long as the `stackvec.len() >= 3`. (@3 $self:ident, $rview:ident, $t:ident, $fn:ident) => {{ let r0 = unsafe { index_unchecked!($rview[0]) as $t }; let r1 = unsafe { index_unchecked!($rview[1]) as $t }; let r2 = unsafe { index_unchecked!($rview[2]) as $t }; $fn(r0, r1, r2) }}; // # Safety // // Safe as long as the `stackvec.len() >= 3`. (@nonzero3 $self:ident, $rview:ident, $t:ident, $fn:ident) => {{ let (v, n) = hi!(@3 $self, $rview, $t, $fn); (v, n || unsafe { nonzero($self, 3 ) }) }}; } impl StackVec { /// Construct an empty vector. #[inline] pub const fn new() -> Self { Self { length: 0, data: [mem::MaybeUninit::uninit(); SIZE], } } /// Get a mutable ptr to the current start of the big integer. #[inline] pub fn as_mut_ptr(&mut self) -> *mut Limb { self.data.as_mut_ptr().cast::() } /// Get a ptr to the current start of the big integer. #[inline] pub fn as_ptr(&self) -> *const Limb { self.data.as_ptr().cast::() } /// Construct a vector from an existing slice. #[inline] pub fn try_from(x: &[Limb]) -> Option { let mut vec = Self::new(); vec.try_extend(x)?; Some(vec) } /// Sets the length of a vector. /// /// This will explicitly set the size of the vector, without actually /// modifying its buffers, so it is up to the caller to ensure that the /// vector is actually the specified size. /// /// # Safety /// /// Safe as long as `len` is less than `SIZE`. #[inline] pub unsafe fn set_len(&mut self, len: usize) { debug_assert!(len <= u16::MAX as usize); debug_assert!(len <= SIZE); self.length = len as u16; } /// The number of elements stored in the vector. #[inline] pub const fn len(&self) -> usize { self.length as usize } /// If the vector is empty. #[inline] pub const fn is_empty(&self) -> bool { self.len() == 0 } /// The number of items the vector can hold. #[inline] pub const fn capacity(&self) -> usize { SIZE as usize } /// Append an item to the vector, without bounds checking. /// /// # Safety /// /// Safe if `self.len() < self.capacity()`. #[inline] pub unsafe fn push_unchecked(&mut self, value: Limb) { debug_assert!(self.len() < self.capacity()); // SAFETY: safe, capacity is less than the current size. unsafe { let len = self.len(); let ptr = self.as_mut_ptr().add(len); ptr.write(value); self.length += 1; } } /// Append an item to the vector. #[inline] pub fn try_push(&mut self, value: Limb) -> Option<()> { if self.len() < self.capacity() { // SAFETY: safe, capacity is less than the current size. unsafe { self.push_unchecked(value) }; Some(()) } else { None } } /// Remove an item from the end of a vector, without bounds checking. /// /// # Safety /// /// Safe if `self.len() > 0`. #[inline] pub unsafe fn pop_unchecked(&mut self) -> Limb { debug_assert!(!self.is_empty()); // SAFETY: safe if `self.length > 0`. // We have a trivial drop and copy, so this is safe. self.length -= 1; unsafe { ptr::read(self.as_mut_ptr().add(self.len())) } } /// Remove an item from the end of the vector and return it, or None if empty. #[inline] pub fn pop(&mut self) -> Option { if self.is_empty() { None } else { // SAFETY: safe, since `self.len() > 0`. unsafe { Some(self.pop_unchecked()) } } } /// Add items from a slice to the vector, without bounds checking. /// /// # Safety /// /// Safe if `self.len() + slc.len() <= self.capacity()`. #[inline] pub unsafe fn extend_unchecked(&mut self, slc: &[Limb]) { let index = self.len(); let new_len = index + slc.len(); debug_assert!(self.len() + slc.len() <= self.capacity()); let src = slc.as_ptr(); // SAFETY: safe if `self.len() + slc.len() <= self.capacity()`. unsafe { let dst = self.as_mut_ptr().add(index); ptr::copy_nonoverlapping(src, dst, slc.len()); self.set_len(new_len); } } /// Copy elements from a slice and append them to the vector. #[inline] pub fn try_extend(&mut self, slc: &[Limb]) -> Option<()> { if self.len() + slc.len() <= self.capacity() { // SAFETY: safe, since `self.len() + slc.len() <= self.capacity()`. unsafe { self.extend_unchecked(slc) }; Some(()) } else { None } } /// Truncate vector to new length, dropping any items after `len`. /// /// # Safety /// /// Safe as long as `len <= self.capacity()`. unsafe fn truncate_unchecked(&mut self, len: usize) { debug_assert!(len <= self.capacity()); self.length = len as u16; } /// Resize the buffer, without bounds checking. /// /// # Safety /// /// Safe as long as `len <= self.capacity()`. #[inline] pub unsafe fn resize_unchecked(&mut self, len: usize, value: Limb) { debug_assert!(len <= self.capacity()); let old_len = self.len(); if len > old_len { // We have a trivial drop, so there's no worry here. // Just, don't set the length until all values have been written, // so we don't accidentally read uninitialized memory. // SAFETY: safe if `len < self.capacity()`. let count = len - old_len; for index in 0..count { unsafe { let dst = self.as_mut_ptr().add(old_len + index); ptr::write(dst, value); } } self.length = len as u16; } else { // SAFETY: safe since `len < self.len()`. unsafe { self.truncate_unchecked(len) }; } } /// Try to resize the buffer. /// /// If the new length is smaller than the current length, truncate /// the input. If it's larger, then append elements to the buffer. #[inline] pub fn try_resize(&mut self, len: usize, value: Limb) -> Option<()> { if len > self.capacity() { None } else { // SAFETY: safe, since `len <= self.capacity()`. unsafe { self.resize_unchecked(len, value) }; Some(()) } } // HI /// Get the high 16 bits from the vector. #[inline(always)] pub fn hi16(&self) -> (u16, bool) { let rview = self.rview(); // SAFETY: the buffer must be at least length bytes long. match self.len() { 0 => (0, false), 1 if LIMB_BITS == 32 => hi!(@1 self, rview, u32, u32_to_hi16_1), 1 => hi!(@1 self, rview, u64, u64_to_hi16_1), _ if LIMB_BITS == 32 => hi!(@nonzero2 self, rview, u32, u32_to_hi16_2), _ => hi!(@nonzero2 self, rview, u64, u64_to_hi16_2), } } /// Get the high 32 bits from the vector. #[inline(always)] pub fn hi32(&self) -> (u32, bool) { let rview = self.rview(); // SAFETY: the buffer must be at least length bytes long. match self.len() { 0 => (0, false), 1 if LIMB_BITS == 32 => hi!(@1 self, rview, u32, u32_to_hi32_1), 1 => hi!(@1 self, rview, u64, u64_to_hi32_1), _ if LIMB_BITS == 32 => hi!(@nonzero2 self, rview, u32, u32_to_hi32_2), _ => hi!(@nonzero2 self, rview, u64, u64_to_hi32_2), } } /// Get the high 64 bits from the vector. #[inline(always)] pub fn hi64(&self) -> (u64, bool) { let rview = self.rview(); // SAFETY: the buffer must be at least length bytes long. match self.len() { 0 => (0, false), 1 if LIMB_BITS == 32 => hi!(@1 self, rview, u32, u32_to_hi64_1), 1 => hi!(@1 self, rview, u64, u64_to_hi64_1), 2 if LIMB_BITS == 32 => hi!(@2 self, rview, u32, u32_to_hi64_2), 2 => hi!(@2 self, rview, u64, u64_to_hi64_2), _ if LIMB_BITS == 32 => hi!(@nonzero3 self, rview, u32, u32_to_hi64_3), _ => hi!(@nonzero2 self, rview, u64, u64_to_hi64_2), } } // FROM /// Create StackVec from u16 value. #[inline(always)] pub fn from_u16(x: u16) -> Self { let mut vec = Self::new(); assert!(1 <= vec.capacity()); // SAFETY: safe since we can always add 1 item. unsafe { vec.push_unchecked(x as Limb) }; vec.normalize(); vec } /// Create StackVec from u32 value. #[inline(always)] pub fn from_u32(x: u32) -> Self { let mut vec = Self::new(); assert!(1 <= vec.capacity()); // SAFETY: safe since we can always add 1 item. unsafe { vec.push_unchecked(x as Limb) }; vec.normalize(); vec } /// Create StackVec from u64 value. #[inline(always)] pub fn from_u64(x: u64) -> Self { let mut vec = Self::new(); assert!(2 <= vec.capacity()); if LIMB_BITS == 32 { // SAFETY: safe since we can always add 2 items. unsafe { vec.push_unchecked(x as Limb); vec.push_unchecked((x >> 32) as Limb); } } else { // SAFETY: safe since we can always add 1 item. unsafe { vec.push_unchecked(x as Limb) }; } vec.normalize(); vec } // INDEX /// Create a reverse view of the vector for indexing. #[inline] pub fn rview(&self) -> ReverseView { ReverseView { inner: &*self, } } // MATH /// Normalize the integer, so any leading zero values are removed. #[inline] pub fn normalize(&mut self) { // We don't care if this wraps: the index is bounds-checked. while let Some(&value) = self.get(self.len().wrapping_sub(1)) { if value == 0 { self.length -= 1; } else { break; } } } /// Get if the big integer is normalized. #[inline] #[allow(clippy::match_like_matches_macro)] pub fn is_normalized(&self) -> bool { // We don't care if this wraps: the index is bounds-checked. match self.get(self.len().wrapping_sub(1)) { Some(&0) => false, _ => true, } } /// Calculate the fast quotient for a single limb-bit quotient. /// /// This requires a non-normalized divisor, where there at least /// `integral_binary_factor` 0 bits set, to ensure at maximum a single /// digit will be produced for a single base. /// /// Warning: This is not a general-purpose division algorithm, /// it is highly specialized for peeling off singular digits. #[inline] #[cfg(feature = "radix")] pub fn quorem(&mut self, y: &Self) -> Limb { large_quorem(self, y) } /// AddAssign small integer. #[inline] pub fn add_small(&mut self, y: Limb) -> Option<()> { small_add(self, y) } /// MulAssign small integer. #[inline] pub fn mul_small(&mut self, y: Limb) -> Option<()> { small_mul(self, y) } } impl PartialEq for StackVec { #[inline] #[allow(clippy::op_ref)] fn eq(&self, other: &Self) -> bool { use core::ops::Deref; self.len() == other.len() && self.deref() == other.deref() } } impl Eq for StackVec { } impl cmp::PartialOrd for StackVec { #[inline] fn partial_cmp(&self, other: &Self) -> Option { Some(compare(self, other)) } } impl cmp::Ord for StackVec { #[inline] fn cmp(&self, other: &Self) -> cmp::Ordering { compare(self, other) } } impl ops::Deref for StackVec { type Target = [Limb]; #[inline] fn deref(&self) -> &[Limb] { // SAFETY: safe since `self.data[..self.len()]` must be initialized // and `self.len() <= self.capacity()`. unsafe { let ptr = self.data.as_ptr() as *const Limb; slice::from_raw_parts(ptr, self.len()) } } } impl ops::DerefMut for StackVec { #[inline] fn deref_mut(&mut self) -> &mut [Limb] { // SAFETY: safe since `self.data[..self.len()]` must be initialized // and `self.len() <= self.capacity()`. unsafe { let ptr = self.data.as_mut_ptr() as *mut Limb; slice::from_raw_parts_mut(ptr, self.len()) } } } impl ops::MulAssign<&[Limb]> for StackVec { #[inline] fn mul_assign(&mut self, rhs: &[Limb]) { large_mul(self, rhs).unwrap(); } } /// REVERSE VIEW /// Reverse, immutable view of a sequence. pub struct ReverseView<'a, T: 'a> { inner: &'a [T], } impl<'a, T: 'a> ReverseView<'a, T> { /// Get a reference to a value, without bounds checking. /// /// # Safety /// /// Safe if forward indexing would be safe for the type, /// or `index < self.inner.len()`. #[inline(always)] pub unsafe fn get_unchecked(&self, index: usize) -> &T { debug_assert!(index < self.inner.len()); let len = self.inner.len(); unsafe { self.inner.get_unchecked(len - index - 1) } } /// Get a reference to a value. #[inline(always)] pub fn get(&self, index: usize) -> Option<&T> { let len = self.inner.len(); // We don't care if this wraps: the index is bounds-checked. self.inner.get(len.wrapping_sub(index + 1)) } } impl<'a, T> ops::Index for ReverseView<'a, T> { type Output = T; #[inline] fn index(&self, index: usize) -> &T { let len = self.inner.len(); &(*self.inner)[len - index - 1] } } // HI // -- /// Check if any of the remaining bits are non-zero. /// /// # Safety /// /// Safe as long as `rindex <= x.len()`. #[inline] pub unsafe fn nonzero(x: &[Limb], rindex: usize) -> bool { debug_assert!(rindex <= x.len()); let len = x.len(); // SAFETY: safe if `rindex < x.len()`, since then `x.len() - rindex < x.len()`. let slc = unsafe { &index_unchecked!(x[..len - rindex]) }; slc.iter().rev().any(|&x| x != 0) } // These return the high X bits and if the bits were truncated. /// Shift 32-bit integer to high 16-bits. #[inline] pub const fn u32_to_hi16_1(r0: u32) -> (u16, bool) { let r0 = u32_to_hi32_1(r0).0; ((r0 >> 16) as u16, r0 as u16 != 0) } /// Shift 2 32-bit integers to high 16-bits. #[inline] pub const fn u32_to_hi16_2(r0: u32, r1: u32) -> (u16, bool) { let (r0, n) = u32_to_hi32_2(r0, r1); ((r0 >> 16) as u16, n || r0 as u16 != 0) } /// Shift 32-bit integer to high 32-bits. #[inline] pub const fn u32_to_hi32_1(r0: u32) -> (u32, bool) { let ls = r0.leading_zeros(); (r0 << ls, false) } /// Shift 2 32-bit integers to high 32-bits. #[inline] pub const fn u32_to_hi32_2(r0: u32, r1: u32) -> (u32, bool) { let ls = r0.leading_zeros(); let rs = 32 - ls; let v = match ls { 0 => r0, _ => (r0 << ls) | (r1 >> rs), }; let n = r1 << ls != 0; (v, n) } /// Shift 32-bit integer to high 64-bits. #[inline] pub const fn u32_to_hi64_1(r0: u32) -> (u64, bool) { u64_to_hi64_1(r0 as u64) } /// Shift 2 32-bit integers to high 64-bits. #[inline] pub const fn u32_to_hi64_2(r0: u32, r1: u32) -> (u64, bool) { let r0 = (r0 as u64) << 32; let r1 = r1 as u64; u64_to_hi64_1(r0 | r1) } /// Shift 3 32-bit integers to high 64-bits. #[inline] pub const fn u32_to_hi64_3(r0: u32, r1: u32, r2: u32) -> (u64, bool) { let r0 = r0 as u64; let r1 = (r1 as u64) << 32; let r2 = r2 as u64; u64_to_hi64_2(r0, r1 | r2) } /// Shift 64-bit integer to high 16-bits. #[inline] pub const fn u64_to_hi16_1(r0: u64) -> (u16, bool) { let r0 = u64_to_hi64_1(r0).0; ((r0 >> 48) as u16, r0 as u16 != 0) } /// Shift 2 64-bit integers to high 16-bits. #[inline] pub const fn u64_to_hi16_2(r0: u64, r1: u64) -> (u16, bool) { let (r0, n) = u64_to_hi64_2(r0, r1); ((r0 >> 48) as u16, n || r0 as u16 != 0) } /// Shift 64-bit integer to high 32-bits. #[inline] pub const fn u64_to_hi32_1(r0: u64) -> (u32, bool) { let r0 = u64_to_hi64_1(r0).0; ((r0 >> 32) as u32, r0 as u32 != 0) } /// Shift 2 64-bit integers to high 32-bits. #[inline] pub const fn u64_to_hi32_2(r0: u64, r1: u64) -> (u32, bool) { let (r0, n) = u64_to_hi64_2(r0, r1); ((r0 >> 32) as u32, n || r0 as u32 != 0) } /// Shift 64-bit integer to high 64-bits. #[inline] pub const fn u64_to_hi64_1(r0: u64) -> (u64, bool) { let ls = r0.leading_zeros(); (r0 << ls, false) } /// Shift 2 64-bit integers to high 64-bits. #[inline] pub const fn u64_to_hi64_2(r0: u64, r1: u64) -> (u64, bool) { let ls = r0.leading_zeros(); let rs = 64 - ls; let v = match ls { 0 => r0, _ => (r0 << ls) | (r1 >> rs), }; let n = r1 << ls != 0; (v, n) } // POWERS // ------ /// MulAssign by a power. /// /// Theoretically... /// /// Use an exponentiation by squaring method, since it reduces the time /// complexity of the multiplication to ~`O(log(n))` for the squaring, /// and `O(n*m)` for the result. Since `m` is typically a lower-order /// factor, this significantly reduces the number of multiplications /// we need to do. Iteratively multiplying by small powers follows /// the nth triangular number series, which scales as `O(p^2)`, but /// where `p` is `n+m`. In short, it scales very poorly. /// /// Practically.... /// /// Exponentiation by Squaring: /// running 2 tests /// test bigcomp_f32_lexical ... bench: 1,018 ns/iter (+/- 78) /// test bigcomp_f64_lexical ... bench: 3,639 ns/iter (+/- 1,007) /// /// Exponentiation by Iterative Small Powers: /// running 2 tests /// test bigcomp_f32_lexical ... bench: 518 ns/iter (+/- 31) /// test bigcomp_f64_lexical ... bench: 583 ns/iter (+/- 47) /// /// Exponentiation by Iterative Large Powers (of 2): /// running 2 tests /// test bigcomp_f32_lexical ... bench: 671 ns/iter (+/- 31) /// test bigcomp_f64_lexical ... bench: 1,394 ns/iter (+/- 47) /// /// The following benchmarks were run on `1 * 5^300`, using native `pow`, /// a version with only small powers, and one with pre-computed powers /// of `5^(3 * max_exp)`, rather than `5^(5 * max_exp)`. /// /// However, using large powers is crucial for good performance for higher /// powers. /// pow/default time: [426.20 ns 427.96 ns 429.89 ns] /// pow/small time: [2.9270 us 2.9411 us 2.9565 us] /// pow/large:3 time: [838.51 ns 842.21 ns 846.27 ns] /// /// Even using worst-case scenarios, exponentiation by squaring is /// significantly slower for our workloads. Just multiply by small powers, /// in simple cases, and use precalculated large powers in other cases. /// /// Furthermore, using sufficiently big large powers is also crucial for /// performance. This is a tradeoff of binary size and performance, and /// using a single value at ~`5^(5 * max_exp)` seems optimal. pub fn pow(x: &mut StackVec, base: u32, mut exp: u32) -> Option<()> { // Minimize the number of iterations for large exponents: just // do a few steps with a large powers. #[cfg(not(feature = "compact"))] { let (large, step) = get_large_int_power(base); while exp >= step { large_mul(x, large)?; exp -= step; } } // Now use our pre-computed small powers iteratively. let small_step = if LIMB_BITS == 32 { u32_power_limit(base) } else { u64_power_limit(base) }; let max_native = (base as Limb).pow(small_step); while exp >= small_step { small_mul(x, max_native)?; exp -= small_step; } if exp != 0 { // SAFETY: safe, since `exp < small_step`. let small_power = unsafe { f64::int_pow_fast_path(exp as usize, base) }; small_mul(x, small_power as Limb)?; } Some(()) } // SCALAR // ------ /// Add two small integers and return the resulting value and if overflow happens. #[inline(always)] pub fn scalar_add(x: Limb, y: Limb) -> (Limb, bool) { x.overflowing_add(y) } /// Multiply two small integers (with carry) (and return the overflow contribution). /// /// Returns the (low, high) components. #[inline(always)] pub fn scalar_mul(x: Limb, y: Limb, carry: Limb) -> (Limb, Limb) { // Cannot overflow, as long as wide is 2x as wide. This is because // the following is always true: // `Wide::MAX - (Narrow::MAX * Narrow::MAX) >= Narrow::MAX` let z: Wide = (x as Wide) * (y as Wide) + (carry as Wide); (z as Limb, (z >> LIMB_BITS) as Limb) } // SMALL // ----- /// Add small integer to bigint starting from offset. #[inline] pub fn small_add_from( x: &mut StackVec, y: Limb, start: usize, ) -> Option<()> { let mut index = start; let mut carry = y; while carry != 0 && index < x.len() { // SAFETY: safe, since `index < x.len()`. let result = scalar_add(unsafe { index_unchecked!(x[index]) }, carry); unsafe { index_unchecked_mut!(x[index]) = result.0 }; carry = result.1 as Limb; index += 1; } // If we carried past all the elements, add to the end of the buffer. if carry != 0 { x.try_push(carry)?; } Some(()) } /// Add small integer to bigint. #[inline(always)] pub fn small_add(x: &mut StackVec, y: Limb) -> Option<()> { small_add_from(x, y, 0) } /// Multiply bigint by small integer. #[inline] pub fn small_mul(x: &mut StackVec, y: Limb) -> Option<()> { let mut carry = 0; for xi in x.iter_mut() { let result = scalar_mul(*xi, y, carry); *xi = result.0; carry = result.1; } // If we carried past all the elements, add to the end of the buffer. if carry != 0 { x.try_push(carry)?; } Some(()) } // LARGE // ----- /// Add bigint to bigint starting from offset. pub fn large_add_from( x: &mut StackVec, y: &[Limb], start: usize, ) -> Option<()> { // The effective x buffer is from `xstart..x.len()`, so we need to treat // that as the current range. If the effective y buffer is longer, need // to resize to that, + the start index. if y.len() > x.len().saturating_sub(start) { // Ensure we panic if we can't extend the buffer. // This avoids any unsafe behavior afterwards. x.try_resize(y.len() + start, 0)?; } // Iteratively add elements from y to x. let mut carry = false; for index in 0..y.len() { // SAFETY: safe since `start + index < x.len()`. // We panicked in `try_resize` if this wasn't true. let xi = unsafe { &mut index_unchecked_mut!(x[start + index]) }; // SAFETY: safe since `index < y.len()`. let yi = unsafe { index_unchecked!(y[index]) }; // Only one op of the two ops can overflow, since we added at max // Limb::max_value() + Limb::max_value(). Add the previous carry, // and store the current carry for the next. let result = scalar_add(*xi, yi); *xi = result.0; let mut tmp = result.1; if carry { let result = scalar_add(*xi, 1); *xi = result.0; tmp |= result.1; } carry = tmp; } // Handle overflow. if carry { small_add_from(x, 1, y.len() + start)?; } Some(()) } /// Add bigint to bigint. #[inline(always)] pub fn large_add(x: &mut StackVec, y: &[Limb]) -> Option<()> { large_add_from(x, y, 0) } /// Grade-school multiplication algorithm. /// /// Slow, naive algorithm, using limb-bit bases and just shifting left for /// each iteration. This could be optimized with numerous other algorithms, /// but it's extremely simple, and works in O(n*m) time, which is fine /// by me. Each iteration, of which there are `m` iterations, requires /// `n` multiplications, and `n` additions, or grade-school multiplication. /// /// Don't use Karatsuba multiplication, since out implementation seems to /// be slower asymptotically, which is likely just due to the small sizes /// we deal with here. For example, running on the following data: /// /// ```text /// const SMALL_X: &[u32] = &[ /// 766857581, 3588187092, 1583923090, 2204542082, 1564708913, 2695310100, 3676050286, /// 1022770393, 468044626, 446028186 /// ]; /// const SMALL_Y: &[u32] = &[ /// 3945492125, 3250752032, 1282554898, 1708742809, 1131807209, 3171663979, 1353276095, /// 1678845844, 2373924447, 3640713171 /// ]; /// const LARGE_X: &[u32] = &[ /// 3647536243, 2836434412, 2154401029, 1297917894, 137240595, 790694805, 2260404854, /// 3872698172, 690585094, 99641546, 3510774932, 1672049983, 2313458559, 2017623719, /// 638180197, 1140936565, 1787190494, 1797420655, 14113450, 2350476485, 3052941684, /// 1993594787, 2901001571, 4156930025, 1248016552, 848099908, 2660577483, 4030871206, /// 692169593, 2835966319, 1781364505, 4266390061, 1813581655, 4210899844, 2137005290, /// 2346701569, 3715571980, 3386325356, 1251725092, 2267270902, 474686922, 2712200426, /// 197581715, 3087636290, 1379224439, 1258285015, 3230794403, 2759309199, 1494932094, /// 326310242 /// ]; /// const LARGE_Y: &[u32] = &[ /// 1574249566, 868970575, 76716509, 3198027972, 1541766986, 1095120699, 3891610505, /// 2322545818, 1677345138, 865101357, 2650232883, 2831881215, 3985005565, 2294283760, /// 3468161605, 393539559, 3665153349, 1494067812, 106699483, 2596454134, 797235106, /// 705031740, 1209732933, 2732145769, 4122429072, 141002534, 790195010, 4014829800, /// 1303930792, 3649568494, 308065964, 1233648836, 2807326116, 79326486, 1262500691, /// 621809229, 2258109428, 3819258501, 171115668, 1139491184, 2979680603, 1333372297, /// 1657496603, 2790845317, 4090236532, 4220374789, 601876604, 1828177209, 2372228171, /// 2247372529 /// ]; /// ``` /// /// We get the following results: /// ```text /// mul/small:long time: [220.23 ns 221.47 ns 222.81 ns] /// Found 4 outliers among 100 measurements (4.00%) /// 2 (2.00%) high mild /// 2 (2.00%) high severe /// mul/small:karatsuba time: [233.88 ns 234.63 ns 235.44 ns] /// Found 11 outliers among 100 measurements (11.00%) /// 8 (8.00%) high mild /// 3 (3.00%) high severe /// mul/large:long time: [1.9365 us 1.9455 us 1.9558 us] /// Found 12 outliers among 100 measurements (12.00%) /// 7 (7.00%) high mild /// 5 (5.00%) high severe /// mul/large:karatsuba time: [4.4250 us 4.4515 us 4.4812 us] /// ``` /// /// In short, Karatsuba multiplication is never worthwhile for out use-case. #[allow(clippy::needless_range_loop)] pub fn long_mul(x: &[Limb], y: &[Limb]) -> Option> { // Using the immutable value, multiply by all the scalars in y, using // the algorithm defined above. Use a single buffer to avoid // frequent reallocations. Handle the first case to avoid a redundant // addition, since we know y.len() >= 1. let mut z = StackVec::::try_from(x)?; if !y.is_empty() { // SAFETY: safe, since `y.len() > 0`. let y0 = unsafe { index_unchecked!(y[0]) }; small_mul(&mut z, y0)?; for index in 1..y.len() { // SAFETY: safe, since `index < y.len()`. let yi = unsafe { index_unchecked!(y[index]) }; if yi != 0 { let mut zi = StackVec::::try_from(x)?; small_mul(&mut zi, yi)?; large_add_from(&mut z, &zi, index)?; } } } z.normalize(); Some(z) } /// Multiply bigint by bigint using grade-school multiplication algorithm. #[inline(always)] pub fn large_mul(x: &mut StackVec, y: &[Limb]) -> Option<()> { // Karatsuba multiplication never makes sense, so just use grade school // multiplication. if y.len() == 1 { // SAFETY: safe since `y.len() == 1`. small_mul(x, unsafe { index_unchecked!(y[0]) })?; } else { *x = long_mul(y, x)?; } Some(()) } /// Emit a single digit for the quotient and store the remainder in-place. /// /// An extremely efficient division algorithm for small quotients, requiring /// you to know the full range of the quotient prior to use. For example, /// with a quotient that can range from [0, 10), you must have 4 leading /// zeros in the divisor, so we can use a single-limb division to get /// an accurate estimate of the quotient. Since we always underestimate /// the quotient, we can add 1 and then emit the digit. /// /// Requires a non-normalized denominator, with at least [1-6] leading /// zeros, depending on the base (for example, 1 for base2, 6 for base36). /// /// Adapted from David M. Gay's dtoa, and therefore under an MIT license: /// www.netlib.org/fp/dtoa.c #[cfg(feature = "radix")] #[allow(clippy::many_single_char_names)] pub fn large_quorem(x: &mut StackVec, y: &[Limb]) -> Limb { // If we have an empty divisor, error out early. assert!(!y.is_empty(), "large_quorem:: division by zero error."); assert!(x.len() <= y.len(), "large_quorem:: oversized numerator."); let mask = Limb::max_value() as Wide; // Numerator is smaller the denominator, quotient always 0. let m = x.len(); let n = y.len(); if m < n { return 0; } // Calculate our initial estimate for q. // SAFETY: safe since `m > 0 && m == x.len()`, since `m > n && n > 0`. let xm_1 = unsafe { index_unchecked!(x[m - 1]) }; // SAFETY: safe since `n > 0 && n == y.len()`. let yn_1 = unsafe { index_unchecked!(y[n - 1]) }; let mut q = xm_1 / (yn_1 + 1); // Need to calculate the remainder if we don't have a 0 quotient. if q != 0 { let mut borrow: Wide = 0; let mut carry: Wide = 0; for j in 0..m { // SAFETY: safe, since `j < n && n == y.len()`. let yj = unsafe { index_unchecked!(y[j]) } as Wide; let p = yj * q as Wide + carry; carry = p >> LIMB_BITS; // SAFETY: safe, since `j < m && m == x.len()`. let xj = unsafe { index_unchecked!(x[j]) } as Wide; let t = xj.wrapping_sub(p & mask).wrapping_sub(borrow); borrow = (t >> LIMB_BITS) & 1; // SAFETY: safe, since `j < m && m == x.len()`. unsafe { index_unchecked_mut!(x[j]) = t as Limb }; } x.normalize(); } // Check if we under-estimated x. if compare(x, y) != cmp::Ordering::Less { q += 1; let mut borrow: Wide = 0; let mut carry: Wide = 0; for j in 0..m { // SAFETY: safe, since `j < n && n == y.len()`. let yj = unsafe { index_unchecked!(y[j]) } as Wide; let p = yj + carry; carry = p >> LIMB_BITS; // SAFETY: safe, since `j < m && m == x.len()`. let xj = unsafe { index_unchecked!(x[j]) } as Wide; let t = xj.wrapping_sub(p & mask).wrapping_sub(borrow); borrow = (t >> LIMB_BITS) & 1; // SAFETY: safe, since `j < m && m == x.len()`. unsafe { index_unchecked_mut!(x[j]) = t as Limb }; } x.normalize(); } q } // COMPARE // ------- /// Compare `x` to `y`, in little-endian order. #[inline] pub fn compare(x: &[Limb], y: &[Limb]) -> cmp::Ordering { match x.len().cmp(&y.len()) { cmp::Ordering::Equal => { let iter = x.iter().rev().zip(y.iter().rev()); for (&xi, yi) in iter { match xi.cmp(yi) { cmp::Ordering::Equal => (), ord => return ord, } } // Equal case. cmp::Ordering::Equal }, ord => ord, } } // SHIFT // ----- /// Shift-left `n` bits inside a buffer. #[inline] pub fn shl_bits(x: &mut StackVec, n: usize) -> Option<()> { debug_assert!(n != 0); // Internally, for each item, we shift left by n, and add the previous // right shifted limb-bits. // For example, we transform (for u8) shifted left 2, to: // b10100100 b01000010 // b10 b10010001 b00001000 debug_assert!(n < LIMB_BITS); let rshift = LIMB_BITS - n; let lshift = n; let mut prev: Limb = 0; for xi in x.iter_mut() { let tmp = *xi; *xi <<= lshift; *xi |= prev >> rshift; prev = tmp; } // Always push the carry, even if it creates a non-normal result. let carry = prev >> rshift; if carry != 0 { x.try_push(carry)?; } Some(()) } /// Shift-left `n` limbs inside a buffer. #[inline] pub fn shl_limbs(x: &mut StackVec, n: usize) -> Option<()> { debug_assert!(n != 0); if n + x.len() > x.capacity() { None } else if !x.is_empty() { let len = n + x.len(); // SAFE: since x is not empty, and `x.len() + n <= x.capacity()`. unsafe { // Move the elements. let x_len = x.len(); let ptr = x.as_mut_ptr(); let src = ptr; let dst = ptr.add(n); ptr::copy(src, dst, x_len); // Write our 0s. ptr::write_bytes(ptr, 0, n); x.set_len(len); } Some(()) } else { Some(()) } } /// Shift-left buffer by n bits. #[inline] pub fn shl(x: &mut StackVec, n: usize) -> Option<()> { let rem = n % LIMB_BITS; let div = n / LIMB_BITS; if rem != 0 { shl_bits(x, rem)?; } if div != 0 { shl_limbs(x, div)?; } Some(()) } /// Get number of leading zero bits in the storage. #[inline] pub fn leading_zeros(x: &[Limb]) -> u32 { let length = x.len(); // wrapping_sub is fine, since it'll just return None. if let Some(&value) = x.get(length.wrapping_sub(1)) { value.leading_zeros() } else { 0 } } /// Calculate the bit-length of the big-integer. #[inline] pub fn bit_length(x: &[Limb]) -> u32 { let nlz = leading_zeros(x); LIMB_BITS as u32 * x.len() as u32 - nlz } // RADIX // ----- /// Get the base, odd radix, and the power-of-two for the type. #[inline(always)] pub const fn split_radix(radix: u32) -> (u32, u32) { match radix { // Is also needed for decimal floats, due to `negative_digit_comp`. 2 => (0, 1), 3 if cfg!(feature = "radix") => (3, 0), 4 if cfg!(feature = "power-of-two") => (0, 2), // Is also needed for decimal floats, due to `negative_digit_comp`. 5 => (5, 0), 6 if cfg!(feature = "radix") => (3, 1), 7 if cfg!(feature = "radix") => (7, 0), 8 if cfg!(feature = "power-of-two") => (0, 3), 9 if cfg!(feature = "radix") => (9, 0), 10 => (5, 1), 11 if cfg!(feature = "radix") => (11, 0), 12 if cfg!(feature = "radix") => (6, 1), 13 if cfg!(feature = "radix") => (13, 0), 14 if cfg!(feature = "radix") => (7, 1), 15 if cfg!(feature = "radix") => (15, 0), 16 if cfg!(feature = "power-of-two") => (0, 4), 17 if cfg!(feature = "radix") => (17, 0), 18 if cfg!(feature = "radix") => (9, 1), 19 if cfg!(feature = "radix") => (19, 0), 20 if cfg!(feature = "radix") => (5, 2), 21 if cfg!(feature = "radix") => (21, 0), 22 if cfg!(feature = "radix") => (11, 1), 23 if cfg!(feature = "radix") => (23, 0), 24 if cfg!(feature = "radix") => (3, 3), 25 if cfg!(feature = "radix") => (25, 0), 26 if cfg!(feature = "radix") => (13, 1), 27 if cfg!(feature = "radix") => (27, 0), 28 if cfg!(feature = "radix") => (7, 2), 29 if cfg!(feature = "radix") => (29, 0), 30 if cfg!(feature = "radix") => (15, 1), 31 if cfg!(feature = "radix") => (31, 0), 32 if cfg!(feature = "power-of-two") => (0, 5), 33 if cfg!(feature = "radix") => (33, 0), 34 if cfg!(feature = "radix") => (17, 1), 35 if cfg!(feature = "radix") => (35, 0), 36 if cfg!(feature = "radix") => (9, 2), // Any other radix should be unreachable. _ => (0, 0), } } // LIMB // ---- // Type for a single limb of the big integer. // // A limb is analogous to a digit in base10, except, it stores 32-bit // or 64-bit numbers instead. We want types where 64-bit multiplication // is well-supported by the architecture, rather than emulated in 3 // instructions. The quickest way to check this support is using a // cross-compiler for numerous architectures, along with the following // source file and command: // // Compile with `gcc main.c -c -S -O3 -masm=intel` // // And the source code is: // ```text // #include // // struct i128 { // uint64_t hi; // uint64_t lo; // }; // // // Type your code here, or load an example. // struct i128 square(uint64_t x, uint64_t y) { // __int128 prod = (__int128)x * (__int128)y; // struct i128 z; // z.hi = (uint64_t)(prod >> 64); // z.lo = (uint64_t)prod; // return z; // } // ``` // // If the result contains `call __multi3`, then the multiplication // is emulated by the compiler. Otherwise, it's natively supported. // // This should be all-known 64-bit platforms supported by Rust. // https://forge.rust-lang.org/platform-support.html // // # Supported // // Platforms where native 128-bit multiplication is explicitly supported: // - x86_64 (Supported via `MUL`). // - mips64 (Supported via `DMULTU`, which `HI` and `LO` can be read-from). // - s390x (Supported via `MLGR`). // // # Efficient // // Platforms where native 64-bit multiplication is supported and // you can extract hi-lo for 64-bit multiplications. // - aarch64 (Requires `UMULH` and `MUL` to capture high and low bits). // - powerpc64 (Requires `MULHDU` and `MULLD` to capture high and low bits). // - riscv64 (Requires `MUL` and `MULH` to capture high and low bits). // // # Unsupported // // Platforms where native 128-bit multiplication is not supported, // requiring software emulation. // sparc64 (`UMUL` only supports double-word arguments). // sparcv9 (Same as sparc64). // // These tests are run via `xcross`, my own library for C cross-compiling, // which supports numerous targets (far in excess of Rust's tier 1 support, // or rust-embedded/cross's list). xcross may be found here: // https://github.com/Alexhuszagh/xcross // // To compile for the given target, run: // `xcross gcc main.c -c -S -O3 --target $target` // // All 32-bit architectures inherently do not have support. That means // we can essentially look for 64-bit architectures that are not SPARC. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub type Limb = u64; #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub type Wide = u128; #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub type SignedWide = i128; #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LIMB_BITS: usize = 64; #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub type Limb = u32; #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub type Wide = u64; #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub type SignedWide = i64; #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LIMB_BITS: usize = 32; lexical-parse-float-0.8.5/src/binary.rs000064400000000000000000000155330072674642500161520ustar 00000000000000//! Optimized float parser for radixes powers of 2. //! //! Note: this does not require the mantissa radix and the //! exponent base to be the same. #![cfg(feature = "power-of-two")] #![doc(hidden)] use crate::float::{ExtendedFloat80, RawFloat}; use crate::mask::lower_n_halfway; use crate::number::Number; use crate::shared; #[cfg(not(feature = "compact"))] use lexical_parse_integer::algorithm; use lexical_util::digit::char_to_valid_digit_const; use lexical_util::format::NumberFormat; use lexical_util::iterator::{AsBytes, BytesIter}; use lexical_util::step::u64_step; // ALGORITHM // --------- /// Algorithm specialized for radixes of powers-of-two. #[inline] pub fn binary(num: &Number, lossy: bool) -> ExtendedFloat80 { let format = NumberFormat::<{ FORMAT }> {}; debug_assert!(matches!(format.radix(), 2 | 4 | 8 | 16 | 32)); let fp_zero = ExtendedFloat80 { mant: 0, exp: 0, }; // Normalize our mantissa for simpler results. let ctlz = num.mantissa.leading_zeros(); let mantissa = num.mantissa << ctlz; // Quick check if we're close to a halfway point. // Since we're using powers-of-two, we can clearly tell if we're at // a halfway point, unless it's even and we're exactly halfway so far. // This is true even for radixes like 8 and 32, where `log2(radix)` // is not a power-of-two. If it's odd and we're at halfway, we'll // always round-up **anyway**. // // We need to check the truncated bits are equal to 0b100000...., // if it's above that, always round-up. If it's odd, we can always // disambiguate the float. If it's even, and exactly halfway, this // step fails. let power2 = shared::calculate_power2::(num.exponent, ctlz); if -power2 + 1 >= 64 { // Have more than 63 bits below the minimum exponent, must be 0. // Since we can't have partial digit rounding, this is true always // if the power-of-two >= 64. return fp_zero; } // Get our shift to shift the digits to the hidden bit, or correct spot. // This differs for denormal floats, so do that carefully, but that's // relative to the current leading zeros of the float. let shift = shared::calculate_shift::(power2); // Determine if we can see if we're at a halfway point. let last_bit = 1u64 << shift; let truncated = last_bit - 1; let halfway = lower_n_halfway(shift as u64); let is_even = mantissa & last_bit == 0; let is_halfway = mantissa & truncated == halfway; if !lossy && is_even && is_halfway && num.many_digits { // Exactly halfway and even, cannot safely determine our representation. // Bias the exponent so we know it's invalid. return ExtendedFloat80 { mant: mantissa, exp: power2 + shared::INVALID_FP, }; } // Shift our digits into place, and round up if needed. let is_above = mantissa & truncated > halfway; let round_up = is_above || (!is_even && is_halfway); let mut fp = ExtendedFloat80 { mant: mantissa, exp: power2, }; shared::round::(&mut fp, |f, s| { shared::round_nearest_tie_even(f, s, |_, _, _| round_up); }); fp } /// Iteratively parse and consume digits without overflowing. #[inline] #[allow(unused_mut)] pub fn parse_u64_digits<'a, Iter, const FORMAT: u128>( mut iter: Iter, mantissa: &mut u64, step: &mut usize, overflowed: &mut bool, zero: &mut bool, ) where Iter: BytesIter<'a>, { let format = NumberFormat::<{ FORMAT }> {}; let radix = format.radix() as u64; // Try to parse 8 digits at a time, if we can. #[cfg(not(feature = "compact"))] if can_try_parse_8digits!(iter, radix) { let radix2 = radix.wrapping_mul(radix); let radix4 = radix2.wrapping_mul(radix2); let radix8 = radix4.wrapping_mul(radix4); while *step > 8 { if let Some(v) = algorithm::try_parse_8digits::(&mut iter) { *mantissa = mantissa.wrapping_mul(radix8).wrapping_add(v); *step -= 8; } else { break; } } } // Parse single digits at a time. for &c in iter { let digit = char_to_valid_digit_const(c, radix as _); if !*overflowed { let result = mantissa.checked_mul(radix as _).and_then(|x| x.checked_add(digit as _)); if let Some(mant) = result { *mantissa = mant; } else { *overflowed = true; *zero &= digit == 0; } } else { *zero &= digit == 0; } *step = step.saturating_sub(1); } } /// Fallback, slow algorithm optimized for powers-of-two. /// /// This avoids the need for arbitrary-precision arithmetic, since the result /// will always be a near-halfway representation where rounded-down it's even. #[inline] pub fn slow_binary(num: Number) -> ExtendedFloat80 { let format = NumberFormat::<{ FORMAT }> {}; let radix = format.radix(); debug_assert!(matches!(radix, 2 | 4 | 8 | 16 | 32)); // This assumes the sign bit has already been parsed, and we're // starting with the integer digits, and the float format has been // correctly validated. // This is quite simple: parse till we get overflow, check if all // the remaining digits are zero/non-zero, and determine if we round-up // or down as a result. let mut mantissa = 0_u64; let mut overflow = false; let mut zero = true; // Parse the integer digits. let mut step = u64_step(radix); let mut integer = num.integer.bytes::(); integer.integer_iter().skip_zeros(); parse_u64_digits::<_, FORMAT>( integer.integer_iter(), &mut mantissa, &mut step, &mut overflow, &mut zero, ); // Parse the fraction digits. if let Some(fraction) = num.fraction { let mut fraction = fraction.bytes::(); if mantissa == 0 { fraction.fraction_iter().skip_zeros(); } parse_u64_digits::<_, FORMAT>( fraction.fraction_iter(), &mut mantissa, &mut step, &mut overflow, &mut zero, ); } // Note: we're not guaranteed to have overflowed here, although it's // very, very likely. We can also skip the exponent, since we already // know it, and we already know the total parsed digits. // Normalize our mantissa for simpler results. let ctlz = mantissa.leading_zeros(); mantissa <<= ctlz; let power2 = shared::calculate_power2::(num.exponent, ctlz); let mut fp = ExtendedFloat80 { mant: mantissa, exp: power2, }; shared::round::(&mut fp, |f, s| { shared::round_nearest_tie_even(f, s, |_, _, _| !zero); }); fp } lexical-parse-float-0.8.5/src/float.rs000064400000000000000000000157230072674642500157740ustar 00000000000000//! Extended helper trait for generic float types. //! //! This adapted from the Rust implementation, based on the fast-float-rust //! implementation, and is similarly subject to an Apache2.0/MIT license. #![doc(hidden)] #[cfg(all(not(feature = "std"), feature = "compact"))] use crate::libm::{powd, powf}; use crate::limits::{ExactFloat, MaxDigits}; #[cfg(not(feature = "compact"))] use crate::table::{get_small_f32_power, get_small_f64_power, get_small_int_power}; #[cfg(feature = "f16")] use lexical_util::bf16::bf16; use lexical_util::extended_float::ExtendedFloat; #[cfg(feature = "f16")] use lexical_util::f16::f16; use lexical_util::num::{AsCast, Float}; /// Alias with ~80 bits of precision, 64 for the mantissa and 16 for exponent. /// This exponent is biased, and if the exponent is negative, it represents /// a value with a bias of `i32::MIN + F::EXPONENT_BIAS`. pub type ExtendedFloat80 = ExtendedFloat; /// Helper trait to add more float characteristics for parsing floats. pub trait RawFloat: Float + ExactFloat + MaxDigits { // Maximum mantissa for the fast-path (`1 << 53` for f64). const MAX_MANTISSA_FAST_PATH: u64 = 2_u64 << Self::MANTISSA_SIZE; // Largest exponent value `(1 << EXP_BITS) - 1`. const INFINITE_POWER: i32 = Self::MAX_EXPONENT + Self::EXPONENT_BIAS; /// Minimum exponent that for a fast path case, or `-⌊(MANTISSA_SIZE+1)/log2(r)⌋` /// where `r` is the radix with powers-of-two removed. #[inline(always)] fn min_exponent_fast_path(radix: u32) -> i64 { Self::exponent_limit(radix).0 } /// Maximum exponent that for a fast path case, or `⌊(MANTISSA_SIZE+1)/log2(r)⌋` /// where `r` is the radix with powers-of-two removed. #[inline(always)] fn max_exponent_fast_path(radix: u32) -> i64 { Self::exponent_limit(radix).1 } // Maximum exponent that can be represented for a disguised-fast path case. // This is `max_exponent_fast_path(radix) + ⌊(MANTISSA_SIZE+1)/log2(radix)⌋` #[inline(always)] fn max_exponent_disguised_fast_path(radix: u32) -> i64 { Self::max_exponent_fast_path(radix) + Self::mantissa_limit(radix) } /// Get a small power-of-radix for fast-path multiplication. /// /// # Safety /// /// Safe as long as the exponent is smaller than the table size. unsafe fn pow_fast_path(exponent: usize, radix: u32) -> Self; /// Get a small, integral power-of-radix for fast-path multiplication. /// /// # Safety /// /// Safe as long as the exponent is smaller than the table size. #[inline(always)] unsafe fn int_pow_fast_path(exponent: usize, radix: u32) -> u64 { // SAFETY: safe as long as the exponent is smaller than the radix table. #[cfg(not(feature = "compact"))] return unsafe { get_small_int_power(exponent, radix) }; #[cfg(feature = "compact")] return (radix as u64).wrapping_pow(exponent as u32); } } impl RawFloat for f32 { #[inline(always)] unsafe fn pow_fast_path(exponent: usize, radix: u32) -> Self { // SAFETY: safe as long as the exponent is smaller than the radix table. #[cfg(not(feature = "compact"))] return unsafe { get_small_f32_power(exponent, radix) }; #[cfg(feature = "compact")] return powf(radix as f32, exponent as f32); } } impl RawFloat for f64 { #[inline(always)] unsafe fn pow_fast_path(exponent: usize, radix: u32) -> Self { // SAFETY: safe as long as the exponent is smaller than the radix table. #[cfg(not(feature = "compact"))] return unsafe { get_small_f64_power(exponent, radix) }; #[cfg(feature = "compact")] return powd(radix as f64, exponent as f64); } } #[cfg(feature = "f16")] impl RawFloat for f16 { #[inline(always)] unsafe fn pow_fast_path(_: usize, _: u32) -> Self { unimplemented!() } } #[cfg(feature = "f16")] impl RawFloat for bf16 { #[inline(always)] unsafe fn pow_fast_path(_: usize, _: u32) -> Self { unimplemented!() } } /// Helper trait to add more float characteristics for the Eisel-Lemire algorithm. pub trait LemireFloat: RawFloat { // Round-to-even only happens for negative values of q // when q ≥ −4 in the 64-bit case and when q ≥ −17 in // the 32-bitcase. // // When q ≥ 0,we have that 5^q ≤ 2m+1. In the 64-bit case,we // have 5^q ≤ 2m+1 ≤ 2^54 or q ≤ 23. In the 32-bit case,we have // 5^q ≤ 2m+1 ≤ 2^25 or q ≤ 10. // // When q < 0, we have w ≥ (2m+1)×5^−q. We must have that w < 2^64 // so (2m+1)×5^−q < 2^64. We have that 2m+1 > 2^53 (64-bit case) // or 2m+1 > 2^24 (32-bit case). Hence,we must have 2^53×5^−q < 2^64 // (64-bit) and 2^24×5^−q < 2^64 (32-bit). Hence we have 5^−q < 2^11 // or q ≥ −4 (64-bit case) and 5^−q < 2^40 or q ≥ −17 (32-bitcase). // // Thus we have that we only need to round ties to even when // we have that q ∈ [−4,23](in the 64-bit case) or q∈[−17,10] // (in the 32-bit case). In both cases,the power of five(5^|q|) // fits in a 64-bit word. const MIN_EXPONENT_ROUND_TO_EVEN: i32; const MAX_EXPONENT_ROUND_TO_EVEN: i32; /// Minimum normal exponent value `-(1 << (EXPONENT_SIZE - 1)) + 1`. const MINIMUM_EXPONENT: i32; /// Smallest decimal exponent for a non-zero value. const SMALLEST_POWER_OF_TEN: i32; /// Largest decimal exponent for a non-infinite value. const LARGEST_POWER_OF_TEN: i32; } impl LemireFloat for f32 { const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17; const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10; const MINIMUM_EXPONENT: i32 = -127; const SMALLEST_POWER_OF_TEN: i32 = -65; const LARGEST_POWER_OF_TEN: i32 = 38; } impl LemireFloat for f64 { const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4; const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23; const MINIMUM_EXPONENT: i32 = -1023; const SMALLEST_POWER_OF_TEN: i32 = -342; const LARGEST_POWER_OF_TEN: i32 = 308; } #[cfg(feature = "f16")] impl LemireFloat for f16 { const MIN_EXPONENT_ROUND_TO_EVEN: i32 = 0; const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 0; const MINIMUM_EXPONENT: i32 = 0; const SMALLEST_POWER_OF_TEN: i32 = 0; const LARGEST_POWER_OF_TEN: i32 = 0; } #[cfg(feature = "f16")] impl LemireFloat for bf16 { const MIN_EXPONENT_ROUND_TO_EVEN: i32 = 0; const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 0; const MINIMUM_EXPONENT: i32 = 0; const SMALLEST_POWER_OF_TEN: i32 = 0; const LARGEST_POWER_OF_TEN: i32 = 0; } #[inline(always)] #[cfg(all(feature = "std", feature = "compact"))] pub fn powf(x: f32, y: f32) -> f32 { x.powf(y) } #[inline(always)] #[cfg(all(feature = "std", feature = "compact"))] pub fn powd(x: f64, y: f64) -> f64 { x.powf(y) } /// Converts an `ExtendedFloat` to the closest machine float type. #[inline(always)] pub fn extended_to_float(x: ExtendedFloat80) -> F { let mut word = x.mant; word |= (x.exp as u64) << F::MANTISSA_SIZE; F::from_bits(F::Unsigned::as_cast(word)) } lexical-parse-float-0.8.5/src/fpu.rs000064400000000000000000000076700072674642500154630ustar 00000000000000//! Platform-specific, assembly instructions to avoid //! intermediate rounding on architectures with FPUs. //! //! This is adapted from the implementation in the Rust core library, //! the original implementation can be [here](https://github.com/rust-lang/rust/blob/master/library/core/src/num/dec2flt/fpu.rs). //! //! It is therefore also subject to a Apache2.0/MIT license. #![cfg(feature = "nightly")] #![doc(hidden)] pub use fpu_precision::set_precision; // On x86, the x87 FPU is used for float operations if the SSE/SSE2 extensions are not available. // The x87 FPU operates with 80 bits of precision by default, which means that operations will // round to 80 bits causing double rounding to happen when values are eventually represented as // 32/64 bit float values. To overcome this, the FPU control word can be set so that the // computations are performed in the desired precision. #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] mod fpu_precision { // We only support the latest nightly, which is 1.59+. // THe `asm!` macro was stabilized in 1.59.0. use core::arch::asm; use core::mem::size_of; /// A structure used to preserve the original value of the FPU control word, so that it can be /// restored when the structure is dropped. /// /// The x87 FPU is a 16-bits register whose fields are as follows: /// /// | 12-15 | 10-11 | 8-9 | 6-7 | 5 | 4 | 3 | 2 | 1 | 0 | /// |------:|------:|----:|----:|---:|---:|---:|---:|---:|---:| /// | | RC | PC | | PM | UM | OM | ZM | DM | IM | /// /// The documentation for all of the fields is available in the IA-32 Architectures Software /// Developer's Manual (Volume 1). /// /// The only field which is relevant for the following code is PC, Precision Control. This /// field determines the precision of the operations performed by the FPU. It can be set to: /// - 0b00, single precision i.e., 32-bits /// - 0b10, double precision i.e., 64-bits /// - 0b11, double extended precision i.e., 80-bits (default state) /// The 0b01 value is reserved and should not be used. pub struct FPUControlWord(u16); fn set_cw(cw: u16) { // SAFETY: the `fldcw` instruction has been audited to be able to work correctly with // any `u16` unsafe { asm!( "fldcw word ptr [{}]", in(reg) &cw, options(nostack), ) } } /// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`. pub fn set_precision() -> FPUControlWord { let mut cw = 0_u16; // Compute the value for the Precision Control field that is appropriate for `T`. let cw_precision = match size_of::() { 4 => 0x0000, // 32 bits 8 => 0x0200, // 64 bits _ => 0x0300, // default, 80 bits }; // Get the original value of the control word to restore it later, when the // `FPUControlWord` structure is dropped // SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with // any `u16` unsafe { asm!( "fnstcw word ptr [{}]", in(reg) &mut cw, options(nostack), ) } // Set the control word to the desired precision. This is achieved by masking away the old // precision (bits 8 and 9, 0x300) and replacing it with the precision flag computed above. set_cw((cw & 0xFCFF) | cw_precision); FPUControlWord(cw) } impl Drop for FPUControlWord { fn drop(&mut self) { set_cw(self.0) } } } // In most architectures, floating point operations have an explicit bit size, therefore the // precision of the computation is determined on a per-operation basis. #[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))] mod fpu_precision { pub fn set_precision() { } } lexical-parse-float-0.8.5/src/index.rs000064400000000000000000000021020072674642500157610ustar 00000000000000//! Wrapper around indexing for opt-in, additional safety. //! //! This is used very sparing in parsers, only when code can trivially //! be shown to be safe, since parsers are tricky to validate. #![cfg_attr(not(feature = "power-of-two"), allow(unused_macros))] #![doc(hidden)] /// Index a buffer, without bounds checking. #[cfg(not(feature = "safe"))] macro_rules! index_unchecked { ($x:ident[$i:expr]) => { *$x.get_unchecked($i) }; } /// Index a buffer and get a mutable reference, without bounds checking. #[cfg(not(feature = "safe"))] #[allow(unknown_lints, unused_macro_rules)] macro_rules! index_unchecked_mut { ($x:ident[$i:expr]) => { *$x.get_unchecked_mut($i) }; } /// Index a buffer, with bounds checking. #[cfg(feature = "safe")] macro_rules! index_unchecked { ($x:ident[$i:expr]) => { $x[$i] }; } /// Index a buffer and get a mutable reference, with bounds checking. #[cfg(feature = "safe")] #[allow(unknown_lints, unused_macro_rules)] macro_rules! index_unchecked_mut { ($x:ident[$i:expr]) => { $x[$i] }; } lexical-parse-float-0.8.5/src/lemire.rs000064400000000000000000000221560072674642500161420ustar 00000000000000//! Implementation of the Eisel-Lemire algorithm. //! //! This is adapted from [fast-float-rust](https://github.com/aldanor/fast-float-rust), //! a port of [fast_float](https://github.com/fastfloat/fast_float) to Rust. #![cfg(not(feature = "compact"))] #![doc(hidden)] use crate::float::{ExtendedFloat80, LemireFloat}; use crate::number::Number; use crate::shared; use crate::table::{LARGEST_POWER_OF_FIVE, POWER_OF_FIVE_128, SMALLEST_POWER_OF_FIVE}; /// Ensure truncation of digits doesn't affect our computation, by doing 2 passes. #[inline] pub fn lemire(num: &Number, lossy: bool) -> ExtendedFloat80 { // If significant digits were truncated, then we can have rounding error // only if `mantissa + 1` produces a different result. We also avoid // redundantly using the Eisel-Lemire algorithm if it was unable to // correctly round on the first pass. let mut fp = compute_float::(num.exponent, num.mantissa, lossy); if !lossy && num.many_digits && fp.exp >= 0 && fp != compute_float::(num.exponent, num.mantissa + 1, false) { // Need to re-calculate, since the previous values are rounded // when the slow path algorithm expects a normalized extended float. fp = compute_error::(num.exponent, num.mantissa); } fp } /// Compute a float using an extended-precision representation. /// /// Fast conversion of a the significant digits and decimal exponent /// a float to a extended representation with a binary float. This /// algorithm will accurately parse the vast majority of cases, /// and uses a 128-bit representation (with a fallback 192-bit /// representation). /// /// This algorithm scales the exponent by the decimal exponent /// using pre-computed powers-of-5, and calculates if the /// representation can be unambiguously rounded to the nearest /// machine float. Near-halfway cases are not handled here, /// and are represented by a negative, biased binary exponent. /// /// The algorithm is described in detail in "Daniel Lemire, Number Parsing /// at a Gigabyte per Second" in section 5, "Fast Algorithm", and /// section 6, "Exact Numbers And Ties", available online: /// . pub fn compute_float(q: i64, mut w: u64, lossy: bool) -> ExtendedFloat80 { let fp_zero = ExtendedFloat80 { mant: 0, exp: 0, }; let fp_inf = ExtendedFloat80 { mant: 0, exp: F::INFINITE_POWER, }; // Short-circuit if the value can only be a literal 0 or infinity. if w == 0 || q < F::SMALLEST_POWER_OF_TEN as i64 { return fp_zero; } else if q > F::LARGEST_POWER_OF_TEN as i64 { return fp_inf; } // Normalize our significant digits, so the most-significant bit is set. let lz = w.leading_zeros() as i32; w <<= lz; let (lo, hi) = compute_product_approx(q, w, F::MANTISSA_SIZE as usize + 3); if !lossy && lo == 0xFFFF_FFFF_FFFF_FFFF { // If we have failed to approximate w x 5^-q with our 128-bit value. // Since the addition of 1 could lead to an overflow which could then // round up over the half-way point, this can lead to improper rounding // of a float. // // However, this can only occur if q ∈ [-27, 55]. The upper bound of q // is 55 because 5^55 < 2^128, however, this can only happen if 5^q > 2^64, // since otherwise the product can be represented in 64-bits, producing // an exact result. For negative exponents, rounding-to-even can // only occur if 5^-q < 2^64. // // For detailed explanations of rounding for negative exponents, see // . For detailed // explanations of rounding for positive exponents, see // . let inside_safe_exponent = (q >= -27) && (q <= 55); if !inside_safe_exponent { return compute_error_scaled::(q, hi, lz); } } let upperbit = (hi >> 63) as i32; let mut mantissa = hi >> (upperbit + 64 - F::MANTISSA_SIZE - 3); let mut power2 = power(q as i32) + upperbit - lz - F::MINIMUM_EXPONENT; if power2 <= 0 { if -power2 + 1 >= 64 { // Have more than 64 bits below the minimum exponent, must be 0. return fp_zero; } // Have a subnormal value. mantissa >>= -power2 + 1; mantissa += mantissa & 1; mantissa >>= 1; power2 = (mantissa >= (1_u64 << F::MANTISSA_SIZE)) as i32; return ExtendedFloat80 { mant: mantissa, exp: power2, }; } // Need to handle rounding ties. Normally, we need to round up, // but if we fall right in between and and we have an even basis, we // need to round down. // // This will only occur if: // 1. The lower 64 bits of the 128-bit representation is 0. // IE, 5^q fits in single 64-bit word. // 2. The least-significant bit prior to truncated mantissa is odd. // 3. All the bits truncated when shifting to mantissa bits + 1 are 0. // // Or, we may fall between two floats: we are exactly halfway. if lo <= 1 && q >= F::MIN_EXPONENT_ROUND_TO_EVEN as i64 && q <= F::MAX_EXPONENT_ROUND_TO_EVEN as i64 && mantissa & 3 == 1 && (mantissa << (upperbit + 64 - F::MANTISSA_SIZE - 3)) == hi { // Zero the lowest bit, so we don't round up. mantissa &= !1_u64; } // Round-to-even, then shift the significant digits into place. mantissa += mantissa & 1; mantissa >>= 1; if mantissa >= (2_u64 << F::MANTISSA_SIZE) { // Rounding up overflowed, so the carry bit is set. Set the // mantissa to 1 (only the implicit, hidden bit is set) and // increase the exponent. mantissa = 1_u64 << F::MANTISSA_SIZE; power2 += 1; } // Zero out the hidden bit. mantissa &= !(1_u64 << F::MANTISSA_SIZE); if power2 >= F::INFINITE_POWER { // Exponent is above largest normal value, must be infinite. return fp_inf; } ExtendedFloat80 { mant: mantissa, exp: power2, } } /// Fallback algorithm to calculate the non-rounded representation. /// This calculates the extended representation, and then normalizes /// the resulting representation, so the high bit is set. #[inline] pub fn compute_error(q: i64, mut w: u64) -> ExtendedFloat80 { let lz = w.leading_zeros() as i32; w <<= lz; let hi = compute_product_approx(q, w, F::MANTISSA_SIZE as usize + 3).1; compute_error_scaled::(q, hi, lz) } /// Compute the error from a mantissa scaled to the exponent. #[inline] pub fn compute_error_scaled(q: i64, mut w: u64, lz: i32) -> ExtendedFloat80 { // Want to normalize the float, but this is faster than ctlz on most architectures. let hilz = (w >> 63) as i32 ^ 1; w <<= hilz; let power2 = power(q as i32) + F::EXPONENT_BIAS - hilz - lz - 62; ExtendedFloat80 { mant: w, exp: power2 + shared::INVALID_FP, } } /// Calculate a base 2 exponent from a decimal exponent. /// This uses a pre-computed integer approximation for /// log2(10), where 217706 / 2^16 is accurate for the /// entire range of non-finite decimal exponents. #[inline] fn power(q: i32) -> i32 { (q.wrapping_mul(152_170 + 65536) >> 16) + 63 } #[inline] fn full_multiplication(a: u64, b: u64) -> (u64, u64) { let r = (a as u128) * (b as u128); (r as u64, (r >> 64) as u64) } // This will compute or rather approximate w * 5**q and return a pair of 64-bit words // approximating the result, with the "high" part corresponding to the most significant // bits and the low part corresponding to the least significant bits. fn compute_product_approx(q: i64, w: u64, precision: usize) -> (u64, u64) { debug_assert!(q >= SMALLEST_POWER_OF_FIVE as i64); debug_assert!(q <= LARGEST_POWER_OF_FIVE as i64); debug_assert!(precision <= 64); let mask = if precision < 64 { 0xFFFF_FFFF_FFFF_FFFF_u64 >> precision } else { 0xFFFF_FFFF_FFFF_FFFF_u64 }; // 5^q < 2^64, then the multiplication always provides an exact value. // That means whenever we need to round ties to even, we always have // an exact value. let index = (q - SMALLEST_POWER_OF_FIVE as i64) as usize; let (lo5, hi5) = POWER_OF_FIVE_128[index]; // Only need one multiplication as long as there is 1 zero but // in the explicit mantissa bits, +1 for the hidden bit, +1 to // determine the rounding direction, +1 for if the computed // product has a leading zero. let (mut first_lo, mut first_hi) = full_multiplication(w, lo5); if first_hi & mask == mask { // Need to do a second multiplication to get better precision // for the lower product. This will always be exact // where q is < 55, since 5^55 < 2^128. If this wraps, // then we need to need to round up the hi product. let (_, second_hi) = full_multiplication(w, hi5); first_lo = first_lo.wrapping_add(second_hi); if second_hi > first_lo { first_hi += 1; } } (first_lo, first_hi) } lexical-parse-float-0.8.5/src/lib.rs000064400000000000000000000121400072674642500154230ustar 00000000000000//! Fast lexical string-to-float conversion routines. //! //! The default implementations are highly optimized both for simple //! strings, as well as input with large numbers of digits. In order to //! keep performance optimal for simple strings, we avoid overly branching //! to minimize the number of branches (and therefore optimization checks). //! Most of the branches in the code are resolved at compile-time, and //! the resulting ASM as well as comprehensive benchmarks are monitored //! to ensure there are no regressions. //! //! For simple floats, we use an optimized digit parser with multiple-digit //! optimizations (parsing 8 digits in 3 multiplication instructions), //! and then use machine floats to create an exact representation with //! high throughput. In more complex cases, we use the Eisel-Lemire //! algorithm, described in "Number Parsing at a Gigabyte per Second", //! available online [here](https://arxiv.org/abs/2101.11408). The //! Eisel-Lemire algorithm creates an extended representation using a //! 128-bit (or a fallback 192-bit representation) of the significant //! digits of the float, scaled to the proper exponent using pre-computed //! powers-of-5. //! //! If the Eisel-Lemire algorithm is unable to unambiguously round the float, //! we fallback to using optimized, big-integer algorithms, which are //! described in [Algorithm Approach](#algorithm-approach) below. //! //! # Features //! //! * `std` - Use the standard library. //! * `power-of-two` - Add support for parsing power-of-two integer strings. //! * `radix` - Add support for strings of any radix. //! * `format` - Add support for parsing custom integer formats. //! * `compact` - Reduce code size at the cost of performance. //! * `safe` - Ensure only memory-safe indexing is used. //! * `nightly` - Enable assembly instructions to control FPU rounding modes. //! //! `safe` has a fairly minimal impact, since all parsers are memory-safe //! by default except where unsafe functionality can trivially be proven //! correct. //! //! # Note //! //! Only documented functionality is considered part of the public API: //! any of the modules, internal functions, or structs may change //! release-to-release without major or minor version changes. Use //! internal implementation details at your own risk. //! //! lexical-parse-float mainly exists as an implementation detail for //! lexical-core, although its API is stable. If you would like to use //! a high-level API that writes to and parses from `String` and `&str`, //! respectively, please look at [lexical](https://crates.io/crates/lexical) //! instead. If you would like an API that supports multiple numeric //! conversions, please look at [lexical-core](https://crates.io/crates/lexical-core) //! instead. //! //! # Machine Float-Only Algorithm //! //! We also support an algorithm that uses only machine floats for the //! fast-path algorithm, however, this may be slower for floats with large //! exponents since it uses an iterative algorithm. A code sample //! using this is: //! //! ```rust //! use lexical_parse_float::Options; //! use lexical_parse_float::format::STANDARD; //! use lexical_parse_float::parse::ParseFloat; //! //! let options = Options::new(); //! let result = f64::fast_path_complete::<{ STANDARD }>(b"1.34000", &options); //! assert_eq!(result, Ok(1.34000)); //! ``` //! //! # Version Support //! //! The minimum, standard, required version is 1.51.0, for const generic //! support. Older versions of lexical support older Rust versions. //! //! # Design //! //! - [Algorithm Approach](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Algorithm.md) //! - [Benchmarks](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Benchmarks.md) //! - [Big Integer Implementation](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/BigInteger.md) // Inline ASM was stabilized in 1.59.0. // FIXME: Remove when the MSRV for Rustc >= 1.59.0. #![allow(stable_features)] // We want to have the same safety guarantees as Rust core, // so we allow unused unsafe to clearly document safety guarantees. #![allow(unused_unsafe)] #![cfg_attr(feature = "lint", warn(unsafe_op_in_unsafe_fn))] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(feature = "nightly", feature(asm))] #[macro_use] mod index; #[macro_use] pub mod shared; pub mod bellerophon; pub mod bigint; pub mod binary; pub mod float; pub mod fpu; pub mod lemire; pub mod libm; pub mod limits; pub mod mask; pub mod number; pub mod options; pub mod parse; pub mod slow; pub mod table; mod api; mod table_bellerophon_decimal; mod table_bellerophon_radix; mod table_binary; mod table_decimal; mod table_large; mod table_lemire; mod table_radix; mod table_small; // Re-exports pub use self::api::{FromLexical, FromLexicalWithOptions}; #[doc(inline)] pub use self::options::{Options, OptionsBuilder}; #[cfg(feature = "f16")] pub use lexical_util::bf16::bf16; pub use lexical_util::error::Error; #[cfg(feature = "f16")] pub use lexical_util::f16::f16; pub use lexical_util::format::{self, NumberFormatBuilder}; pub use lexical_util::options::ParseOptions; pub use lexical_util::result::Result; lexical-parse-float-0.8.5/src/libm.rs000064400000000000000000001134220072674642500156050ustar 00000000000000//! A small number of math routines for floats and doubles. //! //! These are adapted from libm, a port of musl libc's libm to Rust. //! libm can be found online [here](https://github.com/rust-lang/libm), //! and is similarly licensed under an Apache2.0/MIT license #![cfg(all(not(feature = "std"), feature = "compact"))] #![doc(hidden)] /* origin: FreeBSD /usr/src/lib/msun/src/e_powf.c */ /* * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /// # Safety /// /// Safe if `index < array.len()`. macro_rules! i { ($array:ident, $index:expr) => { // SAFETY: safe if `index < array.len()`. unsafe { index_unchecked!($array[$index]) } }; } pub fn powf(x: f32, y: f32) -> f32 { const BP: [f32; 2] = [1.0, 1.5]; const DP_H: [f32; 2] = [0.0, 5.84960938e-01]; /* 0x3f15c000 */ const DP_L: [f32; 2] = [0.0, 1.56322085e-06]; /* 0x35d1cfdc */ const TWO24: f32 = 16777216.0; /* 0x4b800000 */ const HUGE: f32 = 1.0e30; const TINY: f32 = 1.0e-30; const L1: f32 = 6.0000002384e-01; /* 0x3f19999a */ const L2: f32 = 4.2857143283e-01; /* 0x3edb6db7 */ const L3: f32 = 3.3333334327e-01; /* 0x3eaaaaab */ const L4: f32 = 2.7272811532e-01; /* 0x3e8ba305 */ const L5: f32 = 2.3066075146e-01; /* 0x3e6c3255 */ const L6: f32 = 2.0697501302e-01; /* 0x3e53f142 */ const P1: f32 = 1.6666667163e-01; /* 0x3e2aaaab */ const P2: f32 = -2.7777778450e-03; /* 0xbb360b61 */ const P3: f32 = 6.6137559770e-05; /* 0x388ab355 */ const P4: f32 = -1.6533901999e-06; /* 0xb5ddea0e */ const P5: f32 = 4.1381369442e-08; /* 0x3331bb4c */ const LG2: f32 = 6.9314718246e-01; /* 0x3f317218 */ const LG2_H: f32 = 6.93145752e-01; /* 0x3f317200 */ const LG2_L: f32 = 1.42860654e-06; /* 0x35bfbe8c */ const OVT: f32 = 4.2995665694e-08; /* -(128-log2(ovfl+.5ulp)) */ const CP: f32 = 9.6179670095e-01; /* 0x3f76384f =2/(3ln2) */ const CP_H: f32 = 9.6191406250e-01; /* 0x3f764000 =12b cp */ const CP_L: f32 = -1.1736857402e-04; /* 0xb8f623c6 =tail of cp_h */ const IVLN2: f32 = 1.4426950216e+00; const IVLN2_H: f32 = 1.4426879883e+00; const IVLN2_L: f32 = 7.0526075433e-06; let mut z: f32; let mut ax: f32; let z_h: f32; let z_l: f32; let mut p_h: f32; let mut p_l: f32; let y1: f32; let mut t1: f32; let t2: f32; let mut r: f32; let s: f32; let mut sn: f32; let mut t: f32; let mut u: f32; let mut v: f32; let mut w: f32; let i: i32; let mut j: i32; let mut k: i32; let mut yisint: i32; let mut n: i32; let hx: i32; let hy: i32; let mut ix: i32; let iy: i32; let mut is: i32; hx = x.to_bits() as i32; hy = y.to_bits() as i32; ix = hx & 0x7fffffff; iy = hy & 0x7fffffff; /* x**0 = 1, even if x is NaN */ if iy == 0 { return 1.0; } /* 1**y = 1, even if y is NaN */ if hx == 0x3f800000 { return 1.0; } /* NaN if either arg is NaN */ if ix > 0x7f800000 || iy > 0x7f800000 { return x + y; } /* determine if y is an odd int when x < 0 * yisint = 0 ... y is not an integer * yisint = 1 ... y is an odd int * yisint = 2 ... y is an even int */ yisint = 0; if hx < 0 { if iy >= 0x4b800000 { yisint = 2; /* even integer y */ } else if iy >= 0x3f800000 { k = (iy >> 23) - 0x7f; /* exponent */ j = iy >> (23 - k); if (j << (23 - k)) == iy { yisint = 2 - (j & 1); } } } /* special value of y */ if iy == 0x7f800000 { /* y is +-inf */ if ix == 0x3f800000 { /* (-1)**+-inf is 1 */ return 1.0; } else if ix > 0x3f800000 { /* (|x|>1)**+-inf = inf,0 */ return if hy >= 0 { y } else { 0.0 }; } else { /* (|x|<1)**+-inf = 0,inf */ return if hy >= 0 { 0.0 } else { -y }; } } if iy == 0x3f800000 { /* y is +-1 */ return if hy >= 0 { x } else { 1.0 / x }; } if hy == 0x40000000 { /* y is 2 */ return x * x; } if hy == 0x3f000000 /* y is 0.5 */ && hx >= 0 { /* x >= +0 */ return sqrtf(x); } ax = fabsf(x); /* special value of x */ if ix == 0x7f800000 || ix == 0 || ix == 0x3f800000 { /* x is +-0,+-inf,+-1 */ z = ax; if hy < 0 { /* z = (1/|x|) */ z = 1.0 / z; } if hx < 0 { if ((ix - 0x3f800000) | yisint) == 0 { z = (z - z) / (z - z); /* (-1)**non-int is NaN */ } else if yisint == 1 { z = -z; /* (x<0)**odd = -(|x|**odd) */ } } return z; } sn = 1.0; /* sign of result */ if hx < 0 { if yisint == 0 { /* (x<0)**(non-int) is NaN */ return (x - x) / (x - x); } if yisint == 1 { /* (x<0)**(odd int) */ sn = -1.0; } } /* |y| is HUGE */ if iy > 0x4d000000 { /* if |y| > 2**27 */ /* over/underflow if x is not close to one */ if ix < 0x3f7ffff8 { return if hy < 0 { sn * HUGE * HUGE } else { sn * TINY * TINY }; } if ix > 0x3f800007 { return if hy > 0 { sn * HUGE * HUGE } else { sn * TINY * TINY }; } /* now |1-x| is TINY <= 2**-20, suffice to compute log(x) by x-x^2/2+x^3/3-x^4/4 */ t = ax - 1.; /* t has 20 trailing zeros */ w = (t * t) * (0.5 - t * (0.333333333333 - t * 0.25)); u = IVLN2_H * t; /* IVLN2_H has 16 sig. bits */ v = t * IVLN2_L - w * IVLN2; t1 = u + v; is = t1.to_bits() as i32; t1 = f32::from_bits(is as u32 & 0xfffff000); t2 = v - (t1 - u); } else { let mut s2: f32; let mut s_h: f32; let s_l: f32; let mut t_h: f32; let mut t_l: f32; n = 0; /* take care subnormal number */ if ix < 0x00800000 { ax *= TWO24; n -= 24; ix = ax.to_bits() as i32; } n += ((ix) >> 23) - 0x7f; j = ix & 0x007fffff; /* determine interval */ ix = j | 0x3f800000; /* normalize ix */ if j <= 0x1cc471 { /* |x|> 1) & 0xfffff000) | 0x20000000) as i32; t_h = f32::from_bits(is as u32 + 0x00400000 + ((k as u32) << 21)); t_l = ax - (t_h - i!(BP, k as usize)); s_l = v * ((u - s_h * t_h) - s_h * t_l); /* compute log(ax) */ s2 = s * s; r = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6))))); r += s_l * (s_h + s); s2 = s_h * s_h; t_h = 3.0 + s2 + r; is = t_h.to_bits() as i32; t_h = f32::from_bits(is as u32 & 0xfffff000); t_l = r - ((t_h - 3.0) - s2); /* u+v = s*(1+...) */ u = s_h * t_h; v = s_l * t_h + t_l * s; /* 2/(3log2)*(s+...) */ p_h = u + v; is = p_h.to_bits() as i32; p_h = f32::from_bits(is as u32 & 0xfffff000); p_l = v - (p_h - u); z_h = CP_H * p_h; /* cp_h+cp_l = 2/(3*log2) */ z_l = CP_L * p_h + p_l * CP + i!(DP_L, k as usize); /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ t = n as f32; t1 = ((z_h + z_l) + i!(DP_H, k as usize)) + t; is = t1.to_bits() as i32; t1 = f32::from_bits(is as u32 & 0xfffff000); t2 = z_l - (((t1 - t) - i!(DP_H, k as usize)) - z_h); }; /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ is = y.to_bits() as i32; y1 = f32::from_bits(is as u32 & 0xfffff000); p_l = (y - y1) * t1 + y * t2; p_h = y1 * t1; z = p_l + p_h; j = z.to_bits() as i32; if j > 0x43000000 { /* if z > 128 */ return sn * HUGE * HUGE; /* overflow */ } else if j == 0x43000000 { /* if z == 128 */ if p_l + OVT > z - p_h { return sn * HUGE * HUGE; /* overflow */ } } else if (j & 0x7fffffff) > 0x43160000 { /* z < -150 */ // FIXME: check should be (uint32_t)j > 0xc3160000 return sn * TINY * TINY; /* underflow */ } else if j as u32 == 0xc3160000 /* z == -150 */ && p_l <= z - p_h { return sn * TINY * TINY; /* underflow */ } /* * compute 2**(p_h+p_l) */ i = j & 0x7fffffff; k = (i >> 23) - 0x7f; n = 0; if i > 0x3f000000 { /* if |z| > 0.5, set n = [z+0.5] */ n = j + (0x00800000 >> (k + 1)); k = ((n & 0x7fffffff) >> 23) - 0x7f; /* new k for n */ t = f32::from_bits(n as u32 & !(0x007fffff >> k)); n = ((n & 0x007fffff) | 0x00800000) >> (23 - k); if j < 0 { n = -n; } p_h -= t; } t = p_l + p_h; is = t.to_bits() as i32; t = f32::from_bits(is as u32 & 0xffff8000); u = t * LG2_H; v = (p_l - (t - p_h)) * LG2 + t * LG2_L; z = u + v; w = v - (z - u); t = z * z; t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); r = (z * t1) / (t1 - 2.0) - (w + z * w); z = 1.0 - (r - z); j = z.to_bits() as i32; j += n << 23; if (j >> 23) <= 0 { /* subnormal output */ z = scalbnf(z, n); } else { z = f32::from_bits(j as u32); } sn * z } /* origin: FreeBSD /usr/src/lib/msun/src/e_sqrtf.c */ /* * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ pub fn sqrtf(x: f32) -> f32 { #[cfg(target_feature = "sse")] { // Note: This path is unlikely since LLVM will usually have already // optimized sqrt calls into hardware instructions if sse is available, // but if someone does end up here they'll apprected the speed increase. #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; // SAFETY: safe, since `_mm_set_ss` takes a 32-bit float, and returns // a 128-bit type with the lowest 32-bits as `x`, `_mm_sqrt_ss` calculates // the sqrt of this 128-bit vector, and `_mm_cvtss_f32` extracts the lower // 32-bits as a 32-bit float. unsafe { let m = _mm_set_ss(x); let m_sqrt = _mm_sqrt_ss(m); _mm_cvtss_f32(m_sqrt) } } #[cfg(not(target_feature = "sse"))] { const TINY: f32 = 1.0e-30; let mut z: f32; let sign: i32 = 0x80000000u32 as i32; let mut ix: i32; let mut s: i32; let mut q: i32; let mut m: i32; let mut t: i32; let mut i: i32; let mut r: u32; ix = x.to_bits() as i32; /* take care of Inf and NaN */ if (ix as u32 & 0x7f800000) == 0x7f800000 { return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ } /* take care of zero */ if ix <= 0 { if (ix & !sign) == 0 { return x; /* sqrt(+-0) = +-0 */ } if ix < 0 { return (x - x) / (x - x); /* sqrt(-ve) = sNaN */ } } /* normalize x */ m = ix >> 23; if m == 0 { /* subnormal x */ i = 0; while ix & 0x00800000 == 0 { ix <<= 1; i = i + 1; } m -= i - 1; } m -= 127; /* unbias exponent */ ix = (ix & 0x007fffff) | 0x00800000; if m & 1 == 1 { /* odd m, double x to make it even */ ix += ix; } m >>= 1; /* m = [m/2] */ /* generate sqrt(x) bit by bit */ ix += ix; q = 0; s = 0; r = 0x01000000; /* r = moving bit from right to left */ while r != 0 { t = s + r as i32; if t <= ix { s = t + r as i32; ix -= t; q += r as i32; } ix += ix; r >>= 1; } /* use floating add to find out rounding direction */ if ix != 0 { z = 1.0 - TINY; /* raise inexact flag */ if z >= 1.0 { z = 1.0 + TINY; if z > 1.0 { q += 2; } else { q += q & 1; } } } ix = (q >> 1) + 0x3f000000; ix += m << 23; f32::from_bits(ix as u32) } } /// Absolute value (magnitude) (f32) /// Calculates the absolute value (magnitude) of the argument `x`, /// by direct manipulation of the bit representation of `x`. pub fn fabsf(x: f32) -> f32 { f32::from_bits(x.to_bits() & 0x7fffffff) } pub fn scalbnf(mut x: f32, mut n: i32) -> f32 { let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 127 let x1p_126 = f32::from_bits(0x800000); // 0x1p-126f === 2 ^ -126 let x1p24 = f32::from_bits(0x4b800000); // 0x1p24f === 2 ^ 24 if n > 127 { x *= x1p127; n -= 127; if n > 127 { x *= x1p127; n -= 127; if n > 127 { n = 127; } } } else if n < -126 { x *= x1p_126 * x1p24; n += 126 - 24; if n < -126 { x *= x1p_126 * x1p24; n += 126 - 24; if n < -126 { n = -126; } } } x * f32::from_bits(((0x7f + n) as u32) << 23) } /* origin: FreeBSD /usr/src/lib/msun/src/e_pow.c */ /* * ==================================================== * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. * * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ // pow(x,y) return x**y // // n // Method: Let x = 2 * (1+f) // 1. Compute and return log2(x) in two pieces: // log2(x) = w1 + w2, // where w1 has 53-24 = 29 bit trailing zeros. // 2. Perform y*log2(x) = n+y' by simulating muti-precision // arithmetic, where |y'|<=0.5. // 3. Return x**y = 2**n*exp(y'*log2) // // Special cases: // 1. (anything) ** 0 is 1 // 2. 1 ** (anything) is 1 // 3. (anything except 1) ** NAN is NAN // 4. NAN ** (anything except 0) is NAN // 5. +-(|x| > 1) ** +INF is +INF // 6. +-(|x| > 1) ** -INF is +0 // 7. +-(|x| < 1) ** +INF is +0 // 8. +-(|x| < 1) ** -INF is +INF // 9. -1 ** +-INF is 1 // 10. +0 ** (+anything except 0, NAN) is +0 // 11. -0 ** (+anything except 0, NAN, odd integer) is +0 // 12. +0 ** (-anything except 0, NAN) is +INF, raise divbyzero // 13. -0 ** (-anything except 0, NAN, odd integer) is +INF, raise divbyzero // 14. -0 ** (+odd integer) is -0 // 15. -0 ** (-odd integer) is -INF, raise divbyzero // 16. +INF ** (+anything except 0,NAN) is +INF // 17. +INF ** (-anything except 0,NAN) is +0 // 18. -INF ** (+odd integer) is -INF // 19. -INF ** (anything) = -0 ** (-anything), (anything except odd integer) // 20. (anything) ** 1 is (anything) // 21. (anything) ** -1 is 1/(anything) // 22. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) // 23. (-anything except 0 and inf) ** (non-integer) is NAN // // Accuracy: // pow(x,y) returns x**y nearly rounded. In particular // pow(integer,integer) // always returns the correct integer provided it is // representable. // // Constants : // The hexadecimal values are the intended ones for the following // constants. The decimal values may be used, provided that the // compiler will convert from decimal to binary accurately enough // to produce the hexadecimal values shown. pub fn powd(x: f64, y: f64) -> f64 { const BP: [f64; 2] = [1.0, 1.5]; const DP_H: [f64; 2] = [0.0, 5.84962487220764160156e-01]; /* 0x3fe2b803_40000000 */ const DP_L: [f64; 2] = [0.0, 1.35003920212974897128e-08]; /* 0x3E4CFDEB, 0x43CFD006 */ const TWO53: f64 = 9007199254740992.0; /* 0x43400000_00000000 */ const HUGE: f64 = 1.0e300; const TINY: f64 = 1.0e-300; // poly coefs for (3/2)*(log(x)-2s-2/3*s**3: const L1: f64 = 5.99999999999994648725e-01; /* 0x3fe33333_33333303 */ const L2: f64 = 4.28571428578550184252e-01; /* 0x3fdb6db6_db6fabff */ const L3: f64 = 3.33333329818377432918e-01; /* 0x3fd55555_518f264d */ const L4: f64 = 2.72728123808534006489e-01; /* 0x3fd17460_a91d4101 */ const L5: f64 = 2.30660745775561754067e-01; /* 0x3fcd864a_93c9db65 */ const L6: f64 = 2.06975017800338417784e-01; /* 0x3fca7e28_4a454eef */ const P1: f64 = 1.66666666666666019037e-01; /* 0x3fc55555_5555553e */ const P2: f64 = -2.77777777770155933842e-03; /* 0xbf66c16c_16bebd93 */ const P3: f64 = 6.61375632143793436117e-05; /* 0x3f11566a_af25de2c */ const P4: f64 = -1.65339022054652515390e-06; /* 0xbebbbd41_c5d26bf1 */ const P5: f64 = 4.13813679705723846039e-08; /* 0x3e663769_72bea4d0 */ const LG2: f64 = 6.93147180559945286227e-01; /* 0x3fe62e42_fefa39ef */ const LG2_H: f64 = 6.93147182464599609375e-01; /* 0x3fe62e43_00000000 */ const LG2_L: f64 = -1.90465429995776804525e-09; /* 0xbe205c61_0ca86c39 */ const OVT: f64 = 8.0085662595372944372e-017; /* -(1024-log2(ovfl+.5ulp)) */ const CP: f64 = 9.61796693925975554329e-01; /* 0x3feec709_dc3a03fd =2/(3ln2) */ const CP_H: f64 = 9.61796700954437255859e-01; /* 0x3feec709_e0000000 =(float)cp */ const CP_L: f64 = -7.02846165095275826516e-09; /* 0xbe3e2fe0_145b01f5 =tail of cp_h*/ const IVLN2: f64 = 1.44269504088896338700e+00; /* 0x3ff71547_652b82fe =1/ln2 */ const IVLN2_H: f64 = 1.44269502162933349609e+00; /* 0x3ff71547_60000000 =24b 1/ln2*/ const IVLN2_L: f64 = 1.92596299112661746887e-08; /* 0x3e54ae0b_f85ddf44 =1/ln2 tail*/ let t1: f64; let t2: f64; let (hx, lx): (i32, u32) = ((x.to_bits() >> 32) as i32, x.to_bits() as u32); let (hy, ly): (i32, u32) = ((y.to_bits() >> 32) as i32, y.to_bits() as u32); let mut ix: i32 = (hx & 0x7fffffff) as i32; let iy: i32 = (hy & 0x7fffffff) as i32; /* x**0 = 1, even if x is NaN */ if ((iy as u32) | ly) == 0 { return 1.0; } /* 1**y = 1, even if y is NaN */ if hx == 0x3ff00000 && lx == 0 { return 1.0; } /* NaN if either arg is NaN */ if ix > 0x7ff00000 || (ix == 0x7ff00000 && lx != 0) || iy > 0x7ff00000 || (iy == 0x7ff00000 && ly != 0) { return x + y; } /* determine if y is an odd int when x < 0 * yisint = 0 ... y is not an integer * yisint = 1 ... y is an odd int * yisint = 2 ... y is an even int */ let mut yisint: i32 = 0; let mut k: i32; let mut j: i32; if hx < 0 { if iy >= 0x43400000 { yisint = 2; /* even integer y */ } else if iy >= 0x3ff00000 { k = (iy >> 20) - 0x3ff; /* exponent */ if k > 20 { j = (ly >> (52 - k)) as i32; if (j << (52 - k)) == (ly as i32) { yisint = 2 - (j & 1); } } else if ly == 0 { j = iy >> (20 - k); if (j << (20 - k)) == iy { yisint = 2 - (j & 1); } } } } if ly == 0 { /* special value of y */ if iy == 0x7ff00000 { /* y is +-inf */ return if ((ix - 0x3ff00000) | (lx as i32)) == 0 { /* (-1)**+-inf is 1 */ 1.0 } else if ix >= 0x3ff00000 { /* (|x|>1)**+-inf = inf,0 */ if hy >= 0 { y } else { 0.0 } } else { /* (|x|<1)**+-inf = 0,inf */ if hy >= 0 { 0.0 } else { -y } }; } if iy == 0x3ff00000 { /* y is +-1 */ return if hy >= 0 { x } else { 1.0 / x }; } if hy == 0x40000000 { /* y is 2 */ return x * x; } if hy == 0x3fe00000 { /* y is 0.5 */ if hx >= 0 { /* x >= +0 */ return sqrtd(x); } } } let mut ax: f64 = fabsd(x); if lx == 0 { /* special value of x */ if ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000 { /* x is +-0,+-inf,+-1 */ let mut z: f64 = ax; if hy < 0 { /* z = (1/|x|) */ z = 1.0 / z; } if hx < 0 { if ((ix - 0x3ff00000) | yisint) == 0 { z = (z - z) / (z - z); /* (-1)**non-int is NaN */ } else if yisint == 1 { z = -z; /* (x<0)**odd = -(|x|**odd) */ } } return z; } } let mut s: f64 = 1.0; /* sign of result */ if hx < 0 { if yisint == 0 { /* (x<0)**(non-int) is NaN */ return (x - x) / (x - x); } if yisint == 1 { /* (x<0)**(odd int) */ s = -1.0; } } /* |y| is HUGE */ if iy > 0x41e00000 { /* if |y| > 2**31 */ if iy > 0x43f00000 { /* if |y| > 2**64, must o/uflow */ if ix <= 0x3fefffff { return if hy < 0 { HUGE * HUGE } else { TINY * TINY }; } if ix >= 0x3ff00000 { return if hy > 0 { HUGE * HUGE } else { TINY * TINY }; } } /* over/underflow if x is not close to one */ if ix < 0x3fefffff { return if hy < 0 { s * HUGE * HUGE } else { s * TINY * TINY }; } if ix > 0x3ff00000 { return if hy > 0 { s * HUGE * HUGE } else { s * TINY * TINY }; } /* now |1-x| is TINY <= 2**-20, suffice to compute log(x) by x-x^2/2+x^3/3-x^4/4 */ let t: f64 = ax - 1.0; /* t has 20 trailing zeros */ let w: f64 = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25)); let u: f64 = IVLN2_H * t; /* ivln2_h has 21 sig. bits */ let v: f64 = t * IVLN2_L - w * IVLN2; t1 = with_set_low_word(u + v, 0); t2 = v - (t1 - u); } else { // double ss,s2,s_h,s_l,t_h,t_l; let mut n: i32 = 0; if ix < 0x00100000 { /* take care subnormal number */ ax *= TWO53; n -= 53; ix = get_high_word(ax) as i32; } n += (ix >> 20) - 0x3ff; j = ix & 0x000fffff; /* determine interval */ let k: i32; ix = j | 0x3ff00000; /* normalize ix */ if j <= 0x3988E { /* |x|> 1) | 0x20000000) + 0x00080000 + ((k as u32) << 18), ); let t_l: f64 = ax - (t_h - i!(BP, k as usize)); let s_l: f64 = v * ((u - s_h * t_h) - s_h * t_l); /* compute log(ax) */ let s2: f64 = ss * ss; let mut r: f64 = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6))))); r += s_l * (s_h + ss); let s2: f64 = s_h * s_h; let t_h: f64 = with_set_low_word(3.0 + s2 + r, 0); let t_l: f64 = r - ((t_h - 3.0) - s2); /* u+v = ss*(1+...) */ let u: f64 = s_h * t_h; let v: f64 = s_l * t_h + t_l * ss; /* 2/(3log2)*(ss+...) */ let p_h: f64 = with_set_low_word(u + v, 0); let p_l = v - (p_h - u); let z_h: f64 = CP_H * p_h; /* cp_h+cp_l = 2/(3*log2) */ let z_l: f64 = CP_L * p_h + p_l * CP + i!(DP_L, k as usize); /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ let t: f64 = n as f64; t1 = with_set_low_word(((z_h + z_l) + i!(DP_H, k as usize)) + t, 0); t2 = z_l - (((t1 - t) - i!(DP_H, k as usize)) - z_h); } /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ let y1: f64 = with_set_low_word(y, 0); let p_l: f64 = (y - y1) * t1 + y * t2; let mut p_h: f64 = y1 * t1; let z: f64 = p_l + p_h; let mut j: i32 = (z.to_bits() >> 32) as i32; let i: i32 = z.to_bits() as i32; // let (j, i): (i32, i32) = ((z.to_bits() >> 32) as i32, z.to_bits() as i32); if j >= 0x40900000 { /* z >= 1024 */ if (j - 0x40900000) | i != 0 { /* if z > 1024 */ return s * HUGE * HUGE; /* overflow */ } if p_l + OVT > z - p_h { return s * HUGE * HUGE; /* overflow */ } } else if (j & 0x7fffffff) >= 0x4090cc00 { /* z <= -1075 */ // FIXME: instead of abs(j) use unsigned j if (((j as u32) - 0xc090cc00) | (i as u32)) != 0 { /* z < -1075 */ return s * TINY * TINY; /* underflow */ } if p_l <= z - p_h { return s * TINY * TINY; /* underflow */ } } /* compute 2**(p_h+p_l) */ let i: i32 = j & (0x7fffffff as i32); k = (i >> 20) - 0x3ff; let mut n: i32 = 0; if i > 0x3fe00000 { /* if |z| > 0.5, set n = [z+0.5] */ n = j + (0x00100000 >> (k + 1)); k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */ let t: f64 = with_set_high_word(0.0, (n & !(0x000fffff >> k)) as u32); n = ((n & 0x000fffff) | 0x00100000) >> (20 - k); if j < 0 { n = -n; } p_h -= t; } let t: f64 = with_set_low_word(p_l + p_h, 0); let u: f64 = t * LG2_H; let v: f64 = (p_l - (t - p_h)) * LG2 + t * LG2_L; let mut z: f64 = u + v; let w: f64 = v - (z - u); let t: f64 = z * z; let t1: f64 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); let r: f64 = (z * t1) / (t1 - 2.0) - (w + z * w); z = 1.0 - (r - z); j = get_high_word(z) as i32; j += n << 20; if (j >> 20) <= 0 { /* subnormal output */ z = scalbnd(z, n); } else { z = with_set_high_word(z, j as u32); } s * z } /// Absolute value (magnitude) (f64) /// Calculates the absolute value (magnitude) of the argument `x`, /// by direct manipulation of the bit representation of `x`. pub fn fabsd(x: f64) -> f64 { f64::from_bits(x.to_bits() & (u64::MAX / 2)) } pub fn scalbnd(x: f64, mut n: i32) -> f64 { let x1p1023 = f64::from_bits(0x7fe0000000000000); // 0x1p1023 === 2 ^ 1023 let x1p53 = f64::from_bits(0x4340000000000000); // 0x1p53 === 2 ^ 53 let x1p_1022 = f64::from_bits(0x0010000000000000); // 0x1p-1022 === 2 ^ (-1022) let mut y = x; if n > 1023 { y *= x1p1023; n -= 1023; if n > 1023 { y *= x1p1023; n -= 1023; if n > 1023 { n = 1023; } } } else if n < -1022 { /* make sure final n < -53 to avoid double rounding in the subnormal range */ y *= x1p_1022 * x1p53; n += 1022 - 53; if n < -1022 { y *= x1p_1022 * x1p53; n += 1022 - 53; if n < -1022 { n = -1022; } } } y * f64::from_bits(((0x3ff + n) as u64) << 52) } /* origin: FreeBSD /usr/src/lib/msun/src/e_sqrt.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunSoft, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* sqrt(x) * Return correctly rounded sqrt. * ------------------------------------------ * | Use the hardware sqrt if you have one | * ------------------------------------------ * Method: * Bit by bit method using integer arithmetic. (Slow, but portable) * 1. Normalization * Scale x to y in [1,4) with even powers of 2: * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then * sqrt(x) = 2^k * sqrt(y) * 2. Bit by bit computation * Let q = sqrt(y) truncated to i bit after binary point (q = 1), * i 0 * i+1 2 * s = 2*q , and y = 2 * ( y - q ). (1) * i i i i * * To compute q from q , one checks whether * i+1 i * * -(i+1) 2 * (q + 2 ) <= y. (2) * i * -(i+1) * If (2) is false, then q = q ; otherwise q = q + 2 . * i+1 i i+1 i * * With some algebraic manipulation, it is not difficult to see * that (2) is equivalent to * -(i+1) * s + 2 <= y (3) * i i * * The advantage of (3) is that s and y can be computed by * i i * the following recurrence formula: * if (3) is false * * s = s , y = y ; (4) * i+1 i i+1 i * * otherwise, * -i -(i+1) * s = s + 2 , y = y - s - 2 (5) * i+1 i i+1 i i * * One may easily use induction to prove (4) and (5). * Note. Since the left hand side of (3) contain only i+2 bits, * it does not necessary to do a full (53-bit) comparison * in (3). * 3. Final rounding * After generating the 53 bits result, we compute one more bit. * Together with the remainder, we can decide whether the * result is exact, bigger than 1/2ulp, or less than 1/2ulp * (it will never equal to 1/2ulp). * The rounding mode can be detected by checking whether * huge + tiny is equal to huge, and whether huge - tiny is * equal to huge for some floating point number "huge" and "tiny". * * Special cases: * sqrt(+-0) = +-0 ... exact * sqrt(inf) = inf * sqrt(-ve) = NaN ... with invalid signal * sqrt(NaN) = NaN ... with invalid signal for signaling NaN */ pub fn sqrtd(x: f64) -> f64 { #[cfg(target_feature = "sse2")] { // Note: This path is unlikely since LLVM will usually have already // optimized sqrt calls into hardware instructions if sse2 is available, // but if someone does end up here they'll apprected the speed increase. #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; // SAFETY: safe, since `_mm_set_sd` takes a 64-bit float, and returns // a 128-bit type with the lowest 64-bits as `x`, `_mm_sqrt_ss` calculates // the sqrt of this 128-bit vector, and `_mm_cvtss_f64` extracts the lower // 64-bits as a 64-bit float. unsafe { let m = _mm_set_sd(x); let m_sqrt = _mm_sqrt_pd(m); _mm_cvtsd_f64(m_sqrt) } } #[cfg(not(target_feature = "sse2"))] { use core::num::Wrapping; const TINY: f64 = 1.0e-300; let mut z: f64; let sign: Wrapping = Wrapping(0x80000000); let mut ix0: i32; let mut s0: i32; let mut q: i32; let mut m: i32; let mut t: i32; let mut i: i32; let mut r: Wrapping; let mut t1: Wrapping; let mut s1: Wrapping; let mut ix1: Wrapping; let mut q1: Wrapping; ix0 = (x.to_bits() >> 32) as i32; ix1 = Wrapping(x.to_bits() as u32); /* take care of Inf and NaN */ if (ix0 & 0x7ff00000) == 0x7ff00000 { return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ } /* take care of zero */ if ix0 <= 0 { if ((ix0 & !(sign.0 as i32)) | ix1.0 as i32) == 0 { return x; /* sqrt(+-0) = +-0 */ } if ix0 < 0 { return (x - x) / (x - x); /* sqrt(-ve) = sNaN */ } } /* normalize x */ m = ix0 >> 20; if m == 0 { /* subnormal x */ while ix0 == 0 { m -= 21; ix0 |= (ix1 >> 11).0 as i32; ix1 <<= 21; } i = 0; while (ix0 & 0x00100000) == 0 { i += 1; ix0 <<= 1; } m -= i - 1; ix0 |= (ix1 >> (32 - i) as usize).0 as i32; ix1 = ix1 << i as usize; } m -= 1023; /* unbias exponent */ ix0 = (ix0 & 0x000fffff) | 0x00100000; if (m & 1) == 1 { /* odd m, double x to make it even */ ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32; ix1 += ix1; } m >>= 1; /* m = [m/2] */ /* generate sqrt(x) bit by bit */ ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32; ix1 += ix1; q = 0; /* [q,q1] = sqrt(x) */ q1 = Wrapping(0); s0 = 0; s1 = Wrapping(0); r = Wrapping(0x00200000); /* r = moving bit from right to left */ while r != Wrapping(0) { t = s0 + r.0 as i32; if t <= ix0 { s0 = t + r.0 as i32; ix0 -= t; q += r.0 as i32; } ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32; ix1 += ix1; r >>= 1; } r = sign; while r != Wrapping(0) { t1 = s1 + r; t = s0; if t < ix0 || (t == ix0 && t1 <= ix1) { s1 = t1 + r; if (t1 & sign) == sign && (s1 & sign) == Wrapping(0) { s0 += 1; } ix0 -= t; if ix1 < t1 { ix0 -= 1; } ix1 -= t1; q1 += r; } ix0 += ix0 + ((ix1 & sign) >> 31).0 as i32; ix1 += ix1; r >>= 1; } /* use floating add to find out rounding direction */ if (ix0 as u32 | ix1.0) != 0 { z = 1.0 - TINY; /* raise inexact flag */ if z >= 1.0 { z = 1.0 + TINY; if q1.0 == 0xffffffff { q1 = Wrapping(0); q += 1; } else if z > 1.0 { if q1.0 == 0xfffffffe { q += 1; } q1 += Wrapping(2); } else { q1 += q1 & Wrapping(1); } } } ix0 = (q >> 1) + 0x3fe00000; ix1 = q1 >> 1; if (q & 1) == 1 { ix1 |= sign; } ix0 += m << 20; f64::from_bits((ix0 as u64) << 32 | ix1.0 as u64) } } #[inline] fn get_high_word(x: f64) -> u32 { (x.to_bits() >> 32) as u32 } #[inline] fn with_set_high_word(f: f64, hi: u32) -> f64 { let mut tmp = f.to_bits(); tmp &= 0x00000000_ffffffff; tmp |= (hi as u64) << 32; f64::from_bits(tmp) } #[inline] fn with_set_low_word(f: f64, lo: u32) -> f64 { let mut tmp = f.to_bits(); tmp &= 0xffffffff_00000000; tmp |= lo as u64; f64::from_bits(tmp) } lexical-parse-float-0.8.5/src/limits.rs000064400000000000000000000610360072674642500161660ustar 00000000000000//! Determine the limits of exact exponent and mantissas for floats. #![doc(hidden)] use lexical_util::assert::debug_assert_radix; #[cfg(feature = "f16")] use lexical_util::bf16::bf16; #[cfg(feature = "f16")] use lexical_util::f16::f16; // EXACT EXPONENT // -------------- // Calculating the exponent limit requires determining the largest exponent // we can calculate for a radix that can be **exactly** store in the // float type. If the value is a power-of-two, then we simply // need to scale the minimum, denormal exp and maximum exp to the type // size. Otherwise, we need to calculate the number of digits // that can fit into the type's precision, after removing a power-of-two // (since these values can be represented exactly). // // The mantissa limit is the number of digits we can remove from // the exponent into the mantissa, and is therefore is the // `⌊ precision / log2(radix) ⌋`, where precision does not include // the hidden bit. // // The algorithm for calculating both `exponent_limit` and `mantissa_limit`, // in Python, can be done as follows: // // DO NOT MODIFY: Generated by `src/etc/limits.py` // EXACT FLOAT // ----------- /// Get exact exponent limit for radix. #[doc(hidden)] pub trait ExactFloat { /// Get min and max exponent limits (exact) from radix. fn exponent_limit(radix: u32) -> (i64, i64); /// Get the number of digits that can be shifted from exponent to mantissa. fn mantissa_limit(radix: u32) -> i64; } impl ExactFloat for f32 { #[inline(always)] fn exponent_limit(radix: u32) -> (i64, i64) { debug_assert_radix(radix); f32_exponent_limit(radix) } #[inline(always)] fn mantissa_limit(radix: u32) -> i64 { debug_assert_radix(radix); f32_mantissa_limit(radix) } } impl ExactFloat for f64 { #[inline(always)] fn exponent_limit(radix: u32) -> (i64, i64) { debug_assert_radix(radix); f64_exponent_limit(radix) } #[inline(always)] fn mantissa_limit(radix: u32) -> i64 { debug_assert_radix(radix); f64_mantissa_limit(radix) } } #[cfg(feature = "f16")] impl ExactFloat for f16 { #[inline(always)] fn exponent_limit(_: u32) -> (i64, i64) { unimplemented!() } #[inline(always)] fn mantissa_limit(_: u32) -> i64 { unimplemented!() } } #[cfg(feature = "f16")] impl ExactFloat for bf16 { #[inline(always)] fn exponent_limit(_: u32) -> (i64, i64) { unimplemented!() } #[inline(always)] fn mantissa_limit(_: u32) -> i64 { unimplemented!() } } //#[cfg(feature = "f128")] //impl ExactFloat for f128 { // #[inline(always)] // fn exponent_limit(radix: u32) -> (i64, i64) { // debug_assert_radix(radix); // match radix { // 2 if cfg!(feature = "power-of-two") => (-16494, 16383), // 3 if cfg!(feature = "radix") => (-71, 71), // 4 if cfg!(feature = "power-of-two") => (-8247, 8191), // 5 if cfg!(feature = "radix") => (-48, 48), // 6 if cfg!(feature = "radix") => (-71, 71), // 7 if cfg!(feature = "radix") => (-40, 40), // 8 if cfg!(feature = "power-of-two") => (-5498, 5461), // 9 if cfg!(feature = "radix") => (-35, 35), // 10 => (-48, 48), // 11 if cfg!(feature = "radix") => (-32, 32), // 12 if cfg!(feature = "radix") => (-71, 71), // 13 if cfg!(feature = "radix") => (-30, 30), // 14 if cfg!(feature = "radix") => (-40, 40), // 15 if cfg!(feature = "radix") => (-28, 28), // 16 if cfg!(feature = "power-of-two") => (-4123, 4095), // 17 if cfg!(feature = "radix") => (-27, 27), // 18 if cfg!(feature = "radix") => (-35, 35), // 19 if cfg!(feature = "radix") => (-26, 26), // 20 if cfg!(feature = "radix") => (-48, 48), // 21 if cfg!(feature = "radix") => (-25, 25), // 22 if cfg!(feature = "radix") => (-32, 32), // 23 if cfg!(feature = "radix") => (-24, 24), // 24 if cfg!(feature = "radix") => (-71, 71), // 25 if cfg!(feature = "radix") => (-24, 24), // 26 if cfg!(feature = "radix") => (-30, 30), // 27 if cfg!(feature = "radix") => (-23, 23), // 28 if cfg!(feature = "radix") => (-40, 40), // 29 if cfg!(feature = "radix") => (-23, 23), // 30 if cfg!(feature = "radix") => (-28, 28), // 31 if cfg!(feature = "radix") => (-22, 22), // 32 if cfg!(feature = "power-of-two") => (-3298, 3276), // 33 if cfg!(feature = "radix") => (-22, 22), // 34 if cfg!(feature = "radix") => (-27, 27), // 35 if cfg!(feature = "radix") => (-22, 22), // 36 if cfg!(feature = "radix") => (-35, 35), // // Invalid radix // _ => unreachable!(), // } // } // // #[inline(always)] // fn mantissa_limit(radix: u32) -> i64 { // debug_assert_radix(radix); // match radix { // 2 if cfg!(feature = "power-of-two") => 113, // 3 if cfg!(feature = "radix") => 71, // 4 if cfg!(feature = "power-of-two") => 56, // 5 if cfg!(feature = "radix") => 48, // 6 if cfg!(feature = "radix") => 43, // 7 if cfg!(feature = "radix") => 40, // 8 if cfg!(feature = "power-of-two") => 37, // 9 if cfg!(feature = "radix") => 35, // 10 => 34, // 11 if cfg!(feature = "radix") => 32, // 12 if cfg!(feature = "radix") => 31, // 13 if cfg!(feature = "radix") => 30, // 14 if cfg!(feature = "radix") => 29, // 15 if cfg!(feature = "radix") => 28, // 16 if cfg!(feature = "power-of-two") => 28, // 17 if cfg!(feature = "radix") => 27, // 18 if cfg!(feature = "radix") => 27, // 19 if cfg!(feature = "radix") => 26, // 20 if cfg!(feature = "radix") => 26, // 21 if cfg!(feature = "radix") => 25, // 22 if cfg!(feature = "radix") => 25, // 23 if cfg!(feature = "radix") => 24, // 24 if cfg!(feature = "radix") => 24, // 25 if cfg!(feature = "radix") => 24, // 26 if cfg!(feature = "radix") => 24, // 27 if cfg!(feature = "radix") => 23, // 28 if cfg!(feature = "radix") => 23, // 29 if cfg!(feature = "radix") => 23, // 30 if cfg!(feature = "radix") => 23, // 31 if cfg!(feature = "radix") => 22, // 32 if cfg!(feature = "power-of-two") => 22, // 33 if cfg!(feature = "radix") => 22, // 34 if cfg!(feature = "radix") => 22, // 35 if cfg!(feature = "radix") => 22, // 36 if cfg!(feature = "radix") => 21, // // Invalid radix // _ => unreachable!(), // } // } //} // CONST FN // -------- /// Get the exponent limit as a const fn. #[inline(always)] pub const fn f32_exponent_limit(radix: u32) -> (i64, i64) { match radix { 2 if cfg!(feature = "power-of-two") => (-127, 127), 3 if cfg!(feature = "radix") => (-15, 15), 4 if cfg!(feature = "power-of-two") => (-63, 63), 5 if cfg!(feature = "radix") => (-10, 10), 6 if cfg!(feature = "radix") => (-15, 15), 7 if cfg!(feature = "radix") => (-8, 8), 8 if cfg!(feature = "power-of-two") => (-42, 42), 9 if cfg!(feature = "radix") => (-7, 7), 10 => (-10, 10), 11 if cfg!(feature = "radix") => (-6, 6), 12 if cfg!(feature = "radix") => (-15, 15), 13 if cfg!(feature = "radix") => (-6, 6), 14 if cfg!(feature = "radix") => (-8, 8), 15 if cfg!(feature = "radix") => (-6, 6), 16 if cfg!(feature = "power-of-two") => (-31, 31), 17 if cfg!(feature = "radix") => (-5, 5), 18 if cfg!(feature = "radix") => (-7, 7), 19 if cfg!(feature = "radix") => (-5, 5), 20 if cfg!(feature = "radix") => (-10, 10), 21 if cfg!(feature = "radix") => (-5, 5), 22 if cfg!(feature = "radix") => (-6, 6), 23 if cfg!(feature = "radix") => (-5, 5), 24 if cfg!(feature = "radix") => (-15, 15), 25 if cfg!(feature = "radix") => (-5, 5), 26 if cfg!(feature = "radix") => (-6, 6), 27 if cfg!(feature = "radix") => (-5, 5), 28 if cfg!(feature = "radix") => (-8, 8), 29 if cfg!(feature = "radix") => (-4, 4), 30 if cfg!(feature = "radix") => (-6, 6), 31 if cfg!(feature = "radix") => (-4, 4), 32 if cfg!(feature = "power-of-two") => (-25, 25), 33 if cfg!(feature = "radix") => (-4, 4), 34 if cfg!(feature = "radix") => (-5, 5), 35 if cfg!(feature = "radix") => (-4, 4), 36 if cfg!(feature = "radix") => (-7, 7), _ => (0, 0), } } /// Get the mantissa limit as a const fn. #[inline(always)] pub const fn f32_mantissa_limit(radix: u32) -> i64 { match radix { 2 if cfg!(feature = "power-of-two") => 24, 3 if cfg!(feature = "radix") => 15, 4 if cfg!(feature = "power-of-two") => 12, 5 if cfg!(feature = "radix") => 10, 6 if cfg!(feature = "radix") => 9, 7 if cfg!(feature = "radix") => 8, 8 if cfg!(feature = "power-of-two") => 8, 9 if cfg!(feature = "radix") => 7, 10 => 7, 11 if cfg!(feature = "radix") => 6, 12 if cfg!(feature = "radix") => 6, 13 if cfg!(feature = "radix") => 6, 14 if cfg!(feature = "radix") => 6, 15 if cfg!(feature = "radix") => 6, 16 if cfg!(feature = "power-of-two") => 6, 17 if cfg!(feature = "radix") => 5, 18 if cfg!(feature = "radix") => 5, 19 if cfg!(feature = "radix") => 5, 20 if cfg!(feature = "radix") => 5, 21 if cfg!(feature = "radix") => 5, 22 if cfg!(feature = "radix") => 5, 23 if cfg!(feature = "radix") => 5, 24 if cfg!(feature = "radix") => 5, 25 if cfg!(feature = "radix") => 5, 26 if cfg!(feature = "radix") => 5, 27 if cfg!(feature = "radix") => 5, 28 if cfg!(feature = "radix") => 4, 29 if cfg!(feature = "radix") => 4, 30 if cfg!(feature = "radix") => 4, 31 if cfg!(feature = "radix") => 4, 32 if cfg!(feature = "power-of-two") => 4, 33 if cfg!(feature = "radix") => 4, 34 if cfg!(feature = "radix") => 4, 35 if cfg!(feature = "radix") => 4, 36 if cfg!(feature = "radix") => 4, _ => 0, } } /// Get the exponent limit as a const fn. #[inline(always)] pub const fn f64_exponent_limit(radix: u32) -> (i64, i64) { match radix { 2 if cfg!(feature = "power-of-two") => (-1023, 1023), 3 if cfg!(feature = "radix") => (-33, 33), 4 if cfg!(feature = "power-of-two") => (-511, 511), 5 if cfg!(feature = "radix") => (-22, 22), 6 if cfg!(feature = "radix") => (-33, 33), 7 if cfg!(feature = "radix") => (-18, 18), 8 if cfg!(feature = "power-of-two") => (-341, 341), 9 if cfg!(feature = "radix") => (-16, 16), 10 => (-22, 22), 11 if cfg!(feature = "radix") => (-15, 15), 12 if cfg!(feature = "radix") => (-33, 33), 13 if cfg!(feature = "radix") => (-14, 14), 14 if cfg!(feature = "radix") => (-18, 18), 15 if cfg!(feature = "radix") => (-13, 13), 16 if cfg!(feature = "power-of-two") => (-255, 255), 17 if cfg!(feature = "radix") => (-12, 12), 18 if cfg!(feature = "radix") => (-16, 16), 19 if cfg!(feature = "radix") => (-12, 12), 20 if cfg!(feature = "radix") => (-22, 22), 21 if cfg!(feature = "radix") => (-12, 12), 22 if cfg!(feature = "radix") => (-15, 15), 23 if cfg!(feature = "radix") => (-11, 11), 24 if cfg!(feature = "radix") => (-33, 33), 25 if cfg!(feature = "radix") => (-11, 11), 26 if cfg!(feature = "radix") => (-14, 14), 27 if cfg!(feature = "radix") => (-11, 11), 28 if cfg!(feature = "radix") => (-18, 18), 29 if cfg!(feature = "radix") => (-10, 10), 30 if cfg!(feature = "radix") => (-13, 13), 31 if cfg!(feature = "radix") => (-10, 10), 32 if cfg!(feature = "power-of-two") => (-204, 204), 33 if cfg!(feature = "radix") => (-10, 10), 34 if cfg!(feature = "radix") => (-12, 12), 35 if cfg!(feature = "radix") => (-10, 10), 36 if cfg!(feature = "radix") => (-16, 16), _ => (0, 0), } } /// Get the mantissa limit as a const fn. #[inline(always)] pub const fn f64_mantissa_limit(radix: u32) -> i64 { match radix { 2 if cfg!(feature = "power-of-two") => 53, 3 if cfg!(feature = "radix") => 33, 4 if cfg!(feature = "power-of-two") => 26, 5 if cfg!(feature = "radix") => 22, 6 if cfg!(feature = "radix") => 20, 7 if cfg!(feature = "radix") => 18, 8 if cfg!(feature = "power-of-two") => 17, 9 if cfg!(feature = "radix") => 16, 10 => 15, 11 if cfg!(feature = "radix") => 15, 12 if cfg!(feature = "radix") => 14, 13 if cfg!(feature = "radix") => 14, 14 if cfg!(feature = "radix") => 13, 15 if cfg!(feature = "radix") => 13, 16 if cfg!(feature = "power-of-two") => 13, 17 if cfg!(feature = "radix") => 12, 18 if cfg!(feature = "radix") => 12, 19 if cfg!(feature = "radix") => 12, 20 if cfg!(feature = "radix") => 12, 21 if cfg!(feature = "radix") => 12, 22 if cfg!(feature = "radix") => 11, 23 if cfg!(feature = "radix") => 11, 24 if cfg!(feature = "radix") => 11, 25 if cfg!(feature = "radix") => 11, 26 if cfg!(feature = "radix") => 11, 27 if cfg!(feature = "radix") => 11, 28 if cfg!(feature = "radix") => 11, 29 if cfg!(feature = "radix") => 10, 30 if cfg!(feature = "radix") => 10, 31 if cfg!(feature = "radix") => 10, 32 if cfg!(feature = "power-of-two") => 10, 33 if cfg!(feature = "radix") => 10, 34 if cfg!(feature = "radix") => 10, 35 if cfg!(feature = "radix") => 10, 36 if cfg!(feature = "radix") => 10, _ => 0, } } // POWER LIMITS // ------------ // The code used to generate these limits is as follows: // // ```text // import math // // def find_power(base, max_value): // '''Using log is unreliable, since it uses float math.''' // // power = 0 // while base**power < max_value: // power += 1 // return power - 1 // // def print_function(bits): // print('#[inline(always)]') // print(f'pub const fn u{bits}_power_limit(radix: u32) -> u32 {{') // print(' match radix {') // max_value = 2**bits - 1 // for radix in range(2, 37): // power = find_power(radix, max_value) // print(f' {radix} => {power},') // print(' // Any other radix should be unreachable.') // print(' _ => 1,') // print(' }') // print('}') // print('') // // print_function(32) // print_function(64) // ``` /// Get the maximum value for `radix^N` that can be represented in a u32. /// This is calculated as `⌊log(2^32 - 1, b)⌋`. #[inline(always)] pub const fn u32_power_limit(radix: u32) -> u32 { match radix { 2 if cfg!(feature = "power-of-two") => 31, 3 if cfg!(feature = "radix") => 20, 4 if cfg!(feature = "power-of-two") => 15, 5 => 13, 6 if cfg!(feature = "radix") => 12, 7 if cfg!(feature = "radix") => 11, 8 if cfg!(feature = "power-of-two") => 10, 9 if cfg!(feature = "radix") => 10, 10 => 9, 11 if cfg!(feature = "radix") => 9, 12 if cfg!(feature = "radix") => 8, 13 if cfg!(feature = "radix") => 8, 14 if cfg!(feature = "radix") => 8, 15 if cfg!(feature = "radix") => 8, 16 if cfg!(feature = "power-of-two") => 7, 17 if cfg!(feature = "radix") => 7, 18 if cfg!(feature = "radix") => 7, 19 if cfg!(feature = "radix") => 7, 20 if cfg!(feature = "radix") => 7, 21 if cfg!(feature = "radix") => 7, 22 if cfg!(feature = "radix") => 7, 23 if cfg!(feature = "radix") => 7, 24 if cfg!(feature = "radix") => 6, 25 if cfg!(feature = "radix") => 6, 26 if cfg!(feature = "radix") => 6, 27 if cfg!(feature = "radix") => 6, 28 if cfg!(feature = "radix") => 6, 29 if cfg!(feature = "radix") => 6, 30 if cfg!(feature = "radix") => 6, 31 if cfg!(feature = "radix") => 6, 32 if cfg!(feature = "power-of-two") => 6, 33 if cfg!(feature = "radix") => 6, 34 if cfg!(feature = "radix") => 6, 35 if cfg!(feature = "radix") => 6, 36 if cfg!(feature = "radix") => 6, // Any other radix should be unreachable. _ => 1, } } /// Get the maximum value for `radix^N` that can be represented in a u64. /// This is calculated as `⌊log(2^64 - 1, b)⌋`. #[inline(always)] pub const fn u64_power_limit(radix: u32) -> u32 { match radix { 2 if cfg!(feature = "power-of-two") => 63, 3 if cfg!(feature = "radix") => 40, 4 if cfg!(feature = "power-of-two") => 31, 5 => 27, 6 if cfg!(feature = "radix") => 24, 7 if cfg!(feature = "radix") => 22, 8 if cfg!(feature = "power-of-two") => 21, 9 if cfg!(feature = "radix") => 20, 10 => 19, 11 if cfg!(feature = "radix") => 18, 12 if cfg!(feature = "radix") => 17, 13 if cfg!(feature = "radix") => 17, 14 if cfg!(feature = "radix") => 16, 15 if cfg!(feature = "radix") => 16, 16 if cfg!(feature = "power-of-two") => 15, 17 if cfg!(feature = "radix") => 15, 18 if cfg!(feature = "radix") => 15, 19 if cfg!(feature = "radix") => 15, 20 if cfg!(feature = "radix") => 14, 21 if cfg!(feature = "radix") => 14, 22 if cfg!(feature = "radix") => 14, 23 if cfg!(feature = "radix") => 14, 24 if cfg!(feature = "radix") => 13, 25 if cfg!(feature = "radix") => 13, 26 if cfg!(feature = "radix") => 13, 27 if cfg!(feature = "radix") => 13, 28 if cfg!(feature = "radix") => 13, 29 if cfg!(feature = "radix") => 13, 30 if cfg!(feature = "radix") => 13, 31 if cfg!(feature = "radix") => 12, 32 if cfg!(feature = "power-of-two") => 12, 33 if cfg!(feature = "radix") => 12, 34 if cfg!(feature = "radix") => 12, 35 if cfg!(feature = "radix") => 12, 36 if cfg!(feature = "radix") => 12, // Any other radix should be unreachable. _ => 1, } } // MAX DIGITS // ---------- /// Calculate the maximum number of digits possible in the mantissa. /// /// Returns the maximum number of digits plus one. /// /// We can exactly represent a float in radix `b` from radix 2 if /// `b` is divisible by 2. This function calculates the exact number of /// digits required to exactly represent that float. This makes sense, /// and the exact reference and I quote is: /// /// > A necessary and sufficient condition for all numbers representable in radix β /// > with a finite number of digits to be representable in radix γ with a /// > finite number of digits is that β should divide an integer power of γ. /// /// According to the "Handbook of Floating Point Arithmetic", /// for IEEE754, with emin being the min exponent, p2 being the /// precision, and b being the radix, the number of digits follows as: /// /// `−emin + p2 + ⌊(emin + 1) log(2, b) − log(1 − 2^(−p2), b)⌋` /// /// For f16, this follows as: /// emin = -14 /// p2 = 11 /// /// For bfloat16 , this follows as: /// emin = -126 /// p2 = 8 /// /// For f32, this follows as: /// emin = -126 /// p2 = 24 /// /// For f64, this follows as: /// emin = -1022 /// p2 = 53 /// /// For f128, this follows as: /// emin = -16382 /// p2 = 113 /// /// In Python: /// `-emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b))` /// /// This was used to calculate the maximum number of digits for [2, 36]. /// /// The minimum, denormal exponent can be calculated as follows: given /// the number of exponent bits `exp_bits`, and the number of bits /// in the mantissa `mantissa_bits`, we have an exponent bias /// `exp_bias` equal to `2^(exp_bits-1) - 1 + mantissa_bits`. We /// therefore have a denormal exponent `denormal_exp` equal to /// `1 - exp_bias` and the minimum, denormal float `min_float` is /// therefore `2^denormal_exp`. /// /// For f16, this follows as: /// exp_bits = 5 /// mantissa_bits = 10 /// exp_bias = 25 /// denormal_exp = -24 /// min_float = 5.96 * 10^−8 /// /// For bfloat16, this follows as: /// exp_bits = 8 /// mantissa_bits = 7 /// exp_bias = 134 /// denormal_exp = -133 /// min_float = 9.18 * 10^−41 /// /// For f32, this follows as: /// exp_bits = 8 /// mantissa_bits = 23 /// exp_bias = 150 /// denormal_exp = -149 /// min_float = 1.40 * 10^−45 /// /// For f64, this follows as: /// exp_bits = 11 /// mantissa_bits = 52 /// exp_bias = 1075 /// denormal_exp = -1074 /// min_float = 5.00 * 10^−324 /// /// For f128, this follows as: /// exp_bits = 15 /// mantissa_bits = 112 /// exp_bias = 16495 /// denormal_exp = -16494 /// min_float = 6.48 * 10^−4966 /// /// These match statements can be generated with the following Python /// code: /// ```python /// import math /// /// def digits(emin, p2, b): /// return -emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b)) /// /// def max_digits(emin, p2): /// radices = [6, 10, 12, 14, 18, 20, 22, 24 26 28, 30, 34, 36] /// print('match radix {') /// for radix in radices: /// value = digits(emin, p2, radix) /// print(f' {radix} => Some({value + 2}),') /// print(' // Powers of two should be unreachable.') /// print(' // Odd numbers will have infinite digits.') /// print(' _ => None,') /// print('}') /// ``` pub trait MaxDigits { fn max_digits(radix: u32) -> Option; } /// emin = -126 /// p2 = 24 impl MaxDigits for f32 { #[inline(always)] fn max_digits(radix: u32) -> Option { debug_assert_radix(radix); f32_max_digits(radix) } } /// emin = -1022 /// p2 = 53 impl MaxDigits for f64 { #[inline(always)] fn max_digits(radix: u32) -> Option { debug_assert_radix(radix); f64_max_digits(radix) } } #[cfg(feature = "f16")] impl MaxDigits for f16 { #[inline(always)] fn max_digits(_: u32) -> Option { unimplemented!() } } #[cfg(feature = "f16")] impl MaxDigits for bf16 { #[inline(always)] fn max_digits(_: u32) -> Option { unimplemented!() } } ///// emin = -16382 ///// p2 = 113 //#[cfg(feature = "f128")] //impl MaxDigits for f128 { // #[inline(always)] // fn max_digits(radix: u32) -> Option { // match radix { // 6 => Some(10159), // 10 => Some(11565), // 12 => Some(11927), // 14 => Some(12194), // 18 => Some(12568), // 20 => Some(12706), // 22 => Some(12823), // 24 => Some(12924), // 26 => Some(13012), // 28 => Some(13089), // 30 => Some(13158), // 34 => Some(13277), // 36 => Some(13328), // // Powers of two should be unreachable. // // Odd numbers will have infinite digits. // _ => None, // } // } //} // CONST FN // -------- /// Get the maximum number of significant digits as a const fn. #[inline(always)] pub const fn f32_max_digits(radix: u32) -> Option { match radix { 6 => Some(103), 10 => Some(114), 12 => Some(117), 14 => Some(119), 18 => Some(122), 20 => Some(123), 22 => Some(123), 24 => Some(124), 26 => Some(125), 28 => Some(125), 30 => Some(126), 34 => Some(127), 36 => Some(127), // Powers of two should be unreachable. // Odd numbers will have infinite digits. _ => None, } } /// Get the maximum number of significant digits as a const fn. #[inline(always)] pub const fn f64_max_digits(radix: u32) -> Option { match radix { 6 => Some(682), 10 => Some(769), 12 => Some(792), 14 => Some(808), 18 => Some(832), 20 => Some(840), 22 => Some(848), 24 => Some(854), 26 => Some(859), 28 => Some(864), 30 => Some(868), 34 => Some(876), 36 => Some(879), // Powers of two should be unreachable. // Odd numbers will have infinite digits. _ => None, } } lexical-parse-float-0.8.5/src/mask.rs000064400000000000000000000022760072674642500156210ustar 00000000000000//! Utilities to generate bitmasks. #![doc(hidden)] /// Generate a bitwise mask for the lower `n` bits. /// /// # Examples /// /// ```rust /// # use lexical_parse_float::mask::lower_n_mask; /// # pub fn main() { /// assert_eq!(lower_n_mask(2), 0b11); /// # } /// ``` #[inline] pub fn lower_n_mask(n: u64) -> u64 { debug_assert!(n <= 64, "lower_n_mask() overflow in shl."); match n == 64 { true => u64::MAX, false => (1 << n) - 1, } } /// Calculate the halfway point for the lower `n` bits. /// /// # Examples /// /// ```rust /// # use lexical_parse_float::mask::lower_n_halfway; /// # pub fn main() { /// assert_eq!(lower_n_halfway(2), 0b10); /// # } /// ``` #[inline] pub fn lower_n_halfway(n: u64) -> u64 { debug_assert!(n <= 64, "lower_n_halfway() overflow in shl."); match n == 0 { true => 0, false => nth_bit(n - 1), } } /// Calculate a scalar factor of 2 above the halfway point. /// /// # Examples /// /// ```rust /// # use lexical_parse_float::mask::nth_bit; /// # pub fn main() { /// assert_eq!(nth_bit(2), 0b100); /// # } /// ``` #[inline] pub fn nth_bit(n: u64) -> u64 { debug_assert!(n < 64, "nth_bit() overflow in shl."); 1 << n } lexical-parse-float-0.8.5/src/number.rs000064400000000000000000000140710072674642500161520ustar 00000000000000//! Representation of a float as the significant digits and exponent. //! //! This is adapted from [fast-float-rust](https://github.com/aldanor/fast-float-rust), //! a port of [fast_float](https://github.com/fastfloat/fast_float) to Rust. //! #![doc(hidden)] use crate::float::RawFloat; #[cfg(feature = "nightly")] use crate::fpu::set_precision; use lexical_util::format::NumberFormat; /// Representation of a number as the significant digits and exponent. /// /// This is only used if the exponent base and the significant digit /// radix are the same, since we need to be able to move powers in and /// out of the exponent. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct Number<'a> { /// The exponent of the float, scaled to the mantissa. pub exponent: i64, /// The significant digits of the float. pub mantissa: u64, /// If the float is negative. pub is_negative: bool, /// If the significant digits were truncated. pub many_digits: bool, /// The significant integer digits. pub integer: &'a [u8], /// The significant fraction digits. pub fraction: Option<&'a [u8]>, } impl<'a> Number<'a> { /// Detect if the float can be accurately reconstructed from native floats. #[inline] pub fn is_fast_path(&self) -> bool { let format = NumberFormat:: {}; debug_assert!(format.mantissa_radix() == format.exponent_base()); F::min_exponent_fast_path(format.radix()) <= self.exponent && self.exponent <= F::max_exponent_disguised_fast_path(format.radix()) && self.mantissa <= F::MAX_MANTISSA_FAST_PATH && !self.many_digits } /// The fast path algorithmn using machine-sized integers and floats. /// /// This is extracted into a separate function so that it can be attempted before constructing /// a Decimal. This only works if both the mantissa and the exponent /// can be exactly represented as a machine float, since IEE-754 guarantees /// no rounding will occur. /// /// There is an exception: disguised fast-path cases, where we can shift /// powers-of-10 from the exponent to the significant digits. // `set_precision` doesn't return a unit value on x87 FPUs. #[allow(clippy::let_unit_value)] pub fn try_fast_path(&self) -> Option { let format = NumberFormat:: {}; debug_assert!(format.mantissa_radix() == format.exponent_base()); // The fast path crucially depends on arithmetic being rounded to the correct number of bits // without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision // of the x87 FPU stack to be changed so that it directly rounds to 64/32 bit. // The `set_precision` function takes care of setting the precision on architectures which // require setting it by changing the global state (like the control word of the x87 FPU). #[cfg(feature = "nightly")] let _cw = set_precision::(); if self.is_fast_path::() { let radix = format.radix(); let max_exponent = F::max_exponent_fast_path(radix); let mut value = if self.exponent <= max_exponent { // normal fast path let value = F::as_cast(self.mantissa); if self.exponent < 0 { // SAFETY: safe, since the `exponent <= max_exponent`. value / unsafe { F::pow_fast_path((-self.exponent) as _, radix) } } else { // SAFETY: safe, since the `exponent <= max_exponent`. value * unsafe { F::pow_fast_path(self.exponent as _, radix) } } } else { // disguised fast path let shift = self.exponent - max_exponent; // SAFETY: safe, since `shift <= (max_disguised - max_exponent)`. let int_power = unsafe { F::int_pow_fast_path(shift as usize, radix) }; let mantissa = self.mantissa.checked_mul(int_power)?; if mantissa > F::MAX_MANTISSA_FAST_PATH { return None; } // SAFETY: safe, since the `table.len() - 1 == max_exponent`. F::as_cast(mantissa) * unsafe { F::pow_fast_path(max_exponent as _, radix) } }; if self.is_negative { value = -value; } Some(value) } else { None } } /// Force a fast-path algorithm, even when it may not be accurate. // `set_precision` doesn't return a unit value on x87 FPUs. #[allow(clippy::let_unit_value)] pub fn force_fast_path(&self) -> F { let format = NumberFormat:: {}; debug_assert!(format.mantissa_radix() == format.exponent_base()); #[cfg(feature = "nightly")] let _cw = set_precision::(); let radix = format.radix(); let mut value = F::as_cast(self.mantissa); let max_exponent = F::max_exponent_fast_path(radix); let mut exponent = self.exponent.abs(); if self.exponent < 0 { while exponent > max_exponent { // SAFETY: safe, since pow_fast_path is always safe for max_exponent. value /= unsafe { F::pow_fast_path(max_exponent as _, radix) }; exponent -= max_exponent; } // SAFETY: safe, since the `exponent < max_exponent`. value /= unsafe { F::pow_fast_path(exponent as _, radix) }; } else { while exponent > max_exponent { // SAFETY: safe, since pow_fast_path is always safe for max_exponent. value *= unsafe { F::pow_fast_path(max_exponent as _, radix) }; exponent -= max_exponent; } // SAFETY: safe, since the `exponent < max_exponent`. value *= unsafe { F::pow_fast_path(exponent as _, radix) }; } if self.is_negative { value = -value; } value } } lexical-parse-float-0.8.5/src/options.rs000064400000000000000000001114670072674642500163640ustar 00000000000000//! Configuration options for parsing floats. use lexical_util::ascii::{is_valid_ascii, is_valid_letter_slice}; use lexical_util::error::Error; use lexical_util::options::{self, ParseOptions}; use lexical_util::result::Result; use static_assertions::const_assert; /// Maximum length for a special string. const MAX_SPECIAL_STRING_LENGTH: usize = 50; /// Builder for `Options`. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct OptionsBuilder { /// Disable the use of arbitrary-precision arithmetic, and always /// return the results from the fast or intermediate path algorithms. lossy: bool, /// Character to designate the exponent component of a float. exponent: u8, /// Character to separate the integer from the fraction components. decimal_point: u8, /// String representation of Not A Number, aka `NaN`. nan_string: Option<&'static [u8]>, /// Short string representation of `Infinity`. inf_string: Option<&'static [u8]>, /// Long string representation of `Infinity`. infinity_string: Option<&'static [u8]>, } impl OptionsBuilder { /// Create new options builder with default options. #[inline(always)] pub const fn new() -> Self { Self { lossy: false, exponent: b'e', decimal_point: b'.', nan_string: Some(b"NaN"), inf_string: Some(b"inf"), infinity_string: Some(b"infinity"), } } // GETTERS /// Get if we disable the use of arbitrary-precision arithmetic. #[inline(always)] pub const fn get_lossy(&self) -> bool { self.lossy } /// Get the character to designate the exponent component of a float. #[inline(always)] pub const fn get_exponent(&self) -> u8 { self.exponent } /// Get the character to separate the integer from the fraction components. #[inline(always)] pub const fn get_decimal_point(&self) -> u8 { self.decimal_point } /// Get the string representation for `NaN`. #[inline(always)] pub const fn get_nan_string(&self) -> Option<&'static [u8]> { self.nan_string } /// Get the short string representation for `Infinity`. #[inline(always)] pub const fn get_inf_string(&self) -> Option<&'static [u8]> { self.inf_string } /// Get the long string representation for `Infinity`. #[inline(always)] pub const fn get_infinity_string(&self) -> Option<&'static [u8]> { self.infinity_string } // SETTERS /// Set if we disable the use of arbitrary-precision arithmetic. #[inline(always)] pub const fn lossy(mut self, lossy: bool) -> Self { self.lossy = lossy; self } /// Set the character to designate the exponent component of a float. #[inline(always)] pub const fn exponent(mut self, exponent: u8) -> Self { self.exponent = exponent; self } /// Set the character to separate the integer from the fraction components. #[inline(always)] pub const fn decimal_point(mut self, decimal_point: u8) -> Self { self.decimal_point = decimal_point; self } /// Set the string representation for `NaN`. #[inline(always)] pub const fn nan_string(mut self, nan_string: Option<&'static [u8]>) -> Self { self.nan_string = nan_string; self } /// Set the short string representation for `Infinity`. #[inline(always)] pub const fn inf_string(mut self, inf_string: Option<&'static [u8]>) -> Self { self.inf_string = inf_string; self } /// Set the long string representation for `Infinity`. #[inline(always)] pub const fn infinity_string(mut self, infinity_string: Option<&'static [u8]>) -> Self { self.infinity_string = infinity_string; self } // BUILDERS /// Determine if `nan_str` is valid. #[inline(always)] #[allow(clippy::if_same_then_else, clippy::needless_bool)] pub const fn nan_str_is_valid(&self) -> bool { if self.nan_string.is_none() { return true; } let nan = unwrap_str(self.nan_string); let length = nan.len(); if length == 0 || length > MAX_SPECIAL_STRING_LENGTH { false } else if !matches!(nan[0], b'N' | b'n') { false } else if !is_valid_letter_slice(nan) { false } else { true } } /// Determine if `inf_str` is valid. #[inline(always)] #[allow(clippy::if_same_then_else, clippy::needless_bool)] pub const fn inf_str_is_valid(&self) -> bool { if self.infinity_string.is_none() && self.inf_string.is_some() { return false; } else if self.inf_string.is_none() { return true; } let inf = unwrap_str(self.inf_string); let length = inf.len(); let infinity = unwrap_str(self.infinity_string); if length == 0 || length > MAX_SPECIAL_STRING_LENGTH { false } else if !matches!(inf[0], b'I' | b'i') { false } else if length > infinity.len() { false } else if !is_valid_letter_slice(inf) { false } else { true } } /// Determine if `infinity_string` is valid. #[inline(always)] #[allow(clippy::if_same_then_else, clippy::needless_bool)] pub const fn infinity_string_is_valid(&self) -> bool { if self.infinity_string.is_none() && self.inf_string.is_some() { return false; } else if self.infinity_string.is_none() { return true; } let inf = unwrap_str(self.inf_string); let infinity = unwrap_str(self.infinity_string); let length = infinity.len(); if length == 0 || length > MAX_SPECIAL_STRING_LENGTH { false } else if !matches!(infinity[0], b'I' | b'i') { false } else if length < inf.len() { false } else if !is_valid_letter_slice(infinity) { false } else { true } } /// Check if the builder state is valid. #[inline(always)] #[allow(clippy::if_same_then_else, clippy::needless_bool)] pub const fn is_valid(&self) -> bool { if !is_valid_ascii(self.exponent) { false } else if !is_valid_ascii(self.decimal_point) { false } else if !self.nan_str_is_valid() { false } else if !self.inf_str_is_valid() { false } else if !self.infinity_string_is_valid() { false } else { true } } /// Build the Options struct without validation. /// /// # Safety /// /// Always safe, just marked as unsafe for API compatibility. /// The result may be invalid if `is_valid` is not true. #[inline(always)] pub const unsafe fn build_unchecked(&self) -> Options { Options { lossy: self.lossy, exponent: self.exponent, decimal_point: self.decimal_point, nan_string: self.nan_string, inf_string: self.inf_string, infinity_string: self.infinity_string, } } /// Build the Options struct. #[inline(always)] #[allow(clippy::if_same_then_else)] pub const fn build(&self) -> Result { if !is_valid_ascii(self.exponent) { return Err(Error::InvalidExponentSymbol); } else if !is_valid_ascii(self.decimal_point) { return Err(Error::InvalidDecimalPoint); } if self.nan_string.is_some() { let nan = unwrap_str(self.nan_string); if nan.is_empty() || !matches!(nan[0], b'N' | b'n') { return Err(Error::InvalidNanString); } else if !is_valid_letter_slice(nan) { return Err(Error::InvalidNanString); } else if nan.len() > MAX_SPECIAL_STRING_LENGTH { return Err(Error::NanStringTooLong); } } if self.inf_string.is_some() && self.infinity_string.is_none() { return Err(Error::InfinityStringTooShort); } if self.inf_string.is_some() { let inf = unwrap_str(self.inf_string); if inf.is_empty() || !matches!(inf[0], b'I' | b'i') { return Err(Error::InvalidInfString); } else if !is_valid_letter_slice(inf) { return Err(Error::InvalidInfString); } else if inf.len() > MAX_SPECIAL_STRING_LENGTH { return Err(Error::InfStringTooLong); } } if self.infinity_string.is_some() { let inf = unwrap_str(self.inf_string); let infinity = unwrap_str(self.infinity_string); if infinity.is_empty() || !matches!(infinity[0], b'I' | b'i') { return Err(Error::InvalidInfinityString); } else if !is_valid_letter_slice(infinity) { return Err(Error::InvalidInfinityString); } else if infinity.len() > MAX_SPECIAL_STRING_LENGTH { return Err(Error::InfinityStringTooLong); } else if infinity.len() < inf.len() { return Err(Error::InfinityStringTooShort); } } // SAFETY: always safe, since it must be valid. Ok(unsafe { self.build_unchecked() }) } } impl Default for OptionsBuilder { #[inline(always)] fn default() -> Self { Self::new() } } /// Options to customize parsing floats. /// /// # Examples /// /// ```rust /// use lexical_parse_float::Options; /// /// # pub fn main() { /// let options = Options::builder() /// .lossy(true) /// .nan_string(Some(b"NaN")) /// .inf_string(Some(b"Inf")) /// .infinity_string(Some(b"Infinity")) /// .build() /// .unwrap(); /// # } /// ``` #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Options { /// Disable the use of arbitrary-precision arithmetic, and always /// return the results from the fast or intermediate path algorithms. lossy: bool, /// Character to designate the exponent component of a float. exponent: u8, /// Character to separate the integer from the fraction components. decimal_point: u8, /// String representation of Not A Number, aka `NaN`. nan_string: Option<&'static [u8]>, /// Short string representation of `Infinity`. inf_string: Option<&'static [u8]>, /// Long string representation of `Infinity`. infinity_string: Option<&'static [u8]>, } impl Options { // CONSTRUCTORS /// Create options with default values. #[inline(always)] pub const fn new() -> Self { // SAFETY: always safe since it uses the default arguments. unsafe { Self::builder().build_unchecked() } } /// Create the default options for a given radix. #[inline(always)] #[cfg(feature = "power-of-two")] pub const fn from_radix(radix: u8) -> Self { // Need to determine the correct exponent character ('e' or '^'), // since the default character is `e` normally, but this is a valid // digit for radix >= 15. let mut builder = Self::builder(); if radix >= 15 { builder = builder.exponent(b'^'); } // SAFETY: always safe since it uses the default arguments. unsafe { builder.build_unchecked() } } // GETTERS /// Check if the options state is valid. #[inline(always)] pub const fn is_valid(&self) -> bool { self.rebuild().is_valid() } /// Get if we disable the use of arbitrary-precision arithmetic. #[inline(always)] pub const fn lossy(&self) -> bool { self.lossy } /// Get the character to designate the exponent component of a float. #[inline(always)] pub const fn exponent(&self) -> u8 { self.exponent } /// Get the character to separate the integer from the fraction components. #[inline(always)] pub const fn decimal_point(&self) -> u8 { self.decimal_point } /// Get the string representation for `NaN`. #[inline(always)] pub const fn nan_string(&self) -> Option<&'static [u8]> { self.nan_string } /// Get the short string representation for `Infinity`. #[inline(always)] pub const fn inf_string(&self) -> Option<&'static [u8]> { self.inf_string } /// Get the long string representation for `Infinity`. #[inline(always)] pub const fn infinity_string(&self) -> Option<&'static [u8]> { self.infinity_string } // SETTERS /// Set if we disable the use of arbitrary-precision arithmetic. /// /// # Safety /// /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] pub unsafe fn set_lossy(&mut self, lossy: bool) { self.lossy = lossy } /// Set the character to designate the exponent component of a float. /// /// # Safety /// /// Always safe, but may produce invalid output if the exponent /// is not a valid ASCII character. #[inline(always)] pub unsafe fn set_exponent(&mut self, exponent: u8) { self.exponent = exponent; } /// Set the character to separate the integer from the fraction components. /// /// # Safety /// /// Always safe, but may produce invalid output if the decimal point /// is not a valid ASCII character. #[inline(always)] pub unsafe fn set_decimal_point(&mut self, decimal_point: u8) { self.decimal_point = decimal_point; } /// Set the string representation for `NaN`. /// Unsafe, use the builder API for option validation. /// /// # Safety /// /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] pub unsafe fn set_nan_string(&mut self, nan_string: Option<&'static [u8]>) { self.nan_string = nan_string } /// Set the short string representation for `Infinity` /// Unsafe, use the builder API for option validation. /// /// # Safety /// /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] pub unsafe fn set_inf_string(&mut self, inf_string: Option<&'static [u8]>) { self.inf_string = inf_string } /// Set the long string representation for `Infinity` /// Unsafe, use the builder API for option validation. /// /// # Safety /// /// Always safe, just marked as unsafe for API compatibility. #[inline(always)] pub unsafe fn set_infinity_string(&mut self, infinity_string: Option<&'static [u8]>) { self.infinity_string = infinity_string } // BUILDERS /// Get OptionsBuilder as a static function. #[inline(always)] pub const fn builder() -> OptionsBuilder { OptionsBuilder::new() } /// Create OptionsBuilder using existing values. #[inline(always)] pub const fn rebuild(&self) -> OptionsBuilder { OptionsBuilder { lossy: self.lossy, exponent: self.exponent, decimal_point: self.decimal_point, nan_string: self.nan_string, inf_string: self.inf_string, infinity_string: self.infinity_string, } } } impl Default for Options { #[inline(always)] fn default() -> Self { Self::new() } } impl ParseOptions for Options { #[inline(always)] fn is_valid(&self) -> bool { Self::is_valid(self) } } /// Unwrap `Option` as a const fn. #[inline(always)] const fn unwrap_str(option: Option<&'static [u8]>) -> &'static [u8] { match option { Some(x) => x, None => &[], } } // PRE-DEFINED CONSTANTS // --------------------- // Only constants that differ from the standard version are included. // SAFETY: all of these are safe, since they are checked to be valid // after calling `build_unchecked`. Furthermore, even though the methods // are marked as `unsafe`, none of the produced options can cause memory // safety issues. /// Standard number format. #[rustfmt::skip] pub const STANDARD: Options = Options::new(); const_assert!(STANDARD.is_valid()); /// Numerical format with a decimal comma. /// This is the standard numerical format for most of the world. #[rustfmt::skip] pub const DECIMAL_COMMA: Options = unsafe { Options::builder() .decimal_point(b',') .build_unchecked() }; const_assert!(DECIMAL_COMMA.is_valid()); /// Numerical format for hexadecimal floats, which use a `p` exponent. #[rustfmt::skip] pub const HEX_FLOAT: Options = unsafe { Options::builder() .exponent(b'p') .build_unchecked() }; const_assert!(HEX_FLOAT.is_valid()); /// Numerical format where `^` is used as the exponent notation character. /// This isn't very common, but is useful when `e` or `p` are valid digits. #[rustfmt::skip] pub const CARAT_EXPONENT: Options = unsafe { Options::builder() .exponent(b'^') .build_unchecked() }; const_assert!(CARAT_EXPONENT.is_valid()); /// Number format for a Rust literal floating-point number. #[rustfmt::skip] pub const RUST_LITERAL: Options = unsafe { Options::builder() .nan_string(options::RUST_LITERAL) .inf_string(options::RUST_LITERAL) .infinity_string(options::RUST_LITERAL) .build_unchecked() }; const_assert!(RUST_LITERAL.is_valid()); /// Number format for a Python literal floating-point number. #[rustfmt::skip] pub const PYTHON_LITERAL: Options = unsafe { Options::builder() .nan_string(options::PYTHON_LITERAL) .inf_string(options::PYTHON_LITERAL) .infinity_string(options::PYTHON_LITERAL) .build_unchecked() }; const_assert!(PYTHON_LITERAL.is_valid()); /// Number format for a C++ literal floating-point number. #[rustfmt::skip] pub const CXX_LITERAL: Options = unsafe { Options::builder() .nan_string(options::CXX_LITERAL_NAN) .inf_string(options::CXX_LITERAL_INF) .infinity_string(options::CXX_LITERAL_INFINITY) .build_unchecked() }; const_assert!(CXX_LITERAL.is_valid()); /// Number format for a C literal floating-point number. #[rustfmt::skip] pub const C_LITERAL: Options = unsafe { Options::builder() .nan_string(options::C_LITERAL_NAN) .inf_string(options::C_LITERAL_INF) .infinity_string(options::C_LITERAL_INFINITY) .build_unchecked() }; const_assert!(CXX_LITERAL.is_valid()); /// Number format for a Ruby literal floating-point number. #[rustfmt::skip] pub const RUBY_LITERAL: Options = unsafe { Options::builder() .nan_string(options::RUBY) .inf_string(options::RUBY) .infinity_string(options::RUBY) .build_unchecked() }; const_assert!(RUBY_LITERAL.is_valid()); /// Number format to parse a Ruby float from string. #[rustfmt::skip] pub const RUBY_STRING: Options = unsafe { Options::builder() .nan_string(options::RUBY) .inf_string(options::RUBY) .infinity_string(options::RUBY) .build_unchecked() }; const_assert!(RUBY_STRING.is_valid()); /// Number format for a Swift literal floating-point number. #[rustfmt::skip] pub const SWIFT_LITERAL: Options = unsafe { Options::builder() .nan_string(options::SWIFT_LITERAL) .inf_string(options::SWIFT_LITERAL) .infinity_string(options::SWIFT_LITERAL) .build_unchecked() }; const_assert!(SWIFT_LITERAL.is_valid()); /// Number format for a Go literal floating-point number. #[rustfmt::skip] pub const GO_LITERAL: Options = unsafe { Options::builder() .nan_string(options::GO_LITERAL) .inf_string(options::GO_LITERAL) .infinity_string(options::GO_LITERAL) .build_unchecked() }; const_assert!(GO_LITERAL.is_valid()); /// Number format for a Haskell literal floating-point number. #[rustfmt::skip] pub const HASKELL_LITERAL: Options = unsafe { Options::builder() .nan_string(options::HASKELL_LITERAL) .inf_string(options::HASKELL_LITERAL) .infinity_string(options::HASKELL_LITERAL) .build_unchecked() }; const_assert!(HASKELL_LITERAL.is_valid()); /// Number format to parse a Haskell float from string. #[rustfmt::skip] pub const HASKELL_STRING: Options = unsafe { Options::builder() .inf_string(options::HASKELL_STRING_INF) .infinity_string(options::HASKELL_STRING_INFINITY) .build_unchecked() }; const_assert!(HASKELL_STRING.is_valid()); /// Number format for a Javascript literal floating-point number. #[rustfmt::skip] pub const JAVASCRIPT_LITERAL: Options = unsafe { Options::builder() .inf_string(options::JAVASCRIPT_INF) .infinity_string(options::JAVASCRIPT_INFINITY) .build_unchecked() }; const_assert!(JAVASCRIPT_LITERAL.is_valid()); /// Number format to parse a Javascript float from string. #[rustfmt::skip] pub const JAVASCRIPT_STRING: Options = unsafe { Options::builder() .inf_string(options::JAVASCRIPT_INF) .infinity_string(options::JAVASCRIPT_INFINITY) .build_unchecked() }; const_assert!(JAVASCRIPT_STRING.is_valid()); /// Number format for a Perl literal floating-point number. #[rustfmt::skip] pub const PERL_LITERAL: Options = unsafe { Options::builder() .nan_string(options::PERL_LITERAL) .inf_string(options::PERL_LITERAL) .infinity_string(options::PERL_LITERAL) .build_unchecked() }; const_assert!(PERL_LITERAL.is_valid()); /// Number format for a PHP literal floating-point number. #[rustfmt::skip] pub const PHP_LITERAL: Options = unsafe { Options::builder() .nan_string(options::PHP_LITERAL_NAN) .inf_string(options::PHP_LITERAL_INF) .infinity_string(options::PHP_LITERAL_INFINITY) .build_unchecked() }; const_assert!(PHP_LITERAL.is_valid()); /// Number format for a Java literal floating-point number. #[rustfmt::skip] pub const JAVA_LITERAL: Options = unsafe { Options::builder() .nan_string(options::JAVA_LITERAL) .inf_string(options::JAVA_LITERAL) .infinity_string(options::JAVA_LITERAL) .build_unchecked() }; const_assert!(JAVA_LITERAL.is_valid()); /// Number format to parse a Java float from string. #[rustfmt::skip] pub const JAVA_STRING: Options = unsafe { Options::builder() .inf_string(options::JAVA_STRING_INF) .infinity_string(options::JAVA_STRING_INFINITY) .build_unchecked() }; const_assert!(JAVA_STRING.is_valid()); /// Number format for an R literal floating-point number. #[rustfmt::skip] pub const R_LITERAL: Options = unsafe { Options::builder() .inf_string(options::R_LITERAL_INF) .infinity_string(options::R_LITERAL_INFINITY) .build_unchecked() }; const_assert!(R_LITERAL.is_valid()); /// Number format for a Kotlin literal floating-point number. #[rustfmt::skip] pub const KOTLIN_LITERAL: Options = unsafe { Options::builder() .nan_string(options::KOTLIN_LITERAL) .inf_string(options::KOTLIN_LITERAL) .infinity_string(options::KOTLIN_LITERAL) .build_unchecked() }; const_assert!(KOTLIN_LITERAL.is_valid()); /// Number format to parse a Kotlin float from string. #[rustfmt::skip] pub const KOTLIN_STRING: Options = unsafe { Options::builder() .inf_string(options::KOTLIN_STRING_INF) .infinity_string(options::KOTLIN_STRING_INFINITY) .build_unchecked() }; const_assert!(KOTLIN_STRING.is_valid()); /// Number format for a Julia literal floating-point number. #[rustfmt::skip] pub const JULIA_LITERAL: Options = unsafe { Options::builder() .inf_string(options::JULIA_LITERAL_INF) .infinity_string(options::JULIA_LITERAL_INFINITY) .build_unchecked() }; const_assert!(JULIA_LITERAL.is_valid()); /// Number format for a C# literal floating-point number. #[rustfmt::skip] pub const CSHARP_LITERAL: Options = unsafe { Options::builder() .nan_string(options::CSHARP_LITERAL) .inf_string(options::CSHARP_LITERAL) .infinity_string(options::CSHARP_LITERAL) .build_unchecked() }; const_assert!(CSHARP_LITERAL.is_valid()); /// Number format to parse a C# float from string. #[rustfmt::skip] pub const CSHARP_STRING: Options = unsafe { Options::builder() .inf_string(options::CSHARP_STRING_INF) .infinity_string(options::CSHARP_STRING_INFINITY) .build_unchecked() }; const_assert!(CSHARP_STRING.is_valid()); /// Number format for a Kawa literal floating-point number. #[rustfmt::skip] pub const KAWA_LITERAL: Options = unsafe { Options::builder() .nan_string(options::KAWA) .inf_string(options::KAWA) .infinity_string(options::KAWA) .build_unchecked() }; const_assert!(KAWA_LITERAL.is_valid()); /// Number format to parse a Kawa float from string. #[rustfmt::skip] pub const KAWA_STRING: Options = unsafe { Options::builder() .nan_string(options::KAWA) .inf_string(options::KAWA) .infinity_string(options::KAWA) .build_unchecked() }; const_assert!(KAWA_STRING.is_valid()); /// Number format for a Gambit-C literal floating-point number. #[rustfmt::skip] pub const GAMBITC_LITERAL: Options = unsafe { Options::builder() .nan_string(options::GAMBITC) .inf_string(options::GAMBITC) .infinity_string(options::GAMBITC) .build_unchecked() }; const_assert!(GAMBITC_LITERAL.is_valid()); /// Number format to parse a Gambit-C float from string. #[rustfmt::skip] pub const GAMBITC_STRING: Options = unsafe { Options::builder() .nan_string(options::GAMBITC) .inf_string(options::GAMBITC) .infinity_string(options::GAMBITC) .build_unchecked() }; const_assert!(GAMBITC_STRING.is_valid()); /// Number format for a Guile literal floating-point number. #[rustfmt::skip] pub const GUILE_LITERAL: Options = unsafe { Options::builder() .nan_string(options::GUILE) .inf_string(options::GUILE) .infinity_string(options::GUILE) .build_unchecked() }; const_assert!(GUILE_LITERAL.is_valid()); /// Number format to parse a Guile float from string. #[rustfmt::skip] pub const GUILE_STRING: Options = unsafe { Options::builder() .nan_string(options::GUILE) .inf_string(options::GUILE) .infinity_string(options::GUILE) .build_unchecked() }; const_assert!(GUILE_STRING.is_valid()); /// Number format for a Clojure literal floating-point number. #[rustfmt::skip] pub const CLOJURE_LITERAL: Options = unsafe { Options::builder() .nan_string(options::CLOJURE_LITERAL) .inf_string(options::CLOJURE_LITERAL) .infinity_string(options::CLOJURE_LITERAL) .build_unchecked() }; const_assert!(CLOJURE_LITERAL.is_valid()); /// Number format to parse a Clojure float from string. #[rustfmt::skip] pub const CLOJURE_STRING: Options = unsafe { Options::builder() .inf_string(options::CLOJURE_STRING_INF) .infinity_string(options::CLOJURE_STRING_INFINITY) .build_unchecked() }; const_assert!(CLOJURE_STRING.is_valid()); /// Number format for an Erlang literal floating-point number. #[rustfmt::skip] pub const ERLANG_LITERAL: Options = unsafe { Options::builder() .nan_string(options::ERLANG_LITERAL_NAN) .build_unchecked() }; const_assert!(ERLANG_LITERAL.is_valid()); /// Number format to parse an Erlang float from string. #[rustfmt::skip] pub const ERLANG_STRING: Options = unsafe { Options::builder() .nan_string(options::ERLANG_STRING) .inf_string(options::ERLANG_STRING) .infinity_string(options::ERLANG_STRING) .build_unchecked() }; const_assert!(ERLANG_STRING.is_valid()); /// Number format for an Elm literal floating-point number. #[rustfmt::skip] pub const ELM_LITERAL: Options = unsafe { Options::builder() .nan_string(options::ELM_LITERAL) .inf_string(options::ELM_LITERAL) .infinity_string(options::ELM_LITERAL) .build_unchecked() }; const_assert!(ELM_LITERAL.is_valid()); /// Number format to parse an Elm float from string. #[rustfmt::skip] pub const ELM_STRING: Options = unsafe { Options::builder() .nan_string(options::ELM_STRING_NAN) .inf_string(options::ELM_STRING_INF) .infinity_string(options::ELM_STRING_INFINITY) .build_unchecked() }; const_assert!(ELM_STRING.is_valid()); /// Number format for a Scala literal floating-point number. #[rustfmt::skip] pub const SCALA_LITERAL: Options = unsafe { Options::builder() .nan_string(options::SCALA_LITERAL) .inf_string(options::SCALA_LITERAL) .infinity_string(options::SCALA_LITERAL) .build_unchecked() }; const_assert!(SCALA_LITERAL.is_valid()); /// Number format to parse a Scala float from string. #[rustfmt::skip] pub const SCALA_STRING: Options = unsafe { Options::builder() .inf_string(options::SCALA_STRING_INF) .infinity_string(options::SCALA_STRING_INFINITY) .build_unchecked() }; const_assert!(SCALA_STRING.is_valid()); /// Number format for an Elixir literal floating-point number. #[rustfmt::skip] pub const ELIXIR_LITERAL: Options = unsafe { Options::builder() .nan_string(options::ELIXIR) .inf_string(options::ELIXIR) .infinity_string(options::ELIXIR) .build_unchecked() }; const_assert!(ELIXIR_LITERAL.is_valid()); /// Number format to parse an Elixir float from string. #[rustfmt::skip] pub const ELIXIR_STRING: Options = unsafe { Options::builder() .nan_string(options::ELIXIR) .inf_string(options::ELIXIR) .infinity_string(options::ELIXIR) .build_unchecked() }; const_assert!(ELIXIR_STRING.is_valid()); /// Number format for a FORTRAN literal floating-point number. #[rustfmt::skip] pub const FORTRAN_LITERAL: Options = unsafe { Options::builder() .nan_string(options::FORTRAN_LITERAL) .inf_string(options::FORTRAN_LITERAL) .infinity_string(options::FORTRAN_LITERAL) .build_unchecked() }; const_assert!(FORTRAN_LITERAL.is_valid()); /// Number format for a D literal floating-point number. #[rustfmt::skip] pub const D_LITERAL: Options = unsafe { Options::builder() .nan_string(options::D_LITERAL) .inf_string(options::D_LITERAL) .infinity_string(options::D_LITERAL) .build_unchecked() }; const_assert!(D_LITERAL.is_valid()); /// Number format for a Coffeescript literal floating-point number. #[rustfmt::skip] pub const COFFEESCRIPT_LITERAL: Options = unsafe { Options::builder() .inf_string(options::COFFEESCRIPT_INF) .infinity_string(options::COFFEESCRIPT_INFINITY) .build_unchecked() }; const_assert!(COFFEESCRIPT_LITERAL.is_valid()); /// Number format to parse a Coffeescript float from string. #[rustfmt::skip] pub const COFFEESCRIPT_STRING: Options = unsafe { Options::builder() .inf_string(options::COFFEESCRIPT_INF) .infinity_string(options::COFFEESCRIPT_INFINITY) .build_unchecked() }; const_assert!(COFFEESCRIPT_STRING.is_valid()); /// Number format for a COBOL literal floating-point number. #[rustfmt::skip] pub const COBOL_LITERAL: Options = unsafe { Options::builder() .nan_string(options::COBOL) .inf_string(options::COBOL) .infinity_string(options::COBOL) .build_unchecked() }; const_assert!(COBOL_LITERAL.is_valid()); /// Number format to parse a COBOL float from string. #[rustfmt::skip] pub const COBOL_STRING: Options = unsafe { Options::builder() .nan_string(options::COBOL) .inf_string(options::COBOL) .infinity_string(options::COBOL) .build_unchecked() }; const_assert!(COBOL_STRING.is_valid()); /// Number format for an F# literal floating-point number. #[rustfmt::skip] pub const FSHARP_LITERAL: Options = unsafe { Options::builder() .nan_string(options::FSHARP_LITERAL_NAN) .inf_string(options::FSHARP_LITERAL_INF) .infinity_string(options::FSHARP_LITERAL_INFINITY) .build_unchecked() }; const_assert!(FSHARP_LITERAL.is_valid()); /// Number format for a Visual Basic literal floating-point number. #[rustfmt::skip] pub const VB_LITERAL: Options = unsafe { Options::builder() .nan_string(options::VB_LITERAL) .inf_string(options::VB_LITERAL) .infinity_string(options::VB_LITERAL) .build_unchecked() }; const_assert!(VB_LITERAL.is_valid()); /// Number format to parse a Visual Basic float from string. #[rustfmt::skip] pub const VB_STRING: Options = unsafe { Options::builder() .inf_string(options::VB_STRING_INF) .infinity_string(options::VB_STRING_INFINITY) .build_unchecked() }; const_assert!(VB_STRING.is_valid()); /// Number format for an OCaml literal floating-point number. #[rustfmt::skip] pub const OCAML_LITERAL: Options = unsafe { Options::builder() .nan_string(options::OCAML_LITERAL_NAN) .inf_string(options::OCAML_LITERAL_INF) .infinity_string(options::OCAML_LITERAL_INFINITY) .build_unchecked() }; const_assert!(OCAML_LITERAL.is_valid()); /// Number format for an Objective-C literal floating-point number. #[rustfmt::skip] pub const OBJECTIVEC_LITERAL: Options = unsafe { Options::builder() .nan_string(options::OBJECTIVEC) .inf_string(options::OBJECTIVEC) .infinity_string(options::OBJECTIVEC) .build_unchecked() }; const_assert!(OBJECTIVEC_LITERAL.is_valid()); /// Number format to parse an Objective-C float from string. #[rustfmt::skip] pub const OBJECTIVEC_STRING: Options = unsafe { Options::builder() .nan_string(options::OBJECTIVEC) .inf_string(options::OBJECTIVEC) .infinity_string(options::OBJECTIVEC) .build_unchecked() }; const_assert!(OBJECTIVEC_STRING.is_valid()); /// Number format for an ReasonML literal floating-point number. #[rustfmt::skip] pub const REASONML_LITERAL: Options = unsafe { Options::builder() .nan_string(options::REASONML_LITERAL_NAN) .inf_string(options::REASONML_LITERAL_INF) .infinity_string(options::REASONML_LITERAL_INFINITY) .build_unchecked() }; const_assert!(REASONML_LITERAL.is_valid()); /// Number format for a MATLAB literal floating-point number. #[rustfmt::skip] pub const MATLAB_LITERAL: Options = unsafe { Options::builder() .inf_string(options::MATLAB_LITERAL_INF) .infinity_string(options::MATLAB_LITERAL_INFINITY) .build_unchecked() }; const_assert!(MATLAB_LITERAL.is_valid()); /// Number format for a Zig literal floating-point number. #[rustfmt::skip] pub const ZIG_LITERAL: Options = unsafe { Options::builder() .nan_string(options::ZIG_LITERAL) .inf_string(options::ZIG_LITERAL) .infinity_string(options::ZIG_LITERAL) .build_unchecked() }; const_assert!(ZIG_LITERAL.is_valid()); /// Number format for a Safe literal floating-point number. #[rustfmt::skip] pub const SAGE_LITERAL: Options = unsafe { Options::builder() .inf_string(options::SAGE_LITERAL_INF) .infinity_string(options::SAGE_LITERAL_INFINITY) .build_unchecked() }; const_assert!(SAGE_LITERAL.is_valid()); /// Number format for a JSON literal floating-point number. #[rustfmt::skip] pub const JSON: Options = unsafe { Options::builder() .nan_string(options::JSON) .inf_string(options::JSON) .infinity_string(options::JSON) .build_unchecked() }; const_assert!(JSON.is_valid()); /// Number format for a TOML literal floating-point number. #[rustfmt::skip] pub const TOML: Options = unsafe { Options::builder() .nan_string(options::TOML) .inf_string(options::TOML) .infinity_string(options::TOML) .build_unchecked() }; const_assert!(TOML.is_valid()); /// Number format for a YAML literal floating-point number. #[rustfmt::skip] pub const YAML: Options = JSON; /// Number format for an XML literal floating-point number. #[rustfmt::skip] pub const XML: Options = unsafe { Options::builder() .inf_string(options::XML_INF) .infinity_string(options::XML_INFINITY) .build_unchecked() }; const_assert!(XML.is_valid()); /// Number format for a SQLite literal floating-point number. #[rustfmt::skip] pub const SQLITE: Options = unsafe { Options::builder() .nan_string(options::SQLITE) .inf_string(options::SQLITE) .infinity_string(options::SQLITE) .build_unchecked() }; const_assert!(SQLITE.is_valid()); /// Number format for a PostgreSQL literal floating-point number. #[rustfmt::skip] pub const POSTGRESQL: Options = unsafe { Options::builder() .nan_string(options::POSTGRESQL) .inf_string(options::POSTGRESQL) .infinity_string(options::POSTGRESQL) .build_unchecked() }; const_assert!(POSTGRESQL.is_valid()); /// Number format for a MySQL literal floating-point number. #[rustfmt::skip] pub const MYSQL: Options = unsafe { Options::builder() .nan_string(options::MYSQL) .inf_string(options::MYSQL) .infinity_string(options::MYSQL) .build_unchecked() }; const_assert!(MYSQL.is_valid()); /// Number format for a MongoDB literal floating-point number. #[rustfmt::skip] pub const MONGODB: Options = unsafe { Options::builder() .inf_string(options::MONGODB_INF) .infinity_string(options::MONGODB_INFINITY) .build_unchecked() }; const_assert!(MONGODB.is_valid()); lexical-parse-float-0.8.5/src/parse.rs000064400000000000000000001005510072674642500157730ustar 00000000000000//! Shared trait and methods for parsing floats. //! //! This is adapted from [fast-float-rust](https://github.com/aldanor/fast-float-rust), //! a port of [fast_float](https://github.com/fastfloat/fast_float) to Rust. #![doc(hidden)] #[cfg(any(feature = "compact", feature = "radix"))] use crate::bellerophon::bellerophon; #[cfg(feature = "power-of-two")] use crate::binary::{binary, slow_binary}; use crate::float::{extended_to_float, ExtendedFloat80, LemireFloat}; #[cfg(not(feature = "compact"))] use crate::lemire::lemire; use crate::number::Number; use crate::options::Options; use crate::shared; use crate::slow::slow_radix; #[cfg(not(feature = "compact"))] use lexical_parse_integer::algorithm; #[cfg(feature = "f16")] use lexical_util::bf16::bf16; use lexical_util::digit::{char_to_digit_const, char_to_valid_digit_const}; use lexical_util::error::Error; #[cfg(feature = "f16")] use lexical_util::f16::f16; use lexical_util::format::NumberFormat; use lexical_util::iterator::{AsBytes, Bytes, BytesIter}; use lexical_util::result::Result; use lexical_util::step::u64_step; // API // --- /// Check f radix is a power-of-2. #[cfg(feature = "power-of-two")] macro_rules! is_power_two { ($radix:expr) => { matches!($radix, 2 | 4 | 8 | 16 | 32) }; } /// Check if the radix is valid and error otherwise macro_rules! check_radix { ($format:ident) => {{ let format = NumberFormat::<{ $format }> {}; #[cfg(feature = "power-of-two")] { if format.radix() != format.exponent_base() { let valid_radix = matches!( (format.radix(), format.exponent_base()), (4, 2) | (8, 2) | (16, 2) | (32, 2) | (16, 4) ); if !valid_radix { return Err(Error::InvalidRadix); } } } #[cfg(not(feature = "power-of-two"))] { if format.radix() != format.exponent_base() { return Err(Error::InvalidRadix); } } }}; } /// Parse integer trait, implemented in terms of the optimized back-end. pub trait ParseFloat: LemireFloat { /// Forward complete parser parameters to the backend. #[cfg_attr(not(feature = "compact"), inline(always))] fn parse_complete(bytes: &[u8], options: &Options) -> Result { check_radix!(FORMAT); parse_complete::(bytes, options) } /// Forward partial parser parameters to the backend. #[cfg_attr(not(feature = "compact"), inline(always))] fn parse_partial(bytes: &[u8], options: &Options) -> Result<(Self, usize)> { check_radix!(FORMAT); parse_partial::(bytes, options) } /// Forward complete parser parameters to the backend, using only the fast path. #[cfg_attr(not(feature = "compact"), inline(always))] fn fast_path_complete(bytes: &[u8], options: &Options) -> Result { check_radix!(FORMAT); fast_path_complete::(bytes, options) } /// Forward partial parser parameters to the backend, using only the fast path. #[cfg_attr(not(feature = "compact"), inline(always))] fn fast_path_partial( bytes: &[u8], options: &Options, ) -> Result<(Self, usize)> { check_radix!(FORMAT); fast_path_partial::(bytes, options) } } macro_rules! parse_float_impl { ($($t:ty)*) => ($( impl ParseFloat for $t {} )*) } parse_float_impl! { f32 f64 } #[cfg(feature = "f16")] macro_rules! parse_float_as_f32 { ($($t:ty)*) => ($( impl ParseFloat for $t { #[cfg_attr(not(feature = "compact"), inline(always))] fn parse_complete(bytes: &[u8], options: &Options) -> Result { Ok(Self::from_f32(parse_complete::(bytes, options)?)) } #[cfg_attr(not(feature = "compact"), inline(always))] fn parse_partial(bytes: &[u8], options: &Options) -> Result<(Self, usize)> { let (float, count) = parse_partial::(bytes, options)?; Ok((Self::from_f32(float), count)) } #[cfg_attr(not(feature = "compact"), inline(always))] fn fast_path_complete(bytes: &[u8], options: &Options) -> Result { Ok(Self::from_f32(fast_path_complete::(bytes, options)?)) } #[cfg_attr(not(feature = "compact"), inline(always))] fn fast_path_partial(bytes: &[u8], options: &Options) -> Result<(Self, usize)> { let (float, count) = fast_path_partial::(bytes, options)?; Ok((Self::from_f32(float), count)) } } )*) } #[cfg(feature = "f16")] parse_float_as_f32! { bf16 f16 } // PARSE // ----- // NOTE: // The partial and complete parsers are done separately because it provides // minor optimizations when parsing invalid input, and the logic is slightly // different internally. Most of the code is reshared, so the duplicated // code is only like 30 lines. macro_rules! parse_mantissa_sign { ($byte:ident, $format:ident) => {{ match $byte.integer_iter().peek() { Some(&b'+') if !$format.no_positive_mantissa_sign() => (false, 1), Some(&b'+') if $format.no_positive_mantissa_sign() => { return Err(Error::InvalidPositiveSign($byte.cursor())); }, Some(&b'-') => (true, 1), Some(_) if $format.required_mantissa_sign() => { return Err(Error::MissingSign($byte.cursor())); }, _ => (false, 0), } }}; } macro_rules! parse_exponent_sign { ($byte:ident, $format:ident) => {{ match $byte.integer_iter().peek() { Some(&b'+') if !$format.no_positive_exponent_sign() => (false, 1), Some(&b'+') if $format.no_positive_exponent_sign() => { return Err(Error::InvalidPositiveExponentSign($byte.cursor())); }, Some(&b'-') => (true, 1), Some(_) if $format.required_mantissa_sign() => { return Err(Error::MissingExponentSign($byte.cursor())); }, _ => (false, 0), } }}; } /// Utility to extract the result and handle any errors from parsing a `Number`. macro_rules! parse_number { ( $format:ident, $byte:ident, $is_negative:ident, $options:ident, $parse_normal:ident, $parse_special:ident ) => {{ match $parse_normal::<$format>($byte.clone(), $is_negative, $options) { Ok(n) => n, Err(e) => { if let Some(value) = $parse_special::<_, $format>($byte.clone(), $is_negative, $options) { return Ok(value); } else { return Err(e); } }, } }}; } /// Convert extended float to native. macro_rules! to_native { ($type:ident, $fp:ident, $is_negative:ident) => {{ let mut float = extended_to_float::<$type>($fp); if $is_negative { float = -float; } float }}; } /// Parse a float from bytes using a complete parser. pub fn parse_complete( bytes: &[u8], options: &Options, ) -> Result { let format = NumberFormat::<{ FORMAT }> {}; let mut byte = bytes.bytes::<{ FORMAT }>(); let (is_negative, shift) = parse_mantissa_sign!(byte, format); // SAFETY: safe since we shift at most one for a parsed sign byte. unsafe { byte.step_by_unchecked(shift) }; if byte.integer_iter().is_consumed() { return Err(Error::Empty(byte.cursor())); } // Parse our a small representation of our number. let num = parse_number!(FORMAT, byte, is_negative, options, parse_number, parse_special); // Try the fast-path algorithm. if let Some(value) = num.try_fast_path::<_, FORMAT>() { return Ok(value); } // Now try the moderate path algorithm. let mut fp = moderate_path::(&num, options.lossy()); // Unable to correctly round the float using the fast or moderate algorithms. // Fallback to a slower, but always correct algorithm. If we have // lossy, we can't be here. if fp.exp < 0 { debug_assert!(!options.lossy()); // Undo the invalid extended float biasing. fp.exp -= shared::INVALID_FP; fp = slow_path::(num, fp); } // Convert to native float and return result. Ok(to_native!(F, fp, is_negative)) } /// Parse a float using only the fast path as a complete parser. pub fn fast_path_complete( bytes: &[u8], options: &Options, ) -> Result { let format = NumberFormat::<{ FORMAT }> {}; let mut byte = bytes.bytes::<{ FORMAT }>(); let (is_negative, shift) = parse_mantissa_sign!(byte, format); // SAFETY: safe since we shift at most one for a parsed sign byte. unsafe { byte.step_by_unchecked(shift) }; if byte.integer_iter().is_consumed() { return Err(Error::Empty(byte.cursor())); } // Parse our a small representation of our number. let num = parse_number!(FORMAT, byte, is_negative, options, parse_number, parse_special); Ok(num.force_fast_path::<_, FORMAT>()) } /// Parse a float from bytes using a partial parser. pub fn parse_partial( bytes: &[u8], options: &Options, ) -> Result<(F, usize)> { let format = NumberFormat::<{ FORMAT }> {}; let mut byte = bytes.bytes::<{ FORMAT }>(); let (is_negative, shift) = parse_mantissa_sign!(byte, format); // SAFETY: safe since we shift at most one for a parsed sign byte. unsafe { byte.step_by_unchecked(shift) }; if byte.integer_iter().is_consumed() { return Err(Error::Empty(byte.cursor())); } // Parse our a small representation of our number. let (num, count) = parse_number!( FORMAT, byte, is_negative, options, parse_partial_number, parse_partial_special ); // Try the fast-path algorithm. if let Some(value) = num.try_fast_path::<_, FORMAT>() { return Ok((value, count)); } // Now try the moderate path algorithm. let mut fp = moderate_path::(&num, options.lossy()); // Unable to correctly round the float using the fast or moderate algorithms. // Fallback to a slower, but always correct algorithm. If we have // lossy, we can't be here. if fp.exp < 0 { debug_assert!(!options.lossy()); // Undo the invalid extended float biasing. fp.exp -= shared::INVALID_FP; fp = slow_path::(num, fp); } // Convert to native float and return result. Ok((to_native!(F, fp, is_negative), count)) } /// Parse a float using only the fast path as a partial parser. pub fn fast_path_partial( bytes: &[u8], options: &Options, ) -> Result<(F, usize)> { let format = NumberFormat::<{ FORMAT }> {}; let mut byte = bytes.bytes::<{ FORMAT }>(); let (is_negative, shift) = parse_mantissa_sign!(byte, format); // SAFETY: safe since we shift at most one for a parsed sign byte. unsafe { byte.step_by_unchecked(shift) }; if byte.integer_iter().is_consumed() { return Err(Error::Empty(byte.cursor())); } // Parse our a small representation of our number. let (num, count) = parse_number!( FORMAT, byte, is_negative, options, parse_partial_number, parse_partial_special ); Ok((num.force_fast_path::<_, FORMAT>(), count)) } // PATHS // ----- /// Wrapper for different moderate-path algorithms. /// A return exponent of `-1` indicates an invalid value. #[inline] pub fn moderate_path( num: &Number, lossy: bool, ) -> ExtendedFloat80 { #[cfg(feature = "compact")] { #[cfg(feature = "power-of-two")] { let format = NumberFormat::<{ FORMAT }> {}; if is_power_two!(format.mantissa_radix()) { // Implement the power-of-two backends. binary::(num, lossy) } else { bellerophon::(num, lossy) } } #[cfg(not(feature = "power-of-two"))] { bellerophon::(num, lossy) } } #[cfg(not(feature = "compact"))] { #[cfg(feature = "radix")] { let format = NumberFormat::<{ FORMAT }> {}; let radix = format.mantissa_radix(); if radix == 10 { lemire::(num, lossy) } else if is_power_two!(radix) { // Implement the power-of-two backends. binary::(num, lossy) } else { bellerophon::(num, lossy) } } #[cfg(all(feature = "power-of-two", not(feature = "radix")))] { let format = NumberFormat::<{ FORMAT }> {}; let radix = format.mantissa_radix(); debug_assert!(matches!(radix, 2 | 4 | 8 | 10 | 16 | 32)); if radix == 10 { lemire::(num, lossy) } else { // Implement the power-of-two backends. binary::(num, lossy) } } #[cfg(not(feature = "power-of-two"))] { lemire::(num, lossy) } } } /// Invoke the slow path. /// At this point, the float string has already been validated. #[inline] pub fn slow_path( num: Number, fp: ExtendedFloat80, ) -> ExtendedFloat80 { #[cfg(not(feature = "power-of-two"))] { slow_radix::(num, fp) } #[cfg(feature = "power-of-two")] { let format = NumberFormat::<{ FORMAT }> {}; if is_power_two!(format.mantissa_radix()) { slow_binary::(num) } else { slow_radix::(num, fp) } } } // NUMBER // ------ /// Parse a partial, non-special floating point number. /// /// This creates a representation of the float as the /// significant digits and the decimal exponent. #[inline] #[allow(clippy::collapsible_if)] pub fn parse_partial_number<'a, const FORMAT: u128>( mut byte: Bytes<'a, FORMAT>, is_negative: bool, options: &Options, ) -> Result<(Number<'a>, usize)> { // NOTE: // There are no satisfactory optimizations to reduce the number // of multiplications for very long input strings, but this will // be a small fraction of the performance penalty anyway. // // We've tried: // - checking for explicit overflow, via `overflowing_mul`. // - counting the max number of steps. // - subslicing the string, and only processing the first `step` digits. // - pre-computing the maximum power, and only adding until then. // // All of these lead to substantial performance penalty. // If we pre-parse the string, then only process it then, we // get a performance penalty of ~2.5x (20ns to 50ns) for common // floats, an unacceptable cost, while only improving performance // for rare floats 5-25% (9.3µs to 7.5µs for denormal with 6400 // digits, and 7.8µs to 7.4µs for large floats with 6400 digits). // // The performance cost is **almost** entirely in this function, // but additional branching **does** not improve performance, // and pre-tokenization is a recipe for failure. For halfway // cases with smaller numbers of digits, the majority of the // performance cost is in the big integer arithmetic (`pow` and // `parse_mantissa`), which suggests few optimizations can or should // be made. // Config options let format = NumberFormat::<{ FORMAT }> {}; let decimal_point = options.decimal_point(); let exponent_character = options.exponent(); debug_assert!(format.is_valid()); debug_assert!(!byte.is_done()); let bits_per_digit = shared::log2(format.mantissa_radix()) as i64; let bits_per_base = shared::log2(format.exponent_base()) as i64; // INTEGER // Check to see if we have a valid base prefix. let base_prefix = format.base_prefix(); let mut is_prefix = false; let mut iter = byte.integer_iter(); if cfg!(feature = "format") && base_prefix != 0 && iter.peek() == Some(&b'0') { // SAFETY: safe since `byte.len() >= 1`. unsafe { iter.step_unchecked() }; // Check to see if the next character is the base prefix. // We must have a format like `0x`, `0d`, `0o`. Note: if let Some(&c) = iter.peek() { is_prefix = if format.case_sensitive_base_prefix() { c == base_prefix } else { c.to_ascii_lowercase() == base_prefix.to_ascii_lowercase() }; if is_prefix { // SAFETY: safe since `byte.len() >= 1`. unsafe { iter.step_unchecked() }; if iter.is_done() { return Err(Error::Empty(iter.cursor())); } } } } // Parse our integral digits. let mut mantissa = 0_u64; let start = byte.clone(); #[cfg(not(feature = "compact"))] parse_8digits::<_, FORMAT>(byte.integer_iter(), &mut mantissa); parse_digits::<_, _, FORMAT>(byte.integer_iter(), |digit| { mantissa = mantissa.wrapping_mul(format.radix() as _).wrapping_add(digit as _); }); let mut n_digits = byte.current_count() - start.current_count(); if cfg!(feature = "format") && format.required_integer_digits() && n_digits == 0 { return Err(Error::EmptyInteger(byte.cursor())); } // Store the integer digits for slow-path algorithms. // SAFETY: safe, since `n_digits <= start.as_slice().len()`. debug_assert!(n_digits <= start.as_slice().len()); let integer_digits = unsafe { start.as_slice().get_unchecked(..n_digits) }; // Check if integer leading zeros are disabled. if cfg!(feature = "format") && !is_prefix && format.no_float_leading_zeros() { if integer_digits.len() > 1 && integer_digits.get(0) == Some(&b'0') { return Err(Error::InvalidLeadingZeros(start.cursor())); } } // FRACTION // Handle decimal point and digits afterwards. let mut n_after_dot = 0; let mut exponent = 0_i64; let mut implicit_exponent: i64; let int_end = n_digits as i64; let mut fraction_digits = None; if byte.first_is(decimal_point) { // SAFETY: s cannot be empty due to first_is unsafe { byte.step_unchecked() }; let before = byte.clone(); #[cfg(not(feature = "compact"))] parse_8digits::<_, FORMAT>(byte.fraction_iter(), &mut mantissa); parse_digits::<_, _, FORMAT>(byte.fraction_iter(), |digit| { mantissa = mantissa.wrapping_mul(format.radix() as _).wrapping_add(digit as _); }); n_after_dot = byte.current_count() - before.current_count(); // Store the fraction digits for slow-path algorithms. // SAFETY: safe, since `n_after_dot <= before.as_slice().len()`. debug_assert!(n_after_dot <= before.as_slice().len()); fraction_digits = Some(unsafe { before.as_slice().get_unchecked(..n_after_dot) }); // Calculate the implicit exponent: the number of digits after the dot. implicit_exponent = -(n_after_dot as i64); if format.mantissa_radix() == format.exponent_base() { exponent = implicit_exponent; } else { debug_assert!(bits_per_digit % bits_per_base == 0); exponent = implicit_exponent * bits_per_digit / bits_per_base; }; if cfg!(feature = "format") && format.required_fraction_digits() && n_after_dot == 0 { return Err(Error::EmptyFraction(byte.cursor())); } } n_digits += n_after_dot; if format.required_mantissa_digits() && n_digits == 0 { return Err(Error::EmptyMantissa(byte.cursor())); } // EXPONENT // Handle scientific notation. let mut explicit_exponent = 0_i64; let is_exponent = if cfg!(feature = "format") && format.case_sensitive_exponent() { byte.first_is(exponent_character) } else { byte.case_insensitive_first_is(exponent_character) }; if is_exponent { // Check float format syntax checks. if cfg!(feature = "format") { if format.no_exponent_notation() { return Err(Error::InvalidExponent(byte.cursor())); } // Check if we have no fraction but we required exponent notation. if format.no_exponent_without_fraction() && fraction_digits.is_none() { return Err(Error::ExponentWithoutFraction(byte.cursor())); } } // SAFETY: byte cannot be empty due to first_is unsafe { byte.step_unchecked() }; let (is_negative, shift) = parse_exponent_sign!(byte, format); // SAFETY: safe since we shift at most one for a parsed sign byte. unsafe { byte.step_by_unchecked(shift) }; if cfg!(feature = "format") && format.required_exponent_sign() && shift == 0 { return Err(Error::MissingExponentSign(byte.cursor())); } let before = byte.current_count(); parse_digits::<_, _, FORMAT>(byte.exponent_iter(), |digit| { if explicit_exponent < 0x10000000 { explicit_exponent *= format.radix() as i64; explicit_exponent += digit as i64; } }); if format.required_exponent_digits() && byte.current_count() - before == 0 { return Err(Error::EmptyExponent(byte.cursor())); } // Handle our sign, and get the explicit part of the exponent. explicit_exponent = if is_negative { -explicit_exponent } else { explicit_exponent }; exponent += explicit_exponent; } else if cfg!(feature = "format") && format.required_exponent_notation() { return Err(Error::MissingExponent(byte.cursor())); } // Check to see if we have a valid base suffix. // We've already trimmed any leading digit separators here, so we can be safe // that the first character **is not** a digit separator. let base_suffix = format.base_suffix(); if cfg!(feature = "format") && base_suffix != 0 { let is_suffix = if cfg!(feature = "format") && format.case_sensitive_base_suffix() { byte.first_is(base_suffix) } else { byte.case_insensitive_first_is(base_suffix) }; if is_suffix { // SAFETY: safe since `byte.len() >= 1`. unsafe { byte.step_unchecked() }; } } // CHECK OVERFLOW // Get the number of parsed digits (total), and redo if we had overflow. let end = byte.cursor(); let mut step = u64_step(format.radix()); let mut many_digits = false; if cfg!(feature = "format") && !format.required_mantissa_digits() && n_digits == 0 { exponent = 0; } if n_digits <= step { return Ok(( Number { exponent, mantissa, is_negative, many_digits: false, integer: integer_digits, fraction: fraction_digits, }, end, )); } // Check for leading zeros, and to see if we had a false overflow. n_digits -= step; let mut zeros = start.clone(); let mut zeros_integer = zeros.integer_iter(); while zeros_integer.peek_is(b'0') { n_digits = n_digits.saturating_sub(1); // SAFETY: safe since zeros cannot be empty due to peek_is unsafe { zeros_integer.step_unchecked() }; } if zeros.first_is(decimal_point) { // SAFETY: safe since zeros cannot be empty due to first_is unsafe { zeros.step_unchecked() }; } let mut zeros_fraction = zeros.fraction_iter(); while zeros_fraction.peek_is(b'0') { n_digits = n_digits.saturating_sub(1); // SAFETY: safe since zeros cannot be empty due to peek_is unsafe { zeros_fraction.step_unchecked() }; } // OVERFLOW // Now, check if we explicitly overflowed. if n_digits > 0 { // Have more than 19 significant digits, so we overflowed. many_digits = true; mantissa = 0; let mut integer = integer_digits.bytes::<{ FORMAT }>(); // Skip leading zeros, so we can use the step properly. let mut integer_iter = integer.integer_iter(); integer_iter.skip_zeros(); parse_u64_digits::<_, FORMAT>(integer_iter, &mut mantissa, &mut step); implicit_exponent = if step == 0 { // Filled our mantissa with just the integer. int_end - integer.current_count() as i64 } else { // We know this can't be a None since we had more than 19 // digits previously, so we overflowed a 64-bit integer, // but parsing only the integral digits produced less // than 19 digits. That means we must have a decimal // point, and at least 1 fractional digit. let mut fraction = fraction_digits.unwrap().bytes::<{ FORMAT }>(); let mut fraction_iter = fraction.fraction_iter(); // Skip leading zeros, so we can use the step properly. if mantissa == 0 { fraction_iter.skip_zeros(); } parse_u64_digits::<_, FORMAT>(fraction_iter, &mut mantissa, &mut step); -(fraction.current_count() as i64) }; if format.mantissa_radix() == format.exponent_base() { exponent = implicit_exponent; } else { debug_assert!(bits_per_digit % bits_per_base == 0); exponent = implicit_exponent * bits_per_digit / bits_per_base; }; // Add back the explicit exponent. exponent += explicit_exponent; } Ok(( Number { exponent, mantissa, is_negative, many_digits, integer: integer_digits, fraction: fraction_digits, }, end, )) } /// Try to parse a non-special floating point number. #[inline] pub fn parse_number<'a, const FORMAT: u128>( byte: Bytes<'a, FORMAT>, is_negative: bool, options: &Options, ) -> Result> { let length = byte.length(); let (float, count) = parse_partial_number::(byte, is_negative, options)?; if count == length { Ok(float) } else { Err(Error::InvalidDigit(count)) } } // DIGITS // ------ /// Iteratively parse and consume digits from bytes. #[inline] pub fn parse_digits<'a, Iter, Cb, const FORMAT: u128>(mut iter: Iter, mut cb: Cb) where Iter: BytesIter<'a>, Cb: FnMut(u32), { let format = NumberFormat::<{ FORMAT }> {}; let radix = format.radix(); while let Some(&c) = iter.peek() { match char_to_digit_const(c, radix) { Some(v) => cb(v), None => break, } // SAFETY: iter cannot be empty due to `iter.peek()`. unsafe { iter.step_unchecked() }; } } /// Iteratively parse and consume digits in intervals of 8. #[inline] #[cfg(not(feature = "compact"))] pub fn parse_8digits<'a, Iter, const FORMAT: u128>(mut iter: Iter, mantissa: &mut u64) where Iter: BytesIter<'a>, { let format = NumberFormat::<{ FORMAT }> {}; let radix: u64 = format.radix() as u64; if can_try_parse_8digits!(iter, radix) { let radix2 = radix.wrapping_mul(radix); let radix4 = radix2.wrapping_mul(radix2); let radix8 = radix4.wrapping_mul(radix4); // Can do up to 2 iterations without overflowing, however, for large // inputs, this is much faster than any other alternative. while let Some(v) = algorithm::try_parse_8digits::(&mut iter) { *mantissa = mantissa.wrapping_mul(radix8).wrapping_add(v); } } } /// Iteratively parse and consume digits without overflowing. /// /// # Preconditions /// /// There must be at least `step` digits left in iterator. #[inline] pub fn parse_u64_digits<'a, Iter, const FORMAT: u128>( mut iter: Iter, mantissa: &mut u64, step: &mut usize, ) where Iter: BytesIter<'a>, { let format = NumberFormat::<{ FORMAT }> {}; let radix = format.radix() as u64; // Try to parse 8 digits at a time, if we can. #[cfg(not(feature = "compact"))] if can_try_parse_8digits!(iter, radix) { let radix2 = radix.wrapping_mul(radix); let radix4 = radix2.wrapping_mul(radix2); let radix8 = radix4.wrapping_mul(radix4); while *step > 8 { if let Some(v) = algorithm::try_parse_8digits::(&mut iter) { *mantissa = mantissa.wrapping_mul(radix8).wrapping_add(v); *step -= 8; } else { break; } } } // Parse single digits at a time. while let Some(&c) = iter.peek() { if *step > 0 { let digit = char_to_valid_digit_const(c, radix as u32); *mantissa = *mantissa * radix + digit as u64; *step -= 1; // SAFETY: safe, since `iter` cannot be empty due to `iter.peek()`. unsafe { iter.step_unchecked() }; } else { break; } } } // SPECIAL // ------- /// Determine if the input data matches the special string. /// If there's no match, returns 0. Otherwise, returns the byte's cursor. #[inline] pub fn is_special_eq(mut byte: Bytes, string: &'static [u8]) -> usize { let format = NumberFormat::<{ FORMAT }> {}; if cfg!(feature = "format") && format.case_sensitive_special() { if shared::starts_with(byte.special_iter(), string.iter()) { // Trim the iterator afterwards. byte.special_iter().peek(); return byte.cursor(); } } else if shared::case_insensitive_starts_with(byte.special_iter(), string.iter()) { // Trim the iterator afterwards. byte.special_iter().peek(); return byte.cursor(); } 0 } /// Parse a positive representation of a special, non-finite float. #[inline] pub fn parse_positive_special( byte: Bytes, options: &Options, ) -> Option<(F, usize)> where F: LemireFloat, { let format = NumberFormat::<{ FORMAT }> {}; if cfg!(feature = "format") && format.no_special() { return None; } let cursor = byte.cursor(); let length = byte.length() - cursor; if let Some(nan_string) = options.nan_string() { if length >= nan_string.len() { let count = is_special_eq::(byte.clone(), nan_string); if count != 0 { return Some((F::NAN, count)); } } } if let Some(infinity_string) = options.infinity_string() { if length >= infinity_string.len() { let count = is_special_eq::(byte.clone(), infinity_string); if count != 0 { return Some((F::INFINITY, count)); } } } if let Some(inf_string) = options.inf_string() { if length >= inf_string.len() { let count = is_special_eq::(byte.clone(), inf_string); if count != 0 { return Some((F::INFINITY, count)); } } } None } /// Parse a partial representation of a special, non-finite float. #[inline] pub fn parse_partial_special( byte: Bytes, is_negative: bool, options: &Options, ) -> Option<(F, usize)> where F: LemireFloat, { let (mut float, count) = parse_positive_special::(byte, options)?; if is_negative { float = -float; } Some((float, count)) } /// Try to parse a special, non-finite float. #[inline] pub fn parse_special( byte: Bytes, is_negative: bool, options: &Options, ) -> Option where F: LemireFloat, { let length = byte.length(); if let Some((float, count)) = parse_partial_special::(byte, is_negative, options) { if count == length { return Some(float); } } None } lexical-parse-float-0.8.5/src/shared.rs000064400000000000000000000205220072674642500161260ustar 00000000000000//! Shared utilities and algorithms. #![doc(hidden)] use crate::float::{ExtendedFloat80, RawFloat}; use crate::mask::{lower_n_halfway, lower_n_mask}; #[cfg(feature = "power-of-two")] use lexical_util::format::NumberFormat; use lexical_util::num::AsPrimitive; // 8 DIGIT // ------- /// Check if we can try to parse 8 digits. #[cfg(not(feature = "compact"))] macro_rules! can_try_parse_8digits { ($iter:expr, $radix:expr) => { $iter.is_contiguous() && (cfg!(not(feature = "power-of-two")) || $radix <= 10) }; } // POWER2 // ------ /// Calculate the shift to move the significant digits into place. #[inline(always)] pub fn calculate_shift(power2: i32) -> i32 { let mantissa_shift = 64 - F::MANTISSA_SIZE - 1; if -power2 >= mantissa_shift { -power2 + 1 } else { mantissa_shift } } /// Calculate the biased, binary exponent from the mantissa shift and exponent. #[inline(always)] #[cfg(feature = "power-of-two")] pub fn calculate_power2(exponent: i64, ctlz: u32) -> i32 { let format = NumberFormat::<{ FORMAT }> {}; exponent as i32 * log2(format.exponent_base()) + F::EXPONENT_BIAS - ctlz as i32 } /// Bias for marking an invalid extended float. pub const INVALID_FP: i32 = i16::MIN as i32; // LOG2 // ---- /// Quick log2 that evaluates at compile time for the radix. /// Note that this may produce inaccurate results for other radixes: /// we don't care since it's only called for powers-of-two. #[inline] pub const fn log2(radix: u32) -> i32 { match radix { 2 => 1, 4 => 2, 8 => 3, 16 => 4, 32 => 5, // Fallthrough to 1 for non-power-of-two radixes. _ => 1, } } // STARTS WITH // ----------- /// Check if left iter starts with right iter. /// /// This optimizes decently well, to the following ASM for pure slices: /// /// ```text /// starts_with_slc: /// xor eax, eax /// .LBB0_1: /// cmp rcx, rax /// je .LBB0_2 /// cmp rsi, rax /// je .LBB0_5 /// movzx r8d, byte ptr [rdi + rax] /// lea r9, [rax + 1] /// cmp r8b, byte ptr [rdx + rax] /// mov rax, r9 /// je .LBB0_1 /// .LBB0_5: /// xor eax, eax /// ret /// .LBB0_2: /// mov al, 1 /// ret /// ``` #[cfg_attr(not(feature = "compact"), inline)] pub fn starts_with<'a, 'b, Iter1, Iter2>(mut x: Iter1, mut y: Iter2) -> bool where Iter1: Iterator, Iter2: Iterator, { loop { // Only call `next()` on x if y is not None, otherwise, // we may incorrectly consume an x character. let yi = y.next(); if yi.is_none() { return true; } else if x.next() != yi { return false; } } } /// Check if left iter starts with right iter without case-sensitivity. /// /// This optimizes decently well, to the following ASM for pure slices: /// /// ```text /// case_insensitive_starts_with_slc: /// xor eax, eax /// .LBB1_1: /// cmp rcx, rax /// je .LBB1_2 /// cmp rsi, rax /// je .LBB1_5 /// movzx r8d, byte ptr [rdi + rax] /// xor r8b, byte ptr [rdx + rax] /// add rax, 1 /// test r8b, -33 /// je .LBB1_1 /// .LBB1_5: /// xor eax, eax /// ret /// .LBB1_2: /// mov al, 1 /// ret /// ``` #[cfg_attr(not(feature = "compact"), inline)] pub fn case_insensitive_starts_with<'a, 'b, Iter1, Iter2>(mut x: Iter1, mut y: Iter2) -> bool where Iter1: Iterator, Iter2: Iterator, { // We use a faster optimization here for ASCII letters, which NaN // and infinite strings **must** be. [A-Z] is 0x41-0x5A, while // [a-z] is 0x61-0x7A. Therefore, the xor must be 0 or 32 if they // are case-insensitive equal, but only if at least 1 of the inputs // is an ASCII letter. loop { let yi = y.next(); if yi.is_none() { return true; } let yi = *yi.unwrap(); let is_not_equal = x.next().map_or(true, |&xi| { let xor = xi ^ yi; xor != 0 && xor != 0x20 }); if is_not_equal { return false; } } } // ROUNDING // -------- /// Round an extended-precision float to the nearest machine float. /// /// Shifts the significant digits into place, adjusts the exponent, /// so it can be easily converted to a native float. #[cfg_attr(not(feature = "compact"), inline)] pub fn round(fp: &mut ExtendedFloat80, cb: Cb) where F: RawFloat, Cb: Fn(&mut ExtendedFloat80, i32), { let fp_inf = ExtendedFloat80 { mant: 0, exp: F::INFINITE_POWER, }; // Calculate our shift in significant digits. let mantissa_shift = 64 - F::MANTISSA_SIZE - 1; // Check for a denormal float, if after the shift the exponent is negative. if -fp.exp >= mantissa_shift { // Have a denormal float that isn't a literal 0. // The extra 1 is to adjust for the denormal float, which is // `1 - F::EXPONENT_BIAS`. This works as before, because our // old logic rounded to `F::DENORMAL_EXPONENT` (now 1), and then // checked if `exp == F::DENORMAL_EXPONENT` and no hidden mask // bit was set. Here, we handle that here, rather than later. // // This might round-down to 0, but shift will be at **max** 65, // for halfway cases rounding towards 0. let shift = -fp.exp + 1; debug_assert!(shift <= 65); cb(fp, shift.min(64)); // Check for round-up: if rounding-nearest carried us to the hidden bit. fp.exp = (fp.mant >= F::HIDDEN_BIT_MASK.as_u64()) as i32; return; } // The float is normal, round to the hidden bit. cb(fp, mantissa_shift); // Check if we carried, and if so, shift the bit to the hidden bit. let carry_mask = F::CARRY_MASK.as_u64(); if fp.mant & carry_mask == carry_mask { fp.mant >>= 1; fp.exp += 1; } // Handle if we carried and check for overflow again. if fp.exp >= F::INFINITE_POWER { // Exponent is above largest normal value, must be infinite. *fp = fp_inf; return; } // Remove the hidden bit. fp.mant &= F::MANTISSA_MASK.as_u64(); } /// Shift right N-bytes and round towards a direction. /// /// Callback should take the following parameters: /// 1. is_odd /// 1. is_halfway /// 1. is_above #[cfg_attr(not(feature = "compact"), inline)] pub fn round_nearest_tie_even(fp: &mut ExtendedFloat80, shift: i32, cb: Cb) where // is_odd, is_halfway, is_above Cb: Fn(bool, bool, bool) -> bool, { // Ensure we've already handled denormal values that underflow. debug_assert!(shift <= 64); // Extract the truncated bits using mask. // Calculate if the value of the truncated bits are either above // the mid-way point, or equal to it. // // For example, for 4 truncated bytes, the mask would be 0b1111 // and the midway point would be 0b1000. let mask = lower_n_mask(shift as u64); let halfway = lower_n_halfway(shift as u64); let truncated_bits = fp.mant & mask; let is_above = truncated_bits > halfway; let is_halfway = truncated_bits == halfway; // Bit shift so the leading bit is in the hidden bit. // This optimixes pretty well: // ```text // mov ecx, esi // shr rdi, cl // xor eax, eax // cmp esi, 64 // cmovne rax, rdi // ret // ``` fp.mant = match shift == 64 { true => 0, false => fp.mant >> shift, }; fp.exp += shift; // Extract the last bit after shifting (and determine if it is odd). let is_odd = fp.mant & 1 == 1; // Calculate if we need to roundup. // We need to roundup if we are above halfway, or if we are odd // and at half-way (need to tie-to-even). Avoid the branch here. fp.mant += cb(is_odd, is_halfway, is_above) as u64; } /// Round our significant digits into place, truncating them. #[cfg_attr(not(feature = "compact"), inline)] pub fn round_down(fp: &mut ExtendedFloat80, shift: i32) { // Might have a shift greater than 64 if we have an error. fp.mant = match shift == 64 { true => 0, false => fp.mant >> shift, }; fp.exp += shift; } lexical-parse-float-0.8.5/src/slow.rs000064400000000000000000000700630072674642500156510ustar 00000000000000//! Slow, fallback cases where we cannot unambiguously round a float. //! //! This occurs when we cannot determine the exact representation using //! both the fast path (native) cases nor the Lemire/Bellerophon algorithms, //! and therefore must fallback to a slow, arbitrary-precision representation. #![doc(hidden)] #[cfg(feature = "radix")] use crate::bigint::Bigfloat; use crate::bigint::{Bigint, Limb, LIMB_BITS}; use crate::float::{extended_to_float, ExtendedFloat80, RawFloat}; use crate::limits::{u32_power_limit, u64_power_limit}; use crate::number::Number; use crate::shared; use core::cmp; #[cfg(not(feature = "compact"))] use lexical_parse_integer::algorithm; use lexical_util::digit::char_to_valid_digit_const; #[cfg(feature = "radix")] use lexical_util::digit::digit_to_char_const; use lexical_util::format::NumberFormat; use lexical_util::iterator::{AsBytes, BytesIter}; use lexical_util::num::{AsPrimitive, Integer}; // ALGORITHM // --------- /// Parse the significant digits and biased, binary exponent of a float. /// /// This is a fallback algorithm that uses a big-integer representation /// of the float, and therefore is considerably slower than faster /// approximations. However, it will always determine how to round /// the significant digits to the nearest machine float, allowing /// use to handle near half-way cases. /// /// Near half-way cases are halfway between two consecutive machine floats. /// For example, the float `16777217.0` has a bitwise representation of /// `100000000000000000000000 1`. Rounding to a single-precision float, /// the trailing `1` is truncated. Using round-nearest, tie-even, any /// value above `16777217.0` must be rounded up to `16777218.0`, while /// any value before or equal to `16777217.0` must be rounded down /// to `16777216.0`. These near-halfway conversions therefore may require /// a large number of digits to unambiguously determine how to round. #[inline] pub fn slow_radix( num: Number, fp: ExtendedFloat80, ) -> ExtendedFloat80 { // Ensure our preconditions are valid: // 1. The significant digits are not shifted into place. debug_assert!(fp.mant & (1 << 63) != 0); let format = NumberFormat::<{ FORMAT }> {}; // This assumes the sign bit has already been parsed, and we're // starting with the integer digits, and the float format has been // correctly validated. let sci_exp = scientific_exponent::(&num); // We have 3 major algorithms we use for this: // 1. An algorithm with a finite number of digits and a positive exponent. // 2. An algorithm with a finite number of digits and a negative exponent. // 3. A fallback algorithm with a non-finite number of digits. // In order for a float in radix `b` with a finite number of digits // to have a finite representation in radix `y`, `b` should divide // an integer power of `y`. This means for binary, all even radixes // have finite representations, and all odd ones do not. #[cfg(feature = "radix")] { if let Some(max_digits) = F::max_digits(format.radix()) { // Can use our finite number of digit algorithm. digit_comp::(num, fp, sci_exp, max_digits) } else { // Fallback to infinite digits. byte_comp::(num, fp, sci_exp) } } #[cfg(not(feature = "radix"))] { // Can use our finite number of digit algorithm. let max_digits = F::max_digits(format.radix()).unwrap(); digit_comp::(num, fp, sci_exp, max_digits) } } /// Algorithm that generates the mantissa for a finite representation. /// /// For a positive exponent relative to the significant digits, this /// is just a multiplication by an exponent power. For a negative /// exponent relative to the significant digits, we scale the real /// digits to the theoretical digits for `b` and determine if we /// need to round-up. #[inline] pub fn digit_comp( num: Number, fp: ExtendedFloat80, sci_exp: i32, max_digits: usize, ) -> ExtendedFloat80 { let (bigmant, digits) = parse_mantissa::(num, max_digits); // This can't underflow, since `digits` is at most `max_digits`. let exponent = sci_exp + 1 - digits as i32; if exponent >= 0 { positive_digit_comp::(bigmant, exponent) } else { negative_digit_comp::(bigmant, fp, exponent) } } /// Generate the significant digits with a positive exponent relative to mantissa. pub fn positive_digit_comp( mut bigmant: Bigint, exponent: i32, ) -> ExtendedFloat80 { let format = NumberFormat::<{ FORMAT }> {}; // Simple, we just need to multiply by the power of the radix. // Now, we can calculate the mantissa and the exponent from this. // The binary exponent is the binary exponent for the mantissa // shifted to the hidden bit. bigmant.pow(format.radix(), exponent as u32).unwrap(); // Get the exact representation of the float from the big integer. // hi64 checks **all** the remaining bits after the mantissa, // so it will check if **any** truncated digits exist. let (mant, is_truncated) = bigmant.hi64(); let exp = bigmant.bit_length() as i32 - 64 + F::EXPONENT_BIAS; let mut fp = ExtendedFloat80 { mant, exp, }; // Shift the digits into position and determine if we need to round-up. shared::round::(&mut fp, |f, s| { shared::round_nearest_tie_even(f, s, |is_odd, is_halfway, is_above| { is_above || (is_halfway && is_truncated) || (is_odd && is_halfway) }); }); fp } /// Generate the significant digits with a negative exponent relative to mantissa. /// /// This algorithm is quite simple: we have the significant digits `m1 * b^N1`, /// where `m1` is the bigint mantissa, `b` is the radix, and `N1` is the radix /// exponent. We then calculate the theoretical representation of `b+h`, which /// is `m2 * 2^N2`, where `m2` is the bigint mantissa and `N2` is the binary /// exponent. If we had infinite, efficient floating precision, this would be /// equal to `m1 / b^-N1` and then compare it to `m2 * 2^N2`. /// /// Since we cannot divide and keep precision, we must multiply the other: /// if we want to do `m1 / b^-N1 >= m2 * 2^N2`, we can do /// `m1 >= m2 * b^-N1 * 2^N2` Going to the decimal case, we can show and example /// and simplify this further: `m1 >= m2 * 2^N2 * 10^-N1`. Since we can remove /// a power-of-two, this is `m1 >= m2 * 2^(N2 - N1) * 5^-N1`. Therefore, if /// `N2 - N1 > 0`, we need have `m1 >= m2 * 2^(N2 - N1) * 5^-N1`, otherwise, /// we have `m1 * 2^(N1 - N2) >= m2 * 5^-N1`, where the resulting exponents /// are all positive. /// /// This allows us to compare both floats using integers efficiently /// without any loss of precision. #[allow(clippy::comparison_chain)] pub fn negative_digit_comp( bigmant: Bigint, mut fp: ExtendedFloat80, exponent: i32, ) -> ExtendedFloat80 { // Ensure our preconditions are valid: // 1. The significant digits are not shifted into place. debug_assert!(fp.mant & (1 << 63) != 0); let format = NumberFormat:: {}; let radix = format.radix(); // Get the significant digits and radix exponent for the real digits. let mut real_digits = bigmant; let real_exp = exponent; debug_assert!(real_exp < 0); // Round down our extended-precision float and calculate `b`. let mut b = fp; shared::round::(&mut b, shared::round_down); let b = extended_to_float::(b); // Get the significant digits and the binary exponent for `b+h`. let theor = bh(b); let mut theor_digits = Bigint::from_u64(theor.mant); let theor_exp = theor.exp; // We need to scale the real digits and `b+h` digits to be the same // order. We currently have `real_exp`, in `radix`, that needs to be // shifted to `theor_digits` (since it is negative), and `theor_exp` // to either `theor_digits` or `real_digits` as a power of 2 (since it // may be positive or negative). Try to remove as many powers of 2 // as possible. All values are relative to `theor_digits`, that is, // reflect the power you need to multiply `theor_digits` by. let (binary_exp, halfradix_exp, radix_exp) = match radix.is_even() { // Can remove a power-of-two. // Both are on opposite-sides of equation, can factor out a // power of two. // // Example: 10^-10, 2^-10 -> ( 0, 10, 0) // Example: 10^-10, 2^-15 -> (-5, 10, 0) // Example: 10^-10, 2^-5 -> ( 5, 10, 0) // Example: 10^-10, 2^5 -> (15, 10, 0) true => (theor_exp - real_exp, -real_exp, 0), // Cannot remove a power-of-two. false => (theor_exp, 0, -real_exp), }; if halfradix_exp != 0 { theor_digits.pow(radix / 2, halfradix_exp as u32).unwrap(); } if radix_exp != 0 { theor_digits.pow(radix, radix_exp as u32).unwrap(); } if binary_exp > 0 { theor_digits.pow(2, binary_exp as u32).unwrap(); } else if binary_exp < 0 { real_digits.pow(2, (-binary_exp) as u32).unwrap(); } // Compare our theoretical and real digits and round nearest, tie even. let ord = real_digits.data.cmp(&theor_digits.data); shared::round::(&mut fp, |f, s| { shared::round_nearest_tie_even(f, s, |is_odd, _, _| { // Can ignore `is_halfway` and `is_above`, since those were // calculates using less significant digits. match ord { cmp::Ordering::Greater => true, cmp::Ordering::Less => false, cmp::Ordering::Equal if is_odd => true, cmp::Ordering::Equal => false, } }); }); fp } /// Try to parse 8 digits at a time. #[cfg(not(feature = "compact"))] macro_rules! try_parse_8digits { ( $format:ident, $iter:ident, $value:ident, $count:ident, $counter:ident, $step:ident, $max_digits:ident ) => {{ let format = NumberFormat::<$format> {}; let radix = format.radix() as Limb; // Try 8-digit optimizations. if can_try_parse_8digits!($iter, radix) { let radix2 = radix.wrapping_mul(radix); let radix4 = radix2.wrapping_mul(radix2); let radix8 = radix4.wrapping_mul(radix4); while $step - $counter >= 8 && $max_digits - $count >= 8 { if let Some(v) = algorithm::try_parse_8digits::(&mut $iter) { $value = $value.wrapping_mul(radix8).wrapping_add(v); $counter += 8; $count += 8; } else { break; } } } }}; } /// Add a digit to the temporary value. macro_rules! add_digit { ($c:ident, $radix:ident, $value:ident, $counter:ident, $count:ident) => {{ let digit = char_to_valid_digit_const($c, $radix); $value *= $radix as Limb; $value += digit as Limb; // Increment our counters. $counter += 1; $count += 1; }}; } /// Add a temporary value to our mantissa. macro_rules! add_temporary { // Multiply by the small power and add the native value. (@mul $result:ident, $power:expr, $value:expr) => { $result.data.mul_small($power).unwrap(); $result.data.add_small($value).unwrap(); }; // Add a temporary where we won't read the counter results internally. // // # Safety // // Safe is `counter <= step`, or smaller than the table size. (@end $format:ident, $result:ident, $counter:ident, $value:ident) => { if $counter != 0 { // SAFETY: safe, since `counter <= step`, or smaller than the table size. let small_power = unsafe { f64::int_pow_fast_path($counter, $format.radix()) }; add_temporary!(@mul $result, small_power as Limb, $value); } }; // Add the maximum native value. (@max $format:ident, $result:ident, $counter:ident, $value:ident, $max:ident) => { add_temporary!(@mul $result, $max, $value); $counter = 0; $value = 0; }; } /// Round-up a truncated value. macro_rules! round_up_truncated { ($format:ident, $result:ident, $count:ident) => {{ // Need to round-up. // Can't just add 1, since this can accidentally round-up // values to a halfway point, which can cause invalid results. add_temporary!(@mul $result, $format.radix() as Limb, 1); $count += 1; }}; } /// Check and round-up the fraction if any non-zero digits exist. macro_rules! round_up_nonzero { ($format:ident, $iter:expr, $result:ident, $count:ident) => {{ // NOTE: All digits must be valid. let mut iter = $iter; // First try reading 8-digits at a time. if iter.is_contiguous() { while let Some(value) = iter.read::() { // SAFETY: safe since we have at least 8 bytes in the buffer. unsafe { iter.step_by_unchecked(8) }; if value != 0x3030_3030_3030_3030 { // Have non-zero digits, exit early. round_up_truncated!($format, $result, $count); return ($result, $count); } } } for &digit in iter { if digit != b'0' { round_up_truncated!($format, $result, $count); return ($result, $count); } } }}; } /// Parse the full mantissa into a big integer. /// /// Returns the parsed mantissa and the number of digits in the mantissa. /// The max digits is the maximum number of digits plus one. pub fn parse_mantissa(num: Number, max_digits: usize) -> (Bigint, usize) { let format = NumberFormat:: {}; let radix = format.radix(); // Iteratively process all the data in the mantissa. // We do this via small, intermediate values which once we reach // the maximum number of digits we can process without overflow, // we add the temporary to the big integer. let mut counter: usize = 0; let mut count: usize = 0; let mut value: Limb = 0; let mut result = Bigint::new(); // Now use our pre-computed small powers iteratively. let step = if LIMB_BITS == 32 { u32_power_limit(format.radix()) } else { u64_power_limit(format.radix()) } as usize; let max_native = (format.radix() as Limb).pow(step as u32); // Process the integer digits. let mut integer = num.integer.bytes::(); let mut integer_iter = integer.integer_iter(); integer_iter.skip_zeros(); 'integer: loop { #[cfg(not(feature = "compact"))] try_parse_8digits!(FORMAT, integer_iter, value, count, counter, step, max_digits); // Parse a digit at a time, until we reach step. while counter < step && count < max_digits { if let Some(&c) = integer_iter.next() { add_digit!(c, radix, value, counter, count); } else { break 'integer; } } // Check if we've exhausted our max digits. if count == max_digits { // Need to check if we're truncated, and round-up accordingly. // SAFETY: safe since `counter <= step`. add_temporary!(@end format, result, counter, value); round_up_nonzero!(format, integer_iter, result, count); if let Some(fraction) = num.fraction { let mut fraction = fraction.bytes::(); round_up_nonzero!(format, fraction.fraction_iter(), result, count) } return (result, count); } else { // Add our temporary from the loop. // SAFETY: safe since `counter <= step`. add_temporary!(@max format, result, counter, value, max_native); } } // Process the fraction digits. if let Some(fraction) = num.fraction { let mut fraction = fraction.bytes::(); let mut fraction_iter = fraction.integer_iter(); if count == 0 { // No digits added yet, can skip leading fraction zeros too. fraction_iter.skip_zeros(); } 'fraction: loop { #[cfg(not(feature = "compact"))] try_parse_8digits!(FORMAT, fraction_iter, value, count, counter, step, max_digits); // Parse a digit at a time, until we reach step. while counter < step && count < max_digits { if let Some(&c) = fraction_iter.next() { add_digit!(c, radix, value, counter, count); } else { break 'fraction; } } // Check if we've exhausted our max digits. if count == max_digits { // SAFETY: safe since `counter <= step`. add_temporary!(@end format, result, counter, value); round_up_nonzero!(format, fraction_iter, result, count); return (result, count); } else { // Add our temporary from the loop. // SAFETY: safe since `counter <= step`. add_temporary!(@max format, result, counter, value, max_native); } } } // We will always have a remainder, as long as we entered the loop // once, or counter % step is 0. // SAFETY: safe since `counter <= step`. add_temporary!(@end format, result, counter, value); (result, count) } /// Compare actual integer digits to the theoretical digits. #[cfg(feature = "radix")] macro_rules! integer_compare { ($iter:ident, $num:ident, $den:ident, $radix:ident) => {{ // Compare the integer digits. while !$num.data.is_empty() { // All digits **must** be valid. let actual = match $iter.next() { Some(&v) => v, // Could have hit the decimal point. _ => break, }; let rem = $num.data.quorem(&$den.data) as u32; let expected = digit_to_char_const(rem, $radix); $num.data.mul_small($radix as Limb).unwrap(); if actual < expected { return cmp::Ordering::Less; } else if actual > expected { return cmp::Ordering::Greater; } } // Still have integer digits, check if any are non-zero. if $num.data.is_empty() { for &digit in $iter { if digit != b'0' { return cmp::Ordering::Greater; } } } }}; } /// Compare actual fraction digits to the theoretical digits. #[cfg(feature = "radix")] macro_rules! fraction_compare { ($iter:ident, $num:ident, $den:ident, $radix:ident) => {{ // Compare the fraction digits. // We can only be here if we hit a decimal point. while !$num.data.is_empty() { // All digits **must** be valid. let actual = match $iter.next() { Some(&v) => v, // No more actual digits, or hit the exponent. _ => return cmp::Ordering::Less, }; let rem = $num.data.quorem(&$den.data) as u32; let expected = digit_to_char_const(rem, $radix); $num.data.mul_small($radix as Limb).unwrap(); if actual < expected { return cmp::Ordering::Less; } else if actual > expected { return cmp::Ordering::Greater; } } // Still have fraction digits, check if any are non-zero. for &digit in $iter { if digit != b'0' { return cmp::Ordering::Greater; } } }}; } /// Compare theoretical digits to halfway point from theoretical digits. /// /// Generates a float representing the halfway point, and generates /// theoretical digits as bytes, and compares the generated digits to /// the actual input. /// /// Compares the known string to theoretical digits generated on the /// fly for `b+h`, where a string representation of a float is between /// `b` and `b+u`, where `b+u` is 1 unit in the least-precision. Therefore, /// the string must be close to `b+h`. /// /// Adapted from "Bigcomp: Deciding Truncated, Near Halfway Conversions", /// available [here](https://www.exploringbinary.com/bigcomp-deciding-truncated-near-halfway-conversions/). #[cfg(feature = "radix")] #[allow(clippy::comparison_chain)] pub fn byte_comp( number: Number, mut fp: ExtendedFloat80, sci_exp: i32, ) -> ExtendedFloat80 { // Ensure our preconditions are valid: // 1. The significant digits are not shifted into place. debug_assert!(fp.mant & (1 << 63) != 0); let format = NumberFormat:: {}; // Round down our extended-precision float and calculate `b`. let mut b = fp; shared::round::(&mut b, shared::round_down); let b = extended_to_float::(b); // Calculate `b+h` to create a ratio for our theoretical digits. let theor = Bigfloat::from_float(bh::(b)); // Now, create a scaling factor for the digit count. let mut factor = Bigfloat::from_u32(1); factor.pow(format.radix(), sci_exp.unsigned_abs()).unwrap(); let mut num: Bigfloat; let mut den: Bigfloat; if sci_exp < 0 { // Need to have the basen factor be the numerator, and the fp // be the denominator. Since we assumed that theor was the numerator, // if it's the denominator, we need to multiply it into the numerator. num = factor; num.data *= &theor.data; den = Bigfloat::from_u32(1); den.exp = -theor.exp; } else { num = theor; den = factor; } // Scale the denominator so it has the number of bits // in the radix as the number of leading zeros. let wlz = integral_binary_factor(format.radix()); let nlz = den.leading_zeros().wrapping_sub(wlz) & (32 - 1); if nlz != 0 { den.shl_bits(nlz as usize).unwrap(); den.exp -= nlz as i32; } // Need to scale the numerator or denominator to the same value. // We don't want to shift the denominator, so... let diff = den.exp - num.exp; let shift = diff.unsigned_abs() as usize; if diff < 0 { // Need to shift the numerator left. num.shl(shift).unwrap(); num.exp -= shift as i32; } else if diff > 0 { // Need to shift denominator left, go by a power of LIMB_BITS. // After this, the numerator will be non-normalized, and the // denominator will be normalized. We need to add one to the // quotient,since we're calculating the ceiling of the divmod. let (q, r) = shift.ceil_divmod(LIMB_BITS); let r = -r; if r != 0 { num.shl_bits(r as usize).unwrap(); num.exp -= r; } if q != 0 { den.shl_limbs(q).unwrap(); den.exp -= LIMB_BITS as i32 * q as i32; } } // Compare our theoretical and real digits and round nearest, tie even. let ord = compare_bytes::(number, num, den); shared::round::(&mut fp, |f, s| { shared::round_nearest_tie_even(f, s, |is_odd, _, _| { // Can ignore `is_halfway` and `is_above`, since those were // calculates using less significant digits. match ord { cmp::Ordering::Greater => true, cmp::Ordering::Less => false, cmp::Ordering::Equal if is_odd => true, cmp::Ordering::Equal => false, } }); }); fp } /// Compare digits between the generated values the ratio and the actual view. #[cfg(feature = "radix")] pub fn compare_bytes( number: Number, mut num: Bigfloat, den: Bigfloat, ) -> cmp::Ordering { let format = NumberFormat:: {}; let radix = format.radix(); // Now need to compare the theoretical digits. First, I need to trim // any leading zeros, and will also need to ignore trailing ones. let mut integer = number.integer.bytes::<{ FORMAT }>(); let mut integer_iter = integer.integer_iter(); integer_iter.skip_zeros(); if integer_iter.is_done() { // Cannot be empty, since we must have at least **some** significant digits. let mut fraction = number.fraction.unwrap().bytes::<{ FORMAT }>(); let mut fraction_iter = fraction.fraction_iter(); fraction_iter.skip_zeros(); fraction_compare!(fraction_iter, num, den, radix); } else { integer_compare!(integer_iter, num, den, radix); if let Some(fraction) = number.fraction { let mut fraction = fraction.bytes::<{ FORMAT }>(); let mut fraction_iter = fraction.fraction_iter(); fraction_compare!(fraction_iter, num, den, radix); } else if !num.data.is_empty() { // We had more theoretical digits, but no more actual digits. return cmp::Ordering::Less; } } // Exhausted both, must be equal. cmp::Ordering::Equal } // SCALING // ------- /// Calculate the scientific exponent from a `Number` value. /// Any other attempts would require slowdowns for faster algorithms. #[inline] pub fn scientific_exponent(num: &Number) -> i32 { // This has the significant digits and exponent relative to those // digits: therefore, we just need to scale to mantissa to `[1, radix)`. // This doesn't need to be very fast. let format = NumberFormat:: {}; // Use power reduction to make this faster: we need at least // F::MANTISSA_SIZE bits, so we must have at least radix^4 digits. // IF we're using base 3, we can have at most 11 divisions, and // base 36, at most ~4. So, this is reasonably efficient. let radix = format.radix() as u64; let radix2 = radix * radix; let radix4 = radix2 * radix2; let mut mantissa = num.mantissa; let mut exponent = num.exponent; while mantissa >= radix4 { mantissa /= radix4; exponent += 4; } while mantissa >= radix2 { mantissa /= radix2; exponent += 2; } while mantissa >= radix { mantissa /= radix; exponent += 1; } exponent as i32 } /// Calculate `b` from a a representation of `b` as a float. #[inline] pub fn b(float: F) -> ExtendedFloat80 { ExtendedFloat80 { mant: float.mantissa().as_u64(), exp: float.exponent(), } } /// Calculate `b+h` from a a representation of `b` as a float. #[inline] pub fn bh(float: F) -> ExtendedFloat80 { let fp = b(float); ExtendedFloat80 { mant: (fp.mant << 1) + 1, exp: fp.exp - 1, } } /// Calculate the integral ceiling of the binary factor from a basen number. #[inline] pub const fn integral_binary_factor(radix: u32) -> u32 { match radix { 3 if cfg!(feature = "radix") => 2, 5 if cfg!(feature = "radix") => 3, 6 if cfg!(feature = "radix") => 3, 7 if cfg!(feature = "radix") => 3, 9 if cfg!(feature = "radix") => 4, 10 => 4, 11 if cfg!(feature = "radix") => 4, 12 if cfg!(feature = "radix") => 4, 13 if cfg!(feature = "radix") => 4, 14 if cfg!(feature = "radix") => 4, 15 if cfg!(feature = "radix") => 4, 17 if cfg!(feature = "radix") => 5, 18 if cfg!(feature = "radix") => 5, 19 if cfg!(feature = "radix") => 5, 20 if cfg!(feature = "radix") => 5, 21 if cfg!(feature = "radix") => 5, 22 if cfg!(feature = "radix") => 5, 23 if cfg!(feature = "radix") => 5, 24 if cfg!(feature = "radix") => 5, 25 if cfg!(feature = "radix") => 5, 26 if cfg!(feature = "radix") => 5, 27 if cfg!(feature = "radix") => 5, 28 if cfg!(feature = "radix") => 5, 29 if cfg!(feature = "radix") => 5, 30 if cfg!(feature = "radix") => 5, 31 if cfg!(feature = "radix") => 5, 33 if cfg!(feature = "radix") => 6, 34 if cfg!(feature = "radix") => 6, 35 if cfg!(feature = "radix") => 6, 36 if cfg!(feature = "radix") => 6, // Invalid radix _ => 0, } } lexical-parse-float-0.8.5/src/table.rs000064400000000000000000000003210072674642500157420ustar 00000000000000//! Pre-computed tables for parsing float strings. #![doc(hidden)] // Re-export all the feature-specific files. pub use crate::table_large::*; #[cfg(not(feature = "compact"))] pub use crate::table_small::*; lexical-parse-float-0.8.5/src/table_bellerophon_decimal.rs000064400000000000000000000103630072674642500220200ustar 00000000000000//! Cached exponents for basen values with 80-bit extended floats. //! //! Exact versions of base**n as an extended-precision float, with both //! large and small powers. Use the large powers to minimize the amount //! of compounded error. This is used in the Bellerophon algorithm. //! //! These values were calculated using Python, using the arbitrary-precision //! integer to calculate exact extended-representation of each value. //! These values are all normalized. //! //! These files takes ~30 KB of storage. //! //! Total array storage: //! With radix: ~20 KB: //! 2534 u64 //! //! DO NOT MODIFY: Generated by `etc/bellerophon_table.py` #![cfg(feature = "compact")] #![doc(hidden)] use crate::bellerophon::BellerophonPowers; /// Get Bellerophon powers from radix. #[inline] #[cfg(not(feature = "radix"))] pub const fn bellerophon_powers(_: u32) -> &'static BellerophonPowers { &BASE10_POWERS } // HIGH LEVEL // ---------- pub const BASE10_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE10_SMALL_MANTISSA, large: &BASE10_LARGE_MANTISSA, small_int: &BASE10_SMALL_INT_POWERS, step: BASE10_STEP, bias: BASE10_BIAS, log2: BASE10_LOG2_MULT, log2_shift: BASE10_LOG2_SHIFT, }; // LOW-LEVEL // --------- const BASE10_SMALL_MANTISSA: [u64; 10] = [ 9223372036854775808, // 10^0 11529215046068469760, // 10^1 14411518807585587200, // 10^2 18014398509481984000, // 10^3 11258999068426240000, // 10^4 14073748835532800000, // 10^5 17592186044416000000, // 10^6 10995116277760000000, // 10^7 13743895347200000000, // 10^8 17179869184000000000, // 10^9 ]; const BASE10_LARGE_MANTISSA: [u64; 66] = [ 11555125961253852697, // 10^-350 13451937075301367670, // 10^-340 15660115838168849784, // 10^-330 18230774251475056848, // 10^-320 10611707258198326947, // 10^-310 12353653155963782858, // 10^-300 14381545078898527261, // 10^-290 16742321987285426889, // 10^-280 9745314011399999080, // 10^-270 11345038669416679861, // 10^-260 13207363278391631158, // 10^-250 15375394465392026070, // 10^-240 17899314949046850752, // 10^-230 10418772551374772303, // 10^-220 12129047596099288555, // 10^-210 14120069793541087484, // 10^-200 16437924692338667210, // 10^-190 9568131466127621947, // 10^-180 11138771039116687545, // 10^-170 12967236152753102995, // 10^-160 15095849699286165408, // 10^-150 17573882009934360870, // 10^-140 10229345649675443343, // 10^-130 11908525658859223294, // 10^-120 13863348470604074297, // 10^-110 16139061738043178685, // 10^-100 9394170331095332911, // 10^-90 10936253623915059621, // 10^-80 12731474852090538039, // 10^-70 14821387422376473014, // 10^-60 17254365866976409468, // 10^-50 10043362776618689222, // 10^-40 11692013098647223345, // 10^-30 13611294676837538538, // 10^-20 15845632502852867518, // 10^-10 9223372036854775808, // 10^0 10737418240000000000, // 10^10 12500000000000000000, // 10^20 14551915228366851806, // 10^30 16940658945086006781, // 10^40 9860761315262647567, // 10^50 11479437019748901445, // 10^60 13363823550460978230, // 10^70 15557538194652854267, // 10^80 18111358157653424735, // 10^90 10542197943230523224, // 10^100 12272733663244316382, // 10^110 14287342391028437277, // 10^120 16632655625031838749, // 10^130 9681479787123295682, // 10^140 11270725851789228247, // 10^150 13120851772591970218, // 10^160 15274681817498023410, // 10^170 17782069995880619867, // 10^180 10350527006597618960, // 10^190 12049599325514420588, // 10^200 14027579833653779454, // 10^210 16330252207878254650, // 10^220 9505457831475799117, // 10^230 11065809325636130661, // 10^240 12882297539194266616, // 10^250 14996968138956309548, // 10^260 17458768723248864463, // 10^270 10162340898095201970, // 10^280 11830521861667747109, // 10^290 13772540099066387756, // 10^300 ]; const BASE10_SMALL_INT_POWERS: [u64; 10] = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]; const BASE10_STEP: i32 = 10; const BASE10_BIAS: i32 = 350; const BASE10_LOG2_MULT: i64 = 217706; const BASE10_LOG2_SHIFT: i32 = 16; lexical-parse-float-0.8.5/src/table_bellerophon_radix.rs000064400000000000000000003100000072674642500215200ustar 00000000000000//! Cached exponents for basen values with 80-bit extended floats. //! //! Exact versions of base**n as an extended-precision float, with both //! large and small powers. Use the large powers to minimize the amount //! of compounded error. This is used in the Bellerophon algorithm. //! //! These values were calculated using Python, using the arbitrary-precision //! integer to calculate exact extended-representation of each value. //! These values are all normalized. //! //! These files takes ~30 KB of storage. //! //! Total array storage: //! With radix: ~20 KB: //! 2534 u64 //! //! DO NOT MODIFY: Generated by `etc/bellerophon_table.py` #![cfg(feature = "radix")] #![doc(hidden)] use crate::bellerophon::BellerophonPowers; #[cfg(feature = "compact")] use crate::table_bellerophon_decimal::BASE10_POWERS; /// Get Bellerophon powers from radix. #[inline] pub const fn bellerophon_powers(radix: u32) -> &'static BellerophonPowers { match radix { 3 => &BASE3_POWERS, 5 => &BASE5_POWERS, 6 => &BASE6_POWERS, 7 => &BASE7_POWERS, 9 => &BASE9_POWERS, #[cfg(feature = "compact")] 10 => &BASE10_POWERS, 11 => &BASE11_POWERS, 12 => &BASE12_POWERS, 13 => &BASE13_POWERS, 14 => &BASE14_POWERS, 15 => &BASE15_POWERS, 17 => &BASE17_POWERS, 18 => &BASE18_POWERS, 19 => &BASE19_POWERS, 20 => &BASE20_POWERS, 21 => &BASE21_POWERS, 22 => &BASE22_POWERS, 23 => &BASE23_POWERS, 24 => &BASE24_POWERS, 25 => &BASE25_POWERS, 26 => &BASE26_POWERS, 27 => &BASE27_POWERS, 28 => &BASE28_POWERS, 29 => &BASE29_POWERS, 30 => &BASE30_POWERS, 31 => &BASE31_POWERS, 33 => &BASE33_POWERS, 34 => &BASE34_POWERS, 35 => &BASE35_POWERS, 36 => &BASE36_POWERS, // Fallback if we have an invalid radix. _ => &INVALID_POWERS, } } // HIGH LEVEL // ---------- pub const INVALID_POWERS: BellerophonPowers = BellerophonPowers { small: &[], large: &[], small_int: &[], step: 0, bias: 0, log2: 0, log2_shift: 0, }; pub const BASE3_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE3_SMALL_MANTISSA, large: &BASE3_LARGE_MANTISSA, small_int: &BASE3_SMALL_INT_POWERS, step: BASE3_STEP, bias: BASE3_BIAS, log2: BASE3_LOG2_MULT, log2_shift: BASE3_LOG2_SHIFT, }; pub const BASE5_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE5_SMALL_MANTISSA, large: &BASE5_LARGE_MANTISSA, small_int: &BASE5_SMALL_INT_POWERS, step: BASE5_STEP, bias: BASE5_BIAS, log2: BASE5_LOG2_MULT, log2_shift: BASE5_LOG2_SHIFT, }; pub const BASE6_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE6_SMALL_MANTISSA, large: &BASE6_LARGE_MANTISSA, small_int: &BASE6_SMALL_INT_POWERS, step: BASE6_STEP, bias: BASE6_BIAS, log2: BASE6_LOG2_MULT, log2_shift: BASE6_LOG2_SHIFT, }; pub const BASE7_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE7_SMALL_MANTISSA, large: &BASE7_LARGE_MANTISSA, small_int: &BASE7_SMALL_INT_POWERS, step: BASE7_STEP, bias: BASE7_BIAS, log2: BASE7_LOG2_MULT, log2_shift: BASE7_LOG2_SHIFT, }; pub const BASE9_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE9_SMALL_MANTISSA, large: &BASE9_LARGE_MANTISSA, small_int: &BASE9_SMALL_INT_POWERS, step: BASE9_STEP, bias: BASE9_BIAS, log2: BASE9_LOG2_MULT, log2_shift: BASE9_LOG2_SHIFT, }; pub const BASE11_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE11_SMALL_MANTISSA, large: &BASE11_LARGE_MANTISSA, small_int: &BASE11_SMALL_INT_POWERS, step: BASE11_STEP, bias: BASE11_BIAS, log2: BASE11_LOG2_MULT, log2_shift: BASE11_LOG2_SHIFT, }; pub const BASE12_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE12_SMALL_MANTISSA, large: &BASE12_LARGE_MANTISSA, small_int: &BASE12_SMALL_INT_POWERS, step: BASE12_STEP, bias: BASE12_BIAS, log2: BASE12_LOG2_MULT, log2_shift: BASE12_LOG2_SHIFT, }; pub const BASE13_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE13_SMALL_MANTISSA, large: &BASE13_LARGE_MANTISSA, small_int: &BASE13_SMALL_INT_POWERS, step: BASE13_STEP, bias: BASE13_BIAS, log2: BASE13_LOG2_MULT, log2_shift: BASE13_LOG2_SHIFT, }; pub const BASE14_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE14_SMALL_MANTISSA, large: &BASE14_LARGE_MANTISSA, small_int: &BASE14_SMALL_INT_POWERS, step: BASE14_STEP, bias: BASE14_BIAS, log2: BASE14_LOG2_MULT, log2_shift: BASE14_LOG2_SHIFT, }; pub const BASE15_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE15_SMALL_MANTISSA, large: &BASE15_LARGE_MANTISSA, small_int: &BASE15_SMALL_INT_POWERS, step: BASE15_STEP, bias: BASE15_BIAS, log2: BASE15_LOG2_MULT, log2_shift: BASE15_LOG2_SHIFT, }; pub const BASE17_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE17_SMALL_MANTISSA, large: &BASE17_LARGE_MANTISSA, small_int: &BASE17_SMALL_INT_POWERS, step: BASE17_STEP, bias: BASE17_BIAS, log2: BASE17_LOG2_MULT, log2_shift: BASE17_LOG2_SHIFT, }; pub const BASE18_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE18_SMALL_MANTISSA, large: &BASE18_LARGE_MANTISSA, small_int: &BASE18_SMALL_INT_POWERS, step: BASE18_STEP, bias: BASE18_BIAS, log2: BASE18_LOG2_MULT, log2_shift: BASE18_LOG2_SHIFT, }; pub const BASE19_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE19_SMALL_MANTISSA, large: &BASE19_LARGE_MANTISSA, small_int: &BASE19_SMALL_INT_POWERS, step: BASE19_STEP, bias: BASE19_BIAS, log2: BASE19_LOG2_MULT, log2_shift: BASE19_LOG2_SHIFT, }; pub const BASE20_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE20_SMALL_MANTISSA, large: &BASE20_LARGE_MANTISSA, small_int: &BASE20_SMALL_INT_POWERS, step: BASE20_STEP, bias: BASE20_BIAS, log2: BASE20_LOG2_MULT, log2_shift: BASE20_LOG2_SHIFT, }; pub const BASE21_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE21_SMALL_MANTISSA, large: &BASE21_LARGE_MANTISSA, small_int: &BASE21_SMALL_INT_POWERS, step: BASE21_STEP, bias: BASE21_BIAS, log2: BASE21_LOG2_MULT, log2_shift: BASE21_LOG2_SHIFT, }; pub const BASE22_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE22_SMALL_MANTISSA, large: &BASE22_LARGE_MANTISSA, small_int: &BASE22_SMALL_INT_POWERS, step: BASE22_STEP, bias: BASE22_BIAS, log2: BASE22_LOG2_MULT, log2_shift: BASE22_LOG2_SHIFT, }; pub const BASE23_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE23_SMALL_MANTISSA, large: &BASE23_LARGE_MANTISSA, small_int: &BASE23_SMALL_INT_POWERS, step: BASE23_STEP, bias: BASE23_BIAS, log2: BASE23_LOG2_MULT, log2_shift: BASE23_LOG2_SHIFT, }; pub const BASE24_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE24_SMALL_MANTISSA, large: &BASE24_LARGE_MANTISSA, small_int: &BASE24_SMALL_INT_POWERS, step: BASE24_STEP, bias: BASE24_BIAS, log2: BASE24_LOG2_MULT, log2_shift: BASE24_LOG2_SHIFT, }; pub const BASE25_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE25_SMALL_MANTISSA, large: &BASE25_LARGE_MANTISSA, small_int: &BASE25_SMALL_INT_POWERS, step: BASE25_STEP, bias: BASE25_BIAS, log2: BASE25_LOG2_MULT, log2_shift: BASE25_LOG2_SHIFT, }; pub const BASE26_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE26_SMALL_MANTISSA, large: &BASE26_LARGE_MANTISSA, small_int: &BASE26_SMALL_INT_POWERS, step: BASE26_STEP, bias: BASE26_BIAS, log2: BASE26_LOG2_MULT, log2_shift: BASE26_LOG2_SHIFT, }; pub const BASE27_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE27_SMALL_MANTISSA, large: &BASE27_LARGE_MANTISSA, small_int: &BASE27_SMALL_INT_POWERS, step: BASE27_STEP, bias: BASE27_BIAS, log2: BASE27_LOG2_MULT, log2_shift: BASE27_LOG2_SHIFT, }; pub const BASE28_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE28_SMALL_MANTISSA, large: &BASE28_LARGE_MANTISSA, small_int: &BASE28_SMALL_INT_POWERS, step: BASE28_STEP, bias: BASE28_BIAS, log2: BASE28_LOG2_MULT, log2_shift: BASE28_LOG2_SHIFT, }; pub const BASE29_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE29_SMALL_MANTISSA, large: &BASE29_LARGE_MANTISSA, small_int: &BASE29_SMALL_INT_POWERS, step: BASE29_STEP, bias: BASE29_BIAS, log2: BASE29_LOG2_MULT, log2_shift: BASE29_LOG2_SHIFT, }; pub const BASE30_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE30_SMALL_MANTISSA, large: &BASE30_LARGE_MANTISSA, small_int: &BASE30_SMALL_INT_POWERS, step: BASE30_STEP, bias: BASE30_BIAS, log2: BASE30_LOG2_MULT, log2_shift: BASE30_LOG2_SHIFT, }; pub const BASE31_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE31_SMALL_MANTISSA, large: &BASE31_LARGE_MANTISSA, small_int: &BASE31_SMALL_INT_POWERS, step: BASE31_STEP, bias: BASE31_BIAS, log2: BASE31_LOG2_MULT, log2_shift: BASE31_LOG2_SHIFT, }; pub const BASE33_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE33_SMALL_MANTISSA, large: &BASE33_LARGE_MANTISSA, small_int: &BASE33_SMALL_INT_POWERS, step: BASE33_STEP, bias: BASE33_BIAS, log2: BASE33_LOG2_MULT, log2_shift: BASE33_LOG2_SHIFT, }; pub const BASE34_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE34_SMALL_MANTISSA, large: &BASE34_LARGE_MANTISSA, small_int: &BASE34_SMALL_INT_POWERS, step: BASE34_STEP, bias: BASE34_BIAS, log2: BASE34_LOG2_MULT, log2_shift: BASE34_LOG2_SHIFT, }; pub const BASE35_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE35_SMALL_MANTISSA, large: &BASE35_LARGE_MANTISSA, small_int: &BASE35_SMALL_INT_POWERS, step: BASE35_STEP, bias: BASE35_BIAS, log2: BASE35_LOG2_MULT, log2_shift: BASE35_LOG2_SHIFT, }; pub const BASE36_POWERS: BellerophonPowers = BellerophonPowers { small: &BASE36_SMALL_MANTISSA, large: &BASE36_LARGE_MANTISSA, small_int: &BASE36_SMALL_INT_POWERS, step: BASE36_STEP, bias: BASE36_BIAS, log2: BASE36_LOG2_MULT, log2_shift: BASE36_LOG2_SHIFT, }; // LOW-LEVEL // --------- // BASE3 const BASE3_SMALL_MANTISSA: [u64; 20] = [ 9223372036854775808, // 3^0 13835058055282163712, // 3^1 10376293541461622784, // 3^2 15564440312192434176, // 3^3 11673330234144325632, // 3^4 17509995351216488448, // 3^5 13132496513412366336, // 3^6 9849372385059274752, // 3^7 14774058577588912128, // 3^8 11080543933191684096, // 3^9 16620815899787526144, // 3^10 12465611924840644608, // 3^11 9349208943630483456, // 3^12 14023813415445725184, // 3^13 10517860061584293888, // 3^14 15776790092376440832, // 3^15 11832592569282330624, // 3^16 17748888853923495936, // 3^17 13311666640442621952, // 3^18 9983749980331966464, // 3^19 ]; const BASE3_LARGE_MANTISSA: [u64; 69] = [ 16362187946641408838, // 3^-720 13283319235448605538, // 3^-700 10783800460320302292, // 3^-680 17509230984627012859, // 3^-660 14214523479040558273, // 3^-640 11539780240125690827, // 3^-620 9368342750761260524, // 3^-600 15211008194170796346, // 3^-580 12348756681875770872, // 3^-560 10025094302862174179, // 3^-540 16277349755993950451, // 3^-520 13214445025385558299, // 3^-500 10727886292707736997, // 3^-480 17418445358572088840, // 3^-460 14140820960965941427, // 3^-440 11479946305982273645, // 3^-420 9319767752666157840, // 3^-400 15132138887857638912, // 3^-380 12284728192712064755, // 3^-360 9973114038089604413, // 3^-340 16192951452641260116, // 3^-320 13145927929137795237, // 3^-300 10672262040895386089, // 3^-280 17328130457353990660, // 3^-260 14067500591556283265, // 3^-240 11420422611687500217, // 3^-220 9271444616666914905, // 3^-200 15053678520084183432, // 3^-180 12221031692227883264, // 3^-160 9921403291771844100, // 3^-140 16108990755761097026, // 3^-120 13077766095064811873, // 3^-100 10616926201665464118, // 3^-80 17238283840257358043, // 3^-60 13994560389365007134, // 3^-40 11361207548643088241, // 3^-20 9223372036854775808, // 3^0 14975624970497949696, // 3^20 12157665459056928801, // 3^40 9869960666451650558, // 3^60 16025465396357318008, // 3^80 13009957681126887596, // 3^100 10561877279594392463, // 3^120 17148903079221976570, // 3^140 13921998383219366688, // 3^160 11302299516591361707, // 3^180 18351097428184282358, // 3^200 14897976129740516999, // 3^220 12094627780758213915, // 3^240 9818784771917617934, // 3^260 15942373117198559022, // 3^280 12942500854835305460, // 3^300 10507113787012386253, // 3^320 17059985758777160561, // 3^340 13849812612167175924, // 3^360 11243696923572004730, // 3^380 18255946711954919292, // 3^400 14820729899390519784, // 3^420 12031916953769783440, // 3^440 9767874225166607426, // 3^460 15859711672757234610, // 3^480 12875393793202830082, // 3^500 10452634243963250834, // 3^520 16971529475976476179, // 3^540 13778001125423815423, // 3^560 11185398185879039609, // 3^580 18161289353620602647, // 3^600 14743884191906938838, // 3^620 11969531283362676572, // 3^640 ]; const BASE3_SMALL_INT_POWERS: [u64; 20] = [ 1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721, 129140163, 387420489, 1162261467, ]; const BASE3_STEP: i32 = 20; const BASE3_BIAS: i32 = 720; const BASE3_LOG2_MULT: i64 = 6807362106; const BASE3_LOG2_SHIFT: i32 = 32; // BASE5 const BASE5_SMALL_MANTISSA: [u64; 14] = [ 9223372036854775808, // 5^0 11529215046068469760, // 5^1 14411518807585587200, // 5^2 18014398509481984000, // 5^3 11258999068426240000, // 5^4 14073748835532800000, // 5^5 17592186044416000000, // 5^6 10995116277760000000, // 5^7 13743895347200000000, // 5^8 17179869184000000000, // 5^9 10737418240000000000, // 5^10 13421772800000000000, // 5^11 16777216000000000000, // 5^12 10485760000000000000, // 5^13 ]; const BASE5_LARGE_MANTISSA: [u64; 68] = [ 15492890949478498119, // 5^-504 11008361120075348168, // 5^-490 15643822052986917253, // 5^-476 11115604119273511155, // 5^-462 15796223521069679172, // 5^-448 11223891875338892399, // 5^-434 15950109677957715915, // 5^-420 11333234566249726012, // 5^-406 16105494987428025427, // 5^-392 11443642469137689536, // 5^-378 16262394054163123565, // 5^-364 11555125961253852697, // 5^-350 16420821625123739831, // 5^-336 11667695520944036383, // 5^-322 16580792590934885855, // 5^-308 11781361728633673532, // 5^-294 16742321987285426889, // 5^-280 11896135267822264502, // 5^-266 16905424996341287883, // 5^-252 12012026926087520367, // 5^-238 17070116948172426941, // 5^-224 12129047596099288555, // 5^-210 17236413322193710308, // 5^-196 12247208276643356092, // 5^-182 17404329748619824289, // 5^-168 12366520073655226703, // 5^-154 17573882009934360870, // 5^-140 12486994201263968925, // 5^-126 17745086042373215101, // 5^-112 12608641982846233347, // 5^-98 17917957937422433684, // 5^-84 12731474852090538039, // 5^-70 18092513943330655534, // 5^-56 12855504354071922204, // 5^-42 18268770466636286477, // 5^-28 12980742146337069071, // 5^-14 9223372036854775808, // 5^0 13107200000000000000, // 5^14 9313225746154785156, // 5^28 13234889800848442797, // 5^42 9403954806578300063, // 5^56 13363823550460978230, // 5^70 9495567745759798747, // 5^84 13494013367335069727, // 5^98 9588073174409622174, // 5^112 13625471488026082303, // 5^126 9681479787123295682, // 5^140 13758210268297397763, // 5^154 9775796363198734982, // 5^168 13892242184281734271, // 5^182 9871031767461413346, // 5^196 14027579833653779454, // 5^210 9967194951097567535, // 5^224 14164235936814247246, // 5^238 10064294952495520794, // 5^252 14302223338085469768, // 5^266 10162340898095201970, // 5^280 14441555006918636608, // 5^294 10261342003245940623, // 5^308 14582244039112794984, // 5^322 10361307573072618726, // 5^336 14724303658045725350, // 5^350 10462247003350260393, // 5^364 14867747215916808149, // 5^378 10564169781387141817, // 5^392 15012588195001998509, // 5^406 10667085486916504429, // 5^420 15158840208921026870, // 5^434 ]; const BASE5_SMALL_INT_POWERS: [u64; 14] = [ 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125, ]; const BASE5_STEP: i32 = 14; const BASE5_BIAS: i32 = 504; const BASE5_LOG2_MULT: i64 = 152170; const BASE5_LOG2_SHIFT: i32 = 16; // BASE6 const BASE6_SMALL_MANTISSA: [u64; 12] = [ 9223372036854775808, // 6^0 13835058055282163712, // 6^1 10376293541461622784, // 6^2 15564440312192434176, // 6^3 11673330234144325632, // 6^4 17509995351216488448, // 6^5 13132496513412366336, // 6^6 9849372385059274752, // 6^7 14774058577588912128, // 6^8 11080543933191684096, // 6^9 16620815899787526144, // 6^10 12465611924840644608, // 6^11 ]; const BASE6_LARGE_MANTISSA: [u64; 71] = [ 11172994339528645078, // 6^-444 11325430459582219446, // 6^-432 11479946305982273645, // 6^-420 11636570252986002899, // 6^-408 11795331061968106016, // 6^-396 11956257886702331980, // 6^-384 12119380278715084095, // 6^-372 12284728192712064755, // 6^-360 12452331992078957377, // 6^-348 12622222454457155586, // 6^-336 12794430777395563548, // 6^-324 12968988584079505325, // 6^-312 13145927929137795237, // 6^-300 13325281304529035642, // 6^-288 13507081645508223020, // 6^-276 13691362336674758052, // 6^-264 13878157218102970303, // 6^-252 14067500591556283265, // 6^-240 14259427226786160917, // 6^-228 14453972367916992462, // 6^-216 14651171739918087751, // 6^-204 14851061555163971849, // 6^-192 15053678520084183432, // 6^-180 15259059841903798156, // 6^-168 15467243235475914756, // 6^-156 15678266930207358578, // 6^-144 15892169677078874302, // 6^-132 16108990755761097026, // 6^-120 16328769981827608423, // 6^-108 16551547714066402526, // 6^-96 16777364861891103792, // 6^-84 17006262892853298360, // 6^-72 17238283840257358043, // 6^-60 17473470310879155380, // 6^-48 17711865492790087155, // 6^-36 17953513163287843146, // 6^-24 18198457696935376453, // 6^-12 9223372036854775808, // 6^0 9349208943630483456, // 6^12 9476762676643233792, // 6^24 9606056659007943744, // 6^36 9737114633407288801, // 6^48 9869960666451650558, // 6^60 10004619153098548172, // 6^72 10141114821132365302, // 6^84 10279472735705195138, // 6^96 10419718303939637392, // 6^108 10561877279594392463, // 6^120 10705975767793509530, // 6^132 10852040229820157048, // 6^144 11000097487975795902, // 6^156 11150174730505647564, // 6^168 11302299516591361707, // 6^180 11456499781411800112, // 6^192 11612803841272866179, // 6^204 11771240398807322073, // 6^216 11931838548245548344, // 6^228 12094627780758213915, // 6^240 12259637989871837542, // 6^252 12426899476958235198, // 6^264 12596442956798861450, // 6^276 12768299563225066619, // 6^288 12942500854835305460, // 6^300 13119078820790347231, // 6^312 13298065886687551351, // 6^324 13479494920515287357, // 6^336 13663399238688592583, // 6^348 13849812612167175924, // 6^360 14038769272656891137, // 6^372 14230303918895818486, // 6^384 14424451723026109070, // 6^396 ]; const BASE6_SMALL_INT_POWERS: [u64; 12] = [1, 6, 36, 216, 1296, 7776, 46656, 279936, 1679616, 10077696, 60466176, 362797056]; const BASE6_STEP: i32 = 12; const BASE6_BIAS: i32 = 444; const BASE6_LOG2_MULT: i64 = 11102329402; const BASE6_LOG2_SHIFT: i32 = 32; // BASE7 const BASE7_SMALL_MANTISSA: [u64; 11] = [ 9223372036854775808, // 7^0 16140901064495857664, // 7^1 14123288431433875456, // 7^2 12357877377504641024, // 7^3 10813142705316560896, // 7^4 9461499867151990784, // 7^5 16557624767515983872, // 7^6 14487921671576485888, // 7^7 12676931462629425152, // 7^8 11092315029800747008, // 7^9 9705775651075653632, // 7^10 ]; const BASE7_LARGE_MANTISSA: [u64; 71] = [ 12225664820028455743, // 7^-407 11256958357801915874, // 7^-396 10365007820408367996, // 7^-385 9543731415037814164, // 7^-374 17575058485347314089, // 7^-363 16182490230010039076, // 7^-352 14900262793588950961, // 7^-341 13719633267955538670, // 7^-330 12632551493533408059, // 7^-319 11631605169031861852, // 7^-308 10709969310436274791, // 7^-297 9861359714639799269, // 7^-286 18159980220813419398, // 7^-275 16721065408999761282, // 7^-264 15396163707909854531, // 7^-253 14176241233598532153, // 7^-242 13052979906282242272, // 7^-231 12018720733250263776, // 7^-220 11066411585781870352, // 7^-209 10189559113984709052, // 7^-198 9382184471684205580, // 7^-187 17277565098945522629, // 7^-176 15908568875896010079, // 7^-165 14648045730389016129, // 7^-154 13487400745686688174, // 7^-143 12418720027433908743, // 7^-132 11434716742520575143, // 7^-121 10528681433580712628, // 7^-110 9694436270346269630, // 7^-99 17852585851834022264, // 7^-88 16438027581449061548, // 7^-77 15135552519453149331, // 7^-66 13936279698645574929, // 7^-55 12832031839555071753, // 7^-44 11815279593402393441, // 7^-33 10879090202998704701, // 7^-22 10017080231522506848, // 7^-11 9223372036854775808, // 7^0 16985107389382393856, // 7^11 15639284194331952196, // 7^22 14400097950748064600, // 7^33 13259099228230139701, // 7^44 12208508091080056405, // 7^55 11241161050565762112, // 7^66 10350462220447909415, // 7^77 9530338342721952463, // 7^88 17550394753834620135, // 7^99 16159780741186857313, // 7^110 14879352702091044991, // 7^121 13700379997665963732, // 7^132 12614823765422770599, // 7^143 11615282106028126090, // 7^154 10694939613220642893, // 7^165 9847520902748803399, // 7^176 18134495646931893353, // 7^187 16697600117649658875, // 7^198 15374557700263623520, // 7^209 14156347188413069088, // 7^220 13034662175384360011, // 7^231 12001854416615353596, // 7^242 11050881679899153397, // 7^253 10175259727702178785, // 7^264 9369018104186475301, // 7^275 17253318850937371954, // 7^286 15886243791070066478, // 7^297 14627489584451796037, // 7^308 13468473375910191470, // 7^319 12401292376951646786, // 7^330 11418669980349265042, // 7^341 10513906144367477972, // 7^352 9680831708316613461, // 7^363 ]; const BASE7_SMALL_INT_POWERS: [u64; 11] = [1, 7, 49, 343, 2401, 16807, 117649, 823543, 5764801, 40353607, 282475249]; const BASE7_STEP: i32 = 11; const BASE7_BIAS: i32 = 407; const BASE7_LOG2_MULT: i64 = 183983; const BASE7_LOG2_SHIFT: i32 = 16; // BASE9 const BASE9_SMALL_MANTISSA: [u64; 10] = [ 9223372036854775808, // 9^0 10376293541461622784, // 9^1 11673330234144325632, // 9^2 13132496513412366336, // 9^3 14774058577588912128, // 9^4 16620815899787526144, // 9^5 9349208943630483456, // 9^6 10517860061584293888, // 9^7 11832592569282330624, // 9^8 13311666640442621952, // 9^9 ]; const BASE9_LARGE_MANTISSA: [u64; 69] = [ 16362187946641408838, // 9^-360 13283319235448605538, // 9^-350 10783800460320302292, // 9^-340 17509230984627012859, // 9^-330 14214523479040558273, // 9^-320 11539780240125690827, // 9^-310 9368342750761260524, // 9^-300 15211008194170796346, // 9^-290 12348756681875770872, // 9^-280 10025094302862174179, // 9^-270 16277349755993950451, // 9^-260 13214445025385558299, // 9^-250 10727886292707736997, // 9^-240 17418445358572088840, // 9^-230 14140820960965941427, // 9^-220 11479946305982273645, // 9^-210 9319767752666157840, // 9^-200 15132138887857638912, // 9^-190 12284728192712064755, // 9^-180 9973114038089604413, // 9^-170 16192951452641260116, // 9^-160 13145927929137795237, // 9^-150 10672262040895386089, // 9^-140 17328130457353990660, // 9^-130 14067500591556283265, // 9^-120 11420422611687500217, // 9^-110 9271444616666914905, // 9^-100 15053678520084183432, // 9^-90 12221031692227883264, // 9^-80 9921403291771844100, // 9^-70 16108990755761097026, // 9^-60 13077766095064811873, // 9^-50 10616926201665464118, // 9^-40 17238283840257358043, // 9^-30 13994560389365007134, // 9^-20 11361207548643088241, // 9^-10 9223372036854775808, // 9^0 14975624970497949696, // 9^10 12157665459056928801, // 9^20 9869960666451650558, // 9^30 16025465396357318008, // 9^40 13009957681126887596, // 9^50 10561877279594392463, // 9^60 17148903079221976570, // 9^70 13921998383219366688, // 9^80 11302299516591361707, // 9^90 18351097428184282358, // 9^100 14897976129740516999, // 9^110 12094627780758213915, // 9^120 9818784771917617934, // 9^130 15942373117198559022, // 9^140 12942500854835305460, // 9^150 10507113787012386253, // 9^160 17059985758777160561, // 9^170 13849812612167175924, // 9^180 11243696923572004730, // 9^190 18255946711954919292, // 9^200 14820729899390519784, // 9^210 12031916953769783440, // 9^220 9767874225166607426, // 9^230 15859711672757234610, // 9^240 12875393793202830082, // 9^250 10452634243963250834, // 9^260 16971529475976476179, // 9^270 13778001125423815423, // 9^280 11185398185879039609, // 9^290 18161289353620602647, // 9^300 14743884191906938838, // 9^310 11969531283362676572, // 9^320 ]; const BASE9_SMALL_INT_POWERS: [u64; 10] = [1, 9, 81, 729, 6561, 59049, 531441, 4782969, 43046721, 387420489]; const BASE9_STEP: i32 = 10; const BASE9_BIAS: i32 = 360; const BASE9_LOG2_MULT: i64 = 13614724212; const BASE9_LOG2_SHIFT: i32 = 32; // BASE11 const BASE11_SMALL_MANTISSA: [u64; 9] = [ 9223372036854775808, // 11^0 12682136550675316736, // 11^1 17437937757178560512, // 11^2 11988582208060260352, // 11^3 16484300536082857984, // 11^4 11332956618556964864, // 11^5 15582815350515826688, // 11^6 10713185553479630848, // 11^7 14730630136034492416, // 11^8 ]; const BASE11_LARGE_MANTISSA: [u64; 70] = [ 9282833781626869722, // 11^-333 10192597509046958613, // 11^-324 11191522591630754840, // 11^-315 12288347284174558846, // 11^-306 13492666233761944748, // 11^-297 14815014410453217040, // 11^-288 16266959263598494876, // 11^-279 17861201909926315464, // 11^-270 9805844119283264859, // 11^-261 10766865452458105492, // 11^-252 11822071640254585128, // 11^-243 12980693265318349774, // 11^-234 14252865553152120313, // 11^-225 15649717031600177225, // 11^-216 17183466879401827195, // 11^-207 9433765907692842627, // 11^-198 10358321731667433590, // 11^-189 11373488609595385666, // 11^-180 12488146873940825498, // 11^-171 13712047173770907127, // 11^-162 15055895770097238115, // 11^-153 16531448190583591098, // 11^-144 18151612062879235750, // 11^-135 9965280013064351107, // 11^-126 10941926854184612877, // 11^-117 12014289927163860584, // 11^-108 13191749897208336388, // 11^-99 14484606781216284322, // 11^-90 15904170048801172427, // 11^-81 17462857553661839031, // 11^-72 9587152080358667750, // 11^-63 10526740509619734750, // 11^-54 11558413262671798860, // 11^-45 12691195059726361470, // 11^-36 13934995088312952370, // 11^-27 15300693685460773821, // 11^-18 16800237515163846269, // 11^-9 9223372036854775808, // 11^0 10127308218523713536, // 11^9 11119834626984462962, // 11^18 12209633543621683835, // 11^27 13406238156435497652, // 11^36 14720115953107913248, // 11^45 16162760287003157808, // 11^54 17746790917089950882, // 11^63 9743032200637278641, // 11^72 10697897654413860244, // 11^81 11746344656115154606, // 11^90 12897544661339799796, // 11^99 14161567973799797658, // 11^108 15549471836891389165, // 11^117 17073397158676562691, // 11^126 9373337358196117359, // 11^135 10291970884763903381, // 11^144 11300635050781198339, // 11^153 12408153305213523269, // 11^162 13624213838764580644, // 11^171 14959454332853289890, // 11^180 16425555014410689631, // 11^189 18035340830508227153, // 11^198 9901446818303059920, // 11^207 10871837689903097542, // 11^216 11937331677337075986, // 11^225 13107249357401447067, // 11^234 14391824769622635037, // 11^243 15802294940132787091, // 11^252 17350998179329134782, // 11^261 9525741006595626773, // 11^270 10459310846201225147, // 11^279 11484375157976259923, // 11^288 ]; const BASE11_SMALL_INT_POWERS: [u64; 9] = [1, 11, 121, 1331, 14641, 161051, 1771561, 19487171, 214358881]; const BASE11_STEP: i32 = 9; const BASE11_BIAS: i32 = 333; const BASE11_LOG2_MULT: i64 = 226718; const BASE11_LOG2_SHIFT: i32 = 16; // BASE12 const BASE12_SMALL_MANTISSA: [u64; 9] = [ 9223372036854775808, // 12^0 13835058055282163712, // 12^1 10376293541461622784, // 12^2 15564440312192434176, // 12^3 11673330234144325632, // 12^4 17509995351216488448, // 12^5 13132496513412366336, // 12^6 9849372385059274752, // 12^7 14774058577588912128, // 12^8 ]; const BASE12_LARGE_MANTISSA: [u64; 68] = [ 12794430777395563548, // 12^-324 15370653136686821126, // 12^-315 9232805349408163458, // 12^-306 11091876690210014731, // 12^-297 13325281304529035642, // 12^-288 16008393061343079134, // 12^-279 9615881366772943927, // 12^-270 11552086971569327107, // 12^-261 13878157218102970303, // 12^-252 16672593293696335722, // 12^-243 10014851495355986817, // 12^-234 12031391722600823274, // 12^-225 14453972367916992462, // 12^-216 17364351691754770668, // 12^-207 10430375193750279268, // 12^-198 12530583187169601247, // 12^-189 15053678520084183432, // 12^-180 18084811664478575592, // 12^-171 10863139281980340679, // 12^-162 13050486479932803075, // 12^-153 15678266930207358578, // 12^-144 9417582030861555141, // 12^-135 11313859076748534537, // 12^-126 13591960950173425616, // 12^-117 16328769981827608423, // 12^-108 9808324571298608904, // 12^-99 11783279573783601017, // 12^-90 14155901602220618825, // 12^-81 17006262892853298360, // 12^-72 10215279312745101062, // 12^-63 12272176679245716810, // 12^-54 14743240574804287352, // 12^-45 17711865492790087155, // 12^-36 10639118911577981124, // 12^-27 12781358492223474271, // 12^-18 15354948681789223882, // 12^-9 9223372036854775808, // 12^0 11080543933191684096, // 12^9 13311666640442621952, // 12^18 15992037016835457024, // 12^27 9606056659007943744, // 12^36 11540284009964194135, // 12^45 13863977671394362375, // 12^54 16655558624637160317, // 12^63 10004619153098548172, // 12^72 12019099047267988506, // 12^81 14439204501182606065, // 12^90 17346610241502516795, // 12^99 10419718303939637392, // 12^108 12517780479519279956, // 12^117 15038297923484984581, // 12^126 18066334108151547333, // 12^135 10852040229820157048, // 12^144 13037152578341684032, // 12^153 15662248181121787524, // 12^162 9407959928864140132, // 12^171 11302299516591361707, // 12^180 13578073815006577911, // 12^189 16312086602830473207, // 12^198 9798303241073980839, // 12^207 11771240398807322073, // 12^216 14141438279402131370, // 12^225 16988887307951181138, // 12^234 10204842190014742991, // 12^243 12259637989871837542, // 12^252 14728177157876426901, // 12^261 17693768981840924725, // 12^270 10628248744799039348, // 12^279 ]; const BASE12_SMALL_INT_POWERS: [u64; 9] = [1, 12, 144, 1728, 20736, 248832, 2985984, 35831808, 429981696]; const BASE12_STEP: i32 = 9; const BASE12_BIAS: i32 = 324; const BASE12_LOG2_MULT: i64 = 15397296698; const BASE12_LOG2_SHIFT: i32 = 32; // BASE13 const BASE13_SMALL_MANTISSA: [u64; 8] = [ 9223372036854775808, // 13^0 14987979559889010688, // 13^1 12177733392409821184, // 13^2 9894408381332979712, // 13^3 16078413619666092032, // 13^4 13063711065978699776, // 13^5 10614265241107693568, // 13^6 17248181016800002048, // 13^7 ]; const BASE13_LARGE_MANTISSA: [u64; 74] = [ 12711851154623003921, // 13^-312 9657300550123029827, // 13^-304 14673465379822171777, // 13^-296 11147555423761605318, // 13^-288 16937783776246970219, // 13^-280 12867777209673117558, // 13^-272 9775758889423702247, // 13^-264 14853452979012869128, // 13^-256 11284293521111612769, // 13^-248 17145545948207386966, // 13^-240 13025615884242430727, // 13^-232 9895670261906581517, // 13^-224 15035648341334079534, // 13^-216 11422708874734959378, // 13^-208 17355856571645749915, // 13^-200 13185390638896427802, // 13^-192 10017052490761162429, // 13^-184 15220078547640608376, // 13^-176 11562822058185475244, // 13^-168 17568746906366835671, // 13^-160 13347125221972482607, // 13^-152 10139923617799671626, // 13^-144 15406771010966328102, // 13^-136 11704653897376229735, // 13^-128 17784248595614306423, // 13^-120 13510843673109724761, // 13^-112 10264301906138736839, // 13^-104 15595753480598751694, // 13^-96 11848225473675019323, // 13^-88 18002393670774046392, // 13^-80 13676570326822204041, // 13^-72 10390205842913949994, // 13^-64 15787054046203585657, // 13^-56 11993558127037825287, // 13^-48 18223214556135190308, // 13^-40 13844329816115883890, // 13^-32 10517654142027727687, // 13^-24 15980701141999875583, // 13^-16 12140673459180707010, // 13^-8 9223372036854775808, // 13^0 14014147076150001664, // 13^8 10646665746930877456, // 13^16 16176723550986364864, // 13^24 12289593336790602348, // 13^32 9336507724055083356, // 13^40 14186047347943339851, // 13^48 10777259833438283283, // 13^56 16375150409219694755, // 13^64 12440339894775512302, // 13^72 9451031155744840189, // 13^80 14360056182125959135, // 13^88 10909455812579128852, // 13^96 16576011210145081669, // 13^104 12592935539554553092, // 13^112 9566959354269653198, // 13^120 14536199442736950948, // 13^128 11043273333482082198, // 13^136 16779335808980115413, // 13^144 12747402952388364654, // 13^152 9684309550774553205, // 13^160 14714503311068774005, // 13^168 11178732286295870598, // 13^176 16985154427152329948, // 13^184 12903765092750370582, // 13^192 9803099187765169579, // 13^200 14894994289558746218, // 13^208 11315852805145679810, // 13^216 17193497656791206265, // 13^224 13062045201739390598, // 13^232 9923345921700320715, // 13^240 15077699205728270417, // 13^248 11454655271125817073, // 13^256 17404396465275275042, // 13^264 13222266805534112801, // 13^272 ]; const BASE13_SMALL_INT_POWERS: [u64; 8] = [1, 13, 169, 2197, 28561, 371293, 4826809, 62748517]; const BASE13_STEP: i32 = 8; const BASE13_BIAS: i32 = 312; const BASE13_LOG2_MULT: i64 = 15893267571; const BASE13_LOG2_SHIFT: i32 = 32; // BASE14 const BASE14_SMALL_MANTISSA: [u64; 8] = [ 9223372036854775808, // 14^0 16140901064495857664, // 14^1 14123288431433875456, // 14^2 12357877377504641024, // 14^3 10813142705316560896, // 14^4 9461499867151990784, // 14^5 16557624767515983872, // 14^6 14487921671576485888, // 14^7 ]; const BASE14_LARGE_MANTISSA: [u64; 72] = [ 13636466802170654447, // 14^-304 9371223146631740442, // 14^-296 12880143300754023535, // 14^-288 17702928299982570560, // 14^-280 12165767999490239948, // 14^-272 16721065408999761282, // 14^-264 11491014312609104256, // 14^-256 15793659877858943182, // 14^-248 10853684694473876180, // 14^-240 14917691321465419740, // 14^-232 10251703482589146278, // 14^-224 14090306875260685218, // 14^-216 9683110137559136558, // 14^-208 13308811903980028150, // 14^-200 18292105715960495534, // 14^-192 12570661225733134820, // 14^-184 17277565098945522629, // 14^-176 11873450822826176619, // 14^-168 16319294256419936609, // 14^-160 11214910012329090474, // 14^-152 15414172280784786485, // 14^-144 10592894050889065017, // 14^-136 14559251360287507272, // 14^-128 10005377149705503250, // 14^-120 13751747178554400168, // 14^-112 9450445876917551117, // 14^-104 12989029846596759700, // 14^-96 17852585851834022264, // 14^-88 12268615337757900164, // 14^-80 16862422458582420498, // 14^-72 11588157397706317457, // 14^-64 15927176798452085633, // 14^-56 10945439903127358164, // 14^-48 15043802952525257461, // 14^-40 10338369644227094261, // 14^-32 14209423938610553080, // 14^-24 9764969507542378307, // 14^-16 13421322341453983785, // 14^-8 9223372036854775808, // 14^0 12676931462629425152, // 14^8 17423626702474969088, // 14^16 11973826961285400900, // 14^24 16457254800854930971, // 14^32 11309718958523667683, // 14^40 15544481077627229210, // 14^48 10682444579695049354, // 14^56 14682332800738954595, // 14^64 10089960910324183248, // 14^72 13868002115678253630, // 14^80 9530338342721952463, // 14^88 13098836900821174211, // 14^96 18003508583233548621, // 14^104 12372332129971187630, // 14^112 17004974516675479989, // 14^120 11686121713960805382, // 14^128 16061822448435536582, // 14^136 11037970794744924274, // 14^144 15170980709914287138, // 14^152 10425768466889213611, // 14^160 14329547997401095751, // 14^168 9847520902748803399, // 14^176 13534783923074532648, // 14^184 9301344858947275744, // 14^192 12784100090075520076, // 14^200 17570923086015569737, // 14^208 12075051662586407952, // 14^216 16596381640322157656, // 14^224 11405329403461315009, // 14^232 15675891482926176126, // 14^240 10772752153475797540, // 14^248 14806454750802381310, // 14^256 10175259727702178785, // 14^264 ]; const BASE14_SMALL_INT_POWERS: [u64; 8] = [1, 14, 196, 2744, 38416, 537824, 7529536, 105413504]; const BASE14_STEP: i32 = 8; const BASE14_BIAS: i32 = 304; const BASE14_LOG2_MULT: i64 = 249519; const BASE14_LOG2_SHIFT: i32 = 16; // BASE15 const BASE15_SMALL_MANTISSA: [u64; 8] = [ 9223372036854775808, // 15^0 17293822569102704640, // 15^1 16212958658533785600, // 15^2 15199648742375424000, // 15^3 14249670695976960000, // 15^4 13359066277478400000, // 15^5 12524124635136000000, // 15^6 11741366845440000000, // 15^7 ]; const BASE15_LARGE_MANTISSA: [u64; 70] = [ 13601350414362439244, // 15^-296 16232381325359158633, // 15^-288 9686178043528474499, // 15^-280 11559862131178364723, // 15^-272 13795989697002596758, // 15^-264 16464671426007778306, // 15^-256 9824790070164184132, // 15^-248 11725287122380398084, // 15^-240 13993414324420480958, // 15^-232 16700285665596816319, // 15^-224 9965385675239368708, // 15^-216 11893079393347852255, // 15^-208 14193664155710441018, // 15^-200 16939271613521887687, // 15^-192 10107993244338750184, // 15^-184 12063272820543086702, // 15^-176 14396779620362065880, // 15^-168 17181677519910502131, // 15^-160 10252641569253028545, // 15^-152 12235901765210495847, // 15^-144 14602801726422706134, // 15^-136 17427552325363535592, // 15^-128 10399359853791807565, // 15^-120 12411001080313881072, // 15^-112 14811772068776803956, // 15^-104 17676945670836105047, // 15^-96 10548177719679705225, // 15^-88 12588606117573098524, // 15^-80 15023732837543702665, // 15^-72 17929907907659841510, // 15^-64 10699125212536839185, // 15^-56 12768752734601403407, // 15^-48 15238726826595631383, // 15^-40 18186490107708584674, // 15^-32 10852232807944894743, // 15^-24 12951477302144931748, // 15^-16 15456797442197584532, // 15^-8 9223372036854775808, // 15^0 11007531417600000000, // 15^8 13136816711425781250, // 15^16 15677988711770840524, // 15^24 9355361174851030653, // 15^32 11165052395553650442, // 15^40 13324808381590173768, // 15^48 15902345292781888946, // 15^56 9489239115822963265, // 15^64 11324827544542942993, // 15^72 13515490267263203164, // 15^80 16129912481758560891, // 15^88 9625032889090827484, // 15^96 11486889122411397534, // 15^104 13708900866211693796, // 15^112 16360736223435182728, // 15^120 9762769910772315950, // 15^128 11651269848621662268, // 15^136 13905079227116716745, // 15^144 16594863120028599690, // 15^152 9902477989317744010, // 15^160 11818002910861417777, // 15^168 14104064957457333009, // 15^176 16832340440646942057, // 15^184 10044185331124443731, // 15^192 11987121971743813505, // 15^200 14305898231507155361, // 15^208 17073216130833033517, // 15^216 10187920546231501512, // 15^224 12158661175603789420, // 15^232 14510619798445343328, // 15^240 17317538822244368489, // 15^248 10333712654095989060, // 15^256 ]; const BASE15_SMALL_INT_POWERS: [u64; 8] = [1, 15, 225, 3375, 50625, 759375, 11390625, 170859375]; const BASE15_STEP: i32 = 8; const BASE15_BIAS: i32 = 296; const BASE15_LOG2_MULT: i64 = 256042; const BASE15_LOG2_SHIFT: i32 = 16; // BASE17 const BASE17_SMALL_MANTISSA: [u64; 8] = [ 9223372036854775808, // 17^0 9799832789158199296, // 17^1 10412322338480586752, // 17^2 11063092484635623424, // 17^3 11754535764925349888, // 17^4 12489194250233184256, // 17^5 13269768890872758272, // 17^6 14099129446552305664, // 17^7 ]; const BASE17_LARGE_MANTISSA: [u64; 67] = [ 13138227451101932889, // 17^-280 10669358063439695630, // 17^-272 17328852299072967575, // 17^-264 14072501842077846052, // 17^-256 11428068326595325663, // 17^-248 9280563409615280245, // 17^-240 15073213554289220394, // 17^-232 12240731344920942400, // 17^-224 9940514895438007254, // 17^-216 16145087021687770276, // 17^-208 13111183760586542995, // 17^-200 10647396286743453217, // 17^-192 17293182638130712658, // 17^-184 14043535043777936273, // 17^-176 11404544822822581011, // 17^-168 9261460323937079649, // 17^-160 15042186893809203473, // 17^-152 12215535057871861844, // 17^-144 9920053367473418578, // 17^-136 16111854019870470980, // 17^-128 13084195736727816960, // 17^-120 10625479716106730764, // 17^-112 17257586399518441101, // 17^-104 14014627870654357169, // 17^-96 11381069739763987898, // 17^-88 9242396559996829853, // 17^-80 15011224098520048145, // 17^-72 12190390634789334486, // 17^-64 9899633957460570790, // 17^-56 16078689424770850259, // 17^-48 13057263264941664926, // 17^-40 10603608258477502216, // 17^-32 17222063432103834911, // 17^-24 13985780199974813110, // 17^-16 11357642977750484199, // 17^-8 9223372036854775808, // 17^0 14980325036961824768, // 17^8 12165297968916717120, // 17^16 9879256578703990224, // 17^24 16045593095580712414, // 17^32 13030386230879856604, // 17^40 10581781820995279550, // 17^48 17186613585065666435, // 17^56 13956991909259640275, // 17^64 11334264437318166304, // 17^72 18408773347475537258, // 17^80 14949489577945200446, // 17^88 12140256953717114113, // 17^96 9858921144686656932, // 17^104 16012564891781700940, // 17^112 13003564520429535778, // 17^120 10560000310990718510, // 17^128 17151236707893158013, // 17^136 13928262876281286641, // 17^144 11310934019207866827, // 17^152 18370880780077845311, // 17^160 14918717590550882042, // 17^168 12115267482872925081, // 17^176 9838627569069637357, // 17^184 15979604673144701925, // 17^192 12976798019712735820, // 17^200 10538263635985225157, // 17^208 17115932650385342947, // 17^216 13899592979063793037, // 17^224 11287651624364733171, // 17^232 18333066210634546428, // 17^240 14888008944129060322, // 17^248 ]; const BASE17_SMALL_INT_POWERS: [u64; 8] = [1, 17, 289, 4913, 83521, 1419857, 24137569, 410338673]; const BASE17_STEP: i32 = 8; const BASE17_BIAS: i32 = 280; const BASE17_LOG2_MULT: i64 = 267876; const BASE17_LOG2_SHIFT: i32 = 16; // BASE18 const BASE18_SMALL_MANTISSA: [u64; 7] = [ 9223372036854775808, // 18^0 10376293541461622784, // 18^1 11673330234144325632, // 18^2 13132496513412366336, // 18^3 14774058577588912128, // 18^4 16620815899787526144, // 18^5 9349208943630483456, // 18^6 ]; const BASE18_LARGE_MANTISSA: [u64; 75] = [ 14081888293732326968, // 18^-273 16058262627216485544, // 18^-266 18312018475493194258, // 18^-259 10441042983020688038, // 18^-252 11906429509033078491, // 18^-245 13577481089208229636, // 18^-238 15483062540952967857, // 18^-231 17656089820489710741, // 18^-224 10067049297406417285, // 18^-217 11479946305982273645, // 18^-210 13091141534609253262, // 18^-203 14928465875303384176, // 18^-196 17023656248839843776, // 18^-189 9706451905352742522, // 18^-182 11068739548514628780, // 18^-175 12622222454457155586, // 18^-168 14393734624570008992, // 18^-161 16413876176725623927, // 18^-154 9358770957364699929, // 18^-147 10672262040895386089, // 18^-140 12170099854822007158, // 18^-133 13878157218102970303, // 18^-126 15825938165500818674, // 18^-119 18047087583901234911, // 18^-112 10289986187706530766, // 18^-105 11734172092969064177, // 18^-98 13381047573408163051, // 18^-91 15259059841903798156, // 18^-84 17400648639910404101, // 18^-77 9921403291771844100, // 18^-70 11313859076748534537, // 18^-63 12901744183172431346, // 18^-56 14712486856947913357, // 18^-49 16777364861891103792, // 18^-42 9566022877229980327, // 18^-35 10908601492662859386, // 18^-28 12439609234991117453, // 18^-21 14185491882103974832, // 18^-14 16176406841720334625, // 18^-7 9223372036854775808, // 18^0 10517860061584293888, // 18^7 11994027762626592768, // 18^14 13677373641439044901, // 18^21 15596974880318657672, // 18^28 17785989605508530085, // 18^35 10141114821132365302, // 18^42 11564406827668344530, // 18^49 13187455978423603575, // 18^56 15038297923484984581, // 18^63 17148903079221976570, // 18^70 9777864433756263024, // 18^77 11150174730505647564, // 18^84 12715086956165281921, // 18^91 14499632535849309517, // 18^98 16534636719312342666, // 18^105 9427625519601420913, // 18^112 10750780249562856814, // 18^119 12259637989871837542, // 18^126 13980261911578014597, // 18^133 15942373117198559022, // 18^140 18179864026545065558, // 18^147 10365691907784965713, // 18^154 11820503010388934534, // 18^161 13479494920515287357, // 18^168 15371324143524666656, // 18^175 17528669087274082029, // 18^182 9994397265397337538, // 18^189 11397097657699641734, // 18^196 12996665188491343910, // 18^203 14820729899390519784, // 18^210 16900799671687597041, // 18^217 9636402237998480121, // 18^224 10988858503312433354, // 18^231 12531130210573617469, // 18^238 14289857705148955482, // 18^245 ]; const BASE18_SMALL_INT_POWERS: [u64; 7] = [1, 18, 324, 5832, 104976, 1889568, 34012224]; const BASE18_STEP: i32 = 7; const BASE18_BIAS: i32 = 273; const BASE18_LOG2_MULT: i64 = 17909691508; const BASE18_LOG2_SHIFT: i32 = 32; // BASE19 const BASE19_SMALL_MANTISSA: [u64; 7] = [ 9223372036854775808, // 19^0 10952754293765046272, // 19^1 13006395723845992448, // 19^2 15445094922067116032, // 19^3 18341050219954700288, // 19^4 10889998568098103296, // 19^5 12931873299616497664, // 19^6 ]; const BASE19_LARGE_MANTISSA: [u64; 74] = [ 11480257701232751935, // 19^-273 9557118560717499270, // 19^-266 15912276110980153383, // 19^-259 13246698229359450470, // 19^-252 11027650146079950824, // 19^-245 18360660994723606251, // 19^-238 15284936849533635885, // 19^-231 12724449003299523561, // 19^-224 10592886580523254223, // 19^-217 17636794501472422448, // 19^-210 14682330350779734844, // 19^-203 12222789379976654044, // 19^-196 10175263507767080823, // 19^-189 16941466343535111364, // 19^-182 14103481529006456400, // 19^-175 11740907617180962231, // 19^-168 9774105166278679843, // 19^-161 16273551401031031665, // 19^-154 13547453741119703900, // 19^-147 11278023975525727060, // 19^-140 9388762436329270793, // 19^-133 15631968911773566269, // 19^-126 13013347271048440836, // 19^-119 10833389456740556437, // 19^-112 18037223579289291900, // 19^-105 15015680722474235794, // 19^-98 12500297873901968386, // 19^-91 10406284591707172986, // 19^-84 17326108560931302042, // 19^-77 14423689608892845377, // 19^-70 12007475377523598784, // 19^-63 9996018276276719532, // 19^-56 16643029152771930644, // 19^-49 13855037662215477149, // 19^-42 11534082339177879647, // 19^-35 9601926652984804576, // 19^-28 15986880054797934009, // 19^-21 13308804739049304804, // 19^-14 11079352755197736707, // 19^-7 9223372036854775808, // 19^0 15356599543294590976, // 19^7 12784106972526145936, // 19^14 10642550821503597582, // 19^21 17719483767102098773, // 19^28 14751167752856224795, // 19^35 12280095342105548712, // 19^42 10222969742988875833, // 19^49 17020895596425699999, // 19^56 14169605026128220038, // 19^63 11795954299763191941, // 19^70 9819930589845265884, // 19^77 16349849166729084322, // 19^84 13610970328610229813, // 19^91 11330900450341615431, // 19^98 9432781198977253334, // 19^105 15705258648723927251, // 19^112 13074359725955544955, // 19^119 10884181283927938347, // 19^126 18121790237456409263, // 19^133 15086081021789818522, // 19^140 12558904921302722743, // 19^147 10455073958207408827, // 19^154 17407341190420966318, // 19^161 14491314386248513408, // 19^168 12063771850272711708, // 19^175 10042884128822494706, // 19^182 16721059197198717605, // 19^189 13919996342176535757, // 19^196 11588159331358018389, // 19^203 9646944825844903597, // 19^210 16061833775630288054, // 19^217 13371202432132867541, // 19^224 11131297769520092558, // 19^231 9266615374542536521, // 19^238 ]; const BASE19_SMALL_INT_POWERS: [u64; 7] = [1, 19, 361, 6859, 130321, 2476099, 47045881]; const BASE19_STEP: i32 = 7; const BASE19_BIAS: i32 = 273; const BASE19_LOG2_MULT: i64 = 18244709747; const BASE19_LOG2_SHIFT: i32 = 32; // BASE20 const BASE20_SMALL_MANTISSA: [u64; 7] = [ 9223372036854775808, // 20^0 11529215046068469760, // 20^1 14411518807585587200, // 20^2 18014398509481984000, // 20^3 11258999068426240000, // 20^4 14073748835532800000, // 20^5 17592186044416000000, // 20^6 ]; const BASE20_LARGE_MANTISSA: [u64; 72] = [ 11896135267822264502, // 20^-266 14181298336770849826, // 20^-259 16905424996341287883, // 20^-252 10076418516839318205, // 20^-245 12012026926087520367, // 20^-238 14319451959237480602, // 20^-231 17070116948172426941, // 20^-224 10174582569701926077, // 20^-217 12129047596099288555, // 20^-210 14458951468586073584, // 20^-203 17236413322193710308, // 20^-196 10273702932711667006, // 20^-189 12247208276643356092, // 20^-182 14599809976391024699, // 20^-175 17404329748619824289, // 20^-168 10373788922202482396, // 20^-161 12366520073655226703, // 20^-154 14742040721959145907, // 20^-147 17573882009934360870, // 20^-140 10474849945267653984, // 20^-133 12486994201263968925, // 20^-126 14885657073574029118, // 20^-119 17745086042373215101, // 20^-112 10576895500643977583, // 20^-105 12608641982846233347, // 20^-98 15030672529752532658, // 20^-91 17917957937422433684, // 20^-84 10679935179604550411, // 20^-77 12731474852090538039, // 20^-70 15177100720513508366, // 20^-63 18092513943330655534, // 20^-56 10783978666860255917, // 20^-49 12855504354071922204, // 20^-42 15324955408658888583, // 20^-35 18268770466636286477, // 20^-28 10889035741470030830, // 20^-21 12980742146337069071, // 20^-14 15474250491067253436, // 20^-7 9223372036854775808, // 20^0 10995116277760000000, // 20^7 13107200000000000000, // 20^14 15625000000000000000, // 20^21 9313225746154785156, // 20^28 11102230246251565404, // 20^35 13234889800848442797, // 20^42 15777218104420236108, // 20^49 9403954806578300063, // 20^56 11210387714598536567, // 20^63 13363823550460978230, // 20^70 15930919111324522770, // 20^77 9495567745759798747, // 20^84 11319598848533390459, // 20^91 13494013367335069727, // 20^98 16086117467087590369, // 20^105 9588073174409622174, // 20^112 11429873912822749822, // 20^119 13625471488026082303, // 20^126 16242827758820155028, // 20^133 9681479787123295682, // 20^140 11541223272232169725, // 20^147 13758210268297397763, // 20^154 16401064715739962772, // 20^161 9775796363198734982, // 20^168 11653657392500323036, // 20^175 13892242184281734271, // 20^182 16560843210556190337, // 20^189 9871031767461413346, // 20^196 11767186841322676356, // 20^203 14027579833653779454, // 20^210 16722178260867332761, // 20^217 9967194951097567535, // 20^224 11881822289344748896, // 20^231 ]; const BASE20_SMALL_INT_POWERS: [u64; 7] = [1, 20, 400, 8000, 160000, 3200000, 64000000]; const BASE20_STEP: i32 = 7; const BASE20_BIAS: i32 = 266; const BASE20_LOG2_MULT: i64 = 283242; const BASE20_LOG2_SHIFT: i32 = 16; // BASE21 const BASE21_SMALL_MANTISSA: [u64; 7] = [ 9223372036854775808, // 21^0 12105675798371893248, // 21^1 15888699485363109888, // 21^2 10426959037269540864, // 21^3 13685383736416272384, // 21^4 17962066154046357504, // 21^5 11787605913592922112, // 21^6 ]; const BASE21_LARGE_MANTISSA: [u64; 72] = [ 14408615719666154271, // 21^-266 12084465783258517647, // 21^-259 10135207719324857823, // 21^-252 17000740844691866712, // 21^-245 14258473889848767691, // 21^-238 11958542249702993646, // 21^-231 10029596003240171126, // 21^-224 16823588341749525709, // 21^-217 14109896580142091329, // 21^-210 11833930874797054029, // 21^-203 9925084790952075138, // 21^-196 16648281817731599335, // 21^-189 13962867487806377083, // 21^-182 11710617985478380225, // 21^-175 9821662614901370847, // 21^-168 16474802037018309233, // 21^-161 13817370479981011975, // 21^-154 11588590051161810088, // 21^-147 9719318127024052612, // 21^-140 16303129964430447286, // 21^-133 13673389591914329770, // 21^-126 11467833682254685835, // 21^-119 9618040097506134632, // 21^-112 16133246763140728476, // 21^-105 13530909025211868449, // 21^-98 11348335628687672485, // 21^-91 9517817413551452467, // 21^-84 15965133792606908039, // 21^-77 13389913146102881332, // 21^-70 11230082778460885572, // 21^-63 9418639078162304415, // 21^-56 15798772606526436117, // 21^-49 13250386483724911652, // 21^-42 11113062156205168633, // 21^-35 9320494208932798947, // 21^-28 15634144950812425486, // 21^-21 13112313728426242332, // 21^-14 10997260921758362571, // 21^-7 9223372036854775808, // 21^0 15471232761590710272, // 21^7 12975679730086034724, // 21^14 10882666368756410705, // 21^21 18254523810272339491, // 21^28 15310018163217775871, // 21^35 12840469496451971963, // 21^42 10769265923239144897, // 21^49 18064306536063374465, // 21^56 15150483466319342608, // 21^63 12706668191495224563, // 21^70 10657047142270599779, // 21^77 17876071379371335714, // 21^84 14992611165849387896, // 21^91 12574261133782557711, // 21^98 10545997712573703694, // 21^105 17689797685974006860, // 21^112 14836383939169393936, // 21^119 12443233794865401683, // 21^126 10436105449179196548, // 21^133 17505465016871978304, // 21^140 14681784644147610193, // 21^147 12313571797685708585, // 21^154 10327358294088626305, // 21^161 17323053146045965028, // 21^168 14528796317278122096, // 21^175 12185260914998420522, // 21^182 10219744314951277448, // 21^189 17142542058237493769, // 21^196 14377402171819519570, // 21^203 12058287067810376090, // 21^210 10113251703754886210, // 21^217 16963911946752716066, // 21^224 14227585595952961160, // 21^231 ]; const BASE21_SMALL_INT_POWERS: [u64; 7] = [1, 21, 441, 9261, 194481, 4084101, 85766121]; const BASE21_STEP: i32 = 7; const BASE21_BIAS: i32 = 266; const BASE21_LOG2_MULT: i64 = 287855; const BASE21_LOG2_SHIFT: i32 = 16; // BASE22 const BASE22_SMALL_MANTISSA: [u64; 7] = [ 9223372036854775808, // 22^0 12682136550675316736, // 22^1 17437937757178560512, // 22^2 11988582208060260352, // 22^3 16484300536082857984, // 22^4 11332956618556964864, // 22^5 15582815350515826688, // 22^6 ]; const BASE22_LARGE_MANTISSA: [u64; 70] = [ 9269587019009961312, // 22^-259 10766865452458105492, // 22^-252 12505993140104023937, // 22^-245 14526035001637582317, // 22^-238 16872365953260472216, // 22^-231 9798845067792082715, // 22^-224 11381612386618310709, // 22^-217 13220037629231758864, // 22^-210 15355416173176400877, // 22^-203 17835713669231780592, // 22^-196 10358321731667433590, // 22^-189 12031459025026523680, // 22^-182 13974851334106036811, // 22^-175 16232151844936756579, // 22^-168 9427032431967498649, // 22^-161 10949742378252536811, // 22^-154 12718409426865212084, // 22^-147 14772762021382712235, // 22^-140 17158945778190527545, // 22^-133 9965280013064351107, // 22^-126 11574930887071326019, // 22^-119 13444582075449265201, // 22^-112 15616230364311619568, // 22^-105 18138656108661462534, // 22^-98 10534259477248206780, // 22^-91 12235815274209166465, // 22^-84 14212216411407346527, // 22^-77 16507857531195957209, // 22^-70 9587152080358667750, // 22^-63 11135725497779554116, // 22^-56 12934433638113158426, // 22^-49 15023679738882972932, // 22^-42 17450393207123747022, // 22^-35 10134541882409419905, // 22^-28 11771532933066741091, // 22^-21 13672940444874950532, // 22^-14 15881474526053323426, // 22^-7 9223372036854775808, // 22^0 10713185553479630848, // 22^7 12443642546855641088, // 22^14 14453613172379218947, // 22^21 16788246122479815273, // 22^28 9749991386498543747, // 22^35 11324867570234788254, // 22^42 13154127055020322136, // 22^49 15278859333807672616, // 22^56 17746790917089950882, // 22^63 10306678691583236909, // 22^70 11971474296148943805, // 22^77 13905177517602390611, // 22^84 16151223902158337584, // 22^91 9380032480974399852, // 22^98 10895150717634104284, // 22^105 12654999798852712250, // 22^112 14699110095811391320, // 22^119 17073397158676562691, // 22^126 9915596544207462992, // 22^133 11517222250937216925, // 22^140 13377551999629643946, // 22^147 15538373194824147716, // 22^154 18048222989401488392, // 22^161 10481739271897017716, // 22^168 12174811695150892652, // 22^175 14141359174025375600, // 22^182 16425555014410689631, // 22^189 9539353827706830891, // 22^196 11080206589104387250, // 22^203 12869946987462278079, // 22^210 14948776823616759120, // 22^217 17363391530672110525, // 22^224 ]; const BASE22_SMALL_INT_POWERS: [u64; 7] = [1, 22, 484, 10648, 234256, 5153632, 113379904]; const BASE22_STEP: i32 = 7; const BASE22_BIAS: i32 = 259; const BASE22_LOG2_MULT: i64 = 292254; const BASE22_LOG2_SHIFT: i32 = 16; // BASE23 const BASE23_SMALL_MANTISSA: [u64; 7] = [ 9223372036854775808, // 23^0 13258597302978740224, // 23^1 9529616811515969536, // 23^2 13698824166554206208, // 23^3 9846029869710835712, // 23^4 14153667937709326336, // 23^5 10172948830228578304, // 23^6 ]; const BASE23_LARGE_MANTISSA: [u64; 69] = [ 9630971713765025029, // 23^-252 15269861356524917016, // 23^-245 12105147475110827234, // 23^-238 9596327823341159083, // 23^-231 15214933627595239789, // 23^-224 12061603644316153100, // 23^-217 9561808551614073801, // 23^-210 15160203481036150549, // 23^-203 12018216446491393101, // 23^-196 9527413450313687580, // 23^-189 15105670206117496642, // 23^-182 11974985318206853149, // 23^-175 9493142072782406120, // 23^-168 15051333094665716613, // 23^-161 11931909698059570948, // 23^-154 9458993973969322090, // 23^-147 14997191441054643808, // 23^-140 11888989026666025574, // 23^-133 9424968710424435661, // 23^-126 14943244542196343052, // 23^-119 11846222746654873270, // 23^-112 9391065840292895827, // 23^-105 14889491697531980297, // 23^-98 11803610302659709381, // 23^-91 9357284923309262442, // 23^-84 14835932209022725101, // 23^-77 11761151141311856318, // 23^-70 9323625520791788901, // 23^-63 14782565381140685845, // 23^-56 11718844711233177467, // 23^-49 9290087195636725377, // 23^-42 14729390520859877547, // 23^-35 11676690463028916948, // 23^-28 9256669512312642559, // 23^-21 14676406937647222172, // 23^-14 11634687849280565129, // 23^-7 9223372036854775808, // 23^0 14623613943453581312, // 23^7 11592836324538749809, // 23^14 18380388673718779295, // 23^21 14571010852704821123, // 23^28 11551135345316152959, // 23^35 18314271962956325083, // 23^42 14518596982292909406, // 23^49 11509584370080452960, // 23^56 18248393082825183718, // 23^63 14466371651567044709, // 23^70 11468182859247292218, // 23^77 18182751177816837937, // 23^84 14414334182324817337, // 23^91 11426930275173270071, // 23^98 18117345395500148774, // 23^105 14362483898803402166, // 23^112 11385826082148960918, // 23^119 18052174886510285819, // 23^126 14310820127670783127, // 23^133 11344869746391957446, // 23^140 17987238804537697299, // 23^147 14259342198017009262, // 23^154 11304060736039938888, // 23^161 17922536306317119829, // 23^168 14208049441345482237, // 23^175 11263398521143764220, // 23^182 17858066551616627705, // 23^189 14156941191564275184, // 23^196 11222882573660590193, // 23^203 17793828703226721580, // 23^210 14106016784977482782, // 23^217 11182512367447014130, // 23^224 ]; const BASE23_SMALL_INT_POWERS: [u64; 7] = [1, 23, 529, 12167, 279841, 6436343, 148035889]; const BASE23_STEP: i32 = 7; const BASE23_BIAS: i32 = 252; const BASE23_LOG2_MULT: i64 = 296457; const BASE23_LOG2_SHIFT: i32 = 16; // BASE24 const BASE24_SMALL_MANTISSA: [u64; 7] = [ 9223372036854775808, // 24^0 13835058055282163712, // 24^1 10376293541461622784, // 24^2 15564440312192434176, // 24^3 11673330234144325632, // 24^4 17509995351216488448, // 24^5 13132496513412366336, // 24^6 ]; const BASE24_LARGE_MANTISSA: [u64; 68] = [ 13878157218102970303, // 24^-252 14820082927730076197, // 24^-245 15825938165500818674, // 24^-238 16900061898413227754, // 24^-231 18047087583901234911, // 24^-224 9635981578611328308, // 24^-217 10289986187706530766, // 24^-210 10988378804938565813, // 24^-203 11734172092969064177, // 24^-196 12530583187169601247, // 24^-189 13381047573408163051, // 24^-182 14289233907736158492, // 24^-175 15259059841903798156, // 24^-168 16294708922970511019, // 24^-161 17400648639910404101, // 24^-154 9290824847530286564, // 24^-147 9921403291771844100, // 24^-140 10594779784719249534, // 24^-133 11313859076748534537, // 24^-126 12081743066820822770, // 24^-119 12901744183172431346, // 24^-112 13777399672167044607, // 24^-105 14712486856947913357, // 24^-98 15711039431711468023, // 24^-91 16777364861891103792, // 24^-84 17916062965310470700, // 24^-77 9566022877229980327, // 24^-70 10215279312745101062, // 24^-63 10908601492662859386, // 24^-56 11648980207252770253, // 24^-49 12439609234991117453, // 24^-42 13283899119592565366, // 24^-35 14185491882103974832, // 24^-28 15148276731524117655, // 24^-21 16176406841720334625, // 24^-14 17274317267012876867, // 24^-7 9223372036854775808, // 24^0 9849372385059274752, // 24^7 10517860061584293888, // 24^14 11231718727873462272, // 24^21 11994027762626592768, // 24^28 12808075545343924992, // 24^35 13677373641439044901, // 24^42 14605671950110933202, // 24^49 15596974880318657672, // 24^56 16655558624637160317, // 24^63 17785989605508530085, // 24^70 9496572086730262523, // 24^77 10141114821132365302, // 24^84 10829403375886954548, // 24^91 11564406827668344530, // 24^98 12349295767632162835, // 24^105 13187455978423603575, // 24^112 14082503039459189950, // 24^119 15038297923484984581, // 24^126 16058963651690264296, // 24^133 17148903079221976570, // 24^140 18312817887821515019, // 24^147 9777864433756263024, // 24^154 10441498787414525016, // 24^161 11150174730505647564, // 24^168 11906949284968677354, // 24^175 12715086956165281921, // 24^182 13578073815006577911, // 24^189 14499632535849309517, // 24^196 15483738455030488239, // 24^203 16534636719312342666, // 24^210 17656860598210983110, // 24^217 ]; const BASE24_SMALL_INT_POWERS: [u64; 7] = [1, 24, 576, 13824, 331776, 7962624, 191102976]; const BASE24_STEP: i32 = 7; const BASE24_BIAS: i32 = 252; const BASE24_LOG2_MULT: i64 = 300481; const BASE24_LOG2_SHIFT: i32 = 16; // BASE25 const BASE25_SMALL_MANTISSA: [u64; 7] = [ 9223372036854775808, // 25^0 14411518807585587200, // 25^1 11258999068426240000, // 25^2 17592186044416000000, // 25^3 13743895347200000000, // 25^4 10737418240000000000, // 25^5 16777216000000000000, // 25^6 ]; const BASE25_LARGE_MANTISSA: [u64; 68] = [ 15492890949478498119, // 25^-252 11008361120075348168, // 25^-245 15643822052986917253, // 25^-238 11115604119273511155, // 25^-231 15796223521069679172, // 25^-224 11223891875338892399, // 25^-217 15950109677957715915, // 25^-210 11333234566249726012, // 25^-203 16105494987428025427, // 25^-196 11443642469137689536, // 25^-189 16262394054163123565, // 25^-182 11555125961253852697, // 25^-175 16420821625123739831, // 25^-168 11667695520944036383, // 25^-161 16580792590934885855, // 25^-154 11781361728633673532, // 25^-147 16742321987285426889, // 25^-140 11896135267822264502, // 25^-133 16905424996341287883, // 25^-126 12012026926087520367, // 25^-119 17070116948172426941, // 25^-112 12129047596099288555, // 25^-105 17236413322193710308, // 25^-98 12247208276643356092, // 25^-91 17404329748619824289, // 25^-84 12366520073655226703, // 25^-77 17573882009934360870, // 25^-70 12486994201263968925, // 25^-63 17745086042373215101, // 25^-56 12608641982846233347, // 25^-49 17917957937422433684, // 25^-42 12731474852090538039, // 25^-35 18092513943330655534, // 25^-28 12855504354071922204, // 25^-21 18268770466636286477, // 25^-14 12980742146337069071, // 25^-7 9223372036854775808, // 25^0 13107200000000000000, // 25^7 9313225746154785156, // 25^14 13234889800848442797, // 25^21 9403954806578300063, // 25^28 13363823550460978230, // 25^35 9495567745759798747, // 25^42 13494013367335069727, // 25^49 9588073174409622174, // 25^56 13625471488026082303, // 25^63 9681479787123295682, // 25^70 13758210268297397763, // 25^77 9775796363198734982, // 25^84 13892242184281734271, // 25^91 9871031767461413346, // 25^98 14027579833653779454, // 25^105 9967194951097567535, // 25^112 14164235936814247246, // 25^119 10064294952495520794, // 25^126 14302223338085469768, // 25^133 10162340898095201970, // 25^140 14441555006918636608, // 25^147 10261342003245940623, // 25^154 14582244039112794984, // 25^161 10361307573072618726, // 25^168 14724303658045725350, // 25^175 10462247003350260393, // 25^182 14867747215916808149, // 25^189 10564169781387141817, // 25^196 15012588195001998509, // 25^203 10667085486916504429, // 25^210 15158840208921026870, // 25^217 ]; const BASE25_SMALL_INT_POWERS: [u64; 7] = [1, 25, 625, 15625, 390625, 9765625, 244140625]; const BASE25_STEP: i32 = 7; const BASE25_BIAS: i32 = 252; const BASE25_LOG2_MULT: i64 = 304340; const BASE25_LOG2_SHIFT: i32 = 16; // BASE26 const BASE26_SMALL_MANTISSA: [u64; 7] = [ 9223372036854775808, // 26^0 14987979559889010688, // 26^1 12177733392409821184, // 26^2 9894408381332979712, // 26^3 16078413619666092032, // 26^4 13063711065978699776, // 26^5 10614265241107693568, // 26^6 ]; const BASE26_LARGE_MANTISSA: [u64; 67] = [ 12105269954044049440, // 26^-245 11318739317371282802, // 26^-238 10583312905946974966, // 26^-231 9895670261906581517, // 26^-224 9252706671590202790, // 26^-217 17303038295456506514, // 26^-210 16178786644847745028, // 26^-203 15127582383507515360, // 26^-196 14144679313308326113, // 26^-189 13225639616708097270, // 26^-182 12366313819957994305, // 26^-175 11562822058185475244, // 26^-168 10811536557764206566, // 26^-161 10109065256878566708, // 26^-154 9452236490329416245, // 26^-147 17676169338865748372, // 26^-140 16527673784713390059, // 26^-133 15453800848879553322, // 26^-126 14449701983936623969, // 26^-119 13510843673109724761, // 26^-112 12632986961401522264, // 26^-105 11812168316666510159, // 26^-98 11044681734222321153, // 26^-91 10327062004200202236, // 26^-84 9656069066086567364, // 26^-77 18057346759632441273, // 26^-70 16884084494735168740, // 26^-63 15787054046203585657, // 26^-56 14761302310200400353, // 26^-49 13802198007013635263, // 26^-42 12905410770780760221, // 26^-35 12066891597841972649, // 26^-28 11282854565446737172, // 26^-21 10549759738273355365, // 26^-14 9864297185584324446, // 26^-7 9223372036854775808, // 26^0 17248181016800002048, // 26^7 16127493675824287744, // 26^14 15079622135830712445, // 26^21 14099835245963182583, // 26^28 13183709258266090507, // 26^35 12327107854416477244, // 26^42 11526163470203963629, // 26^49 10777259833438283283, // 26^56 10077015636442889080, // 26^63 9422269269415772631, // 26^70 17620129091456925542, // 26^77 16475274709425560342, // 26^84 15404806363345084091, // 26^91 14403890877545881062, // 26^98 13468009108242878856, // 26^105 12592935539554553092, // 26^112 11774719205254957782, // 26^119 11009665850120294209, // 26^126 10294321250328313309, // 26^133 9625455617601982106, // 26^140 18000098033363922638, // 26^147 16830555460575262708, // 26^154 15737003020008648959, // 26^161 14714503311068774005, // 26^168 13758439736979533044, // 26^175 12864495660801764695, // 26^182 12028634915772762381, // 26^189 11247083581971537298, // 26^196 10516312947031287874, // 26^203 9833023573966516058, // 26^210 18388260808361729691, // 26^217 ]; const BASE26_SMALL_INT_POWERS: [u64; 7] = [1, 26, 676, 17576, 456976, 11881376, 308915776]; const BASE26_STEP: i32 = 7; const BASE26_BIAS: i32 = 245; const BASE26_LOG2_MULT: i64 = 20188234867; const BASE26_LOG2_SHIFT: i32 = 32; // BASE27 const BASE27_SMALL_MANTISSA: [u64; 6] = [ 9223372036854775808, // 27^0 15564440312192434176, // 27^1 13132496513412366336, // 27^2 11080543933191684096, // 27^3 9349208943630483456, // 27^4 15776790092376440832, // 27^5 ]; const BASE27_LARGE_MANTISSA: [u64; 76] = [ 16362187946641408838, // 27^-240 11807394875954316034, // 27^-234 17041067394086403622, // 27^-228 12297292543386873229, // 27^-222 17748114058878258402, // 27^-216 12807516432401518638, // 27^-210 9242248309993244326, // 27^-204 13338909893173747895, // 27^-198 9625716122873707062, // 27^-192 13892351267110242231, // 27^-186 10025094302862174179, // 27^-180 14468755338661289290, // 27^-174 10441042983020688038, // 27^-168 15069074847369989965, // 27^-162 10874249685827050127, // 27^-156 15694302062657520659, // 27^-150 11325430459582219446, // 27^-144 16345470423947416967, // 27^-138 11795331061968106016, // 27^-132 17023656248839843776, // 27^-126 12284728192712064755, // 27^-120 17729980512159296735, // 27^-114 12794430777395563548, // 27^-108 9232805349408163458, // 27^-102 13325281304529035642, // 27^-96 9615881366772943927, // 27^-90 13878157218102970303, // 27^-84 10014851495355986817, // 27^-78 14453972367916992462, // 27^-72 10430375193750279268, // 27^-66 15053678520084183432, // 27^-60 10863139281980340679, // 27^-54 15678266930207358578, // 27^-48 11313859076748534537, // 27^-42 16328769981827608423, // 27^-36 11783279573783601017, // 27^-30 17006262892853298360, // 27^-24 12272176679245716810, // 27^-18 17711865492790087155, // 27^-12 12781358492223474271, // 27^-6 9223372036854775808, // 27^0 13311666640442621952, // 27^6 9606056659007943744, // 27^12 13863977671394362375, // 27^18 10004619153098548172, // 27^24 14439204501182606065, // 27^30 10419718303939637392, // 27^36 15038297923484984581, // 27^42 10852040229820157048, // 27^48 15662248181121787524, // 27^54 11302299516591361707, // 27^60 16312086602830473207, // 27^66 11771240398807322073, // 27^72 16988887307951181138, // 27^78 12259637989871837542, // 27^84 17693768981840924725, // 27^90 12768299563225066619, // 27^96 18427896724951050158, // 27^102 13298065886687551351, // 27^108 9596241989312152815, // 27^114 13849812612167175924, // 27^120 9994397265397337538, // 27^126 14424451723026109070, // 27^132 10409072302452601000, // 27^138 15022933041500086259, // 27^144 10840952517748290136, // 27^150 15646245798661648271, // 27^156 11290751767031273467, // 27^162 16295420269522331823, // 27^168 11759213524458657188, // 27^174 16971529475976476179, // 27^180 12247112111487835932, // 27^186 17675690960401445308, // 27^192 12755253976754113245, // 27^198 18409068632845853217, // 27^204 13284479029051404288, // 27^210 ]; const BASE27_SMALL_INT_POWERS: [u64; 6] = [1, 27, 729, 19683, 531441, 14348907]; const BASE27_STEP: i32 = 6; const BASE27_BIAS: i32 = 240; const BASE27_LOG2_MULT: i64 = 311617; const BASE27_LOG2_SHIFT: i32 = 16; // BASE28 const BASE28_SMALL_MANTISSA: [u64; 6] = [ 9223372036854775808, // 28^0 16140901064495857664, // 28^1 14123288431433875456, // 28^2 12357877377504641024, // 28^3 10813142705316560896, // 28^4 9461499867151990784, // 28^5 ]; const BASE28_LARGE_MANTISSA: [u64; 76] = [ 10853684694473876180, // 28^-240 9742165760957008810, // 28^-234 17488953546307848045, // 28^-228 15697920957714630238, // 28^-222 14090306875260685218, // 28^-216 12647327526607851831, // 28^-210 11352122773573968201, // 28^-204 10189559113984709052, // 28^-198 18292105715960495534, // 28^-192 16418822825447359765, // 28^-186 14737381642082644874, // 28^-180 13228135778880165762, // 28^-174 11873450822826176619, // 28^-168 10657498289906897377, // 28^-162 9566070681070377880, // 28^-156 17172830956378919788, // 28^-150 15414172280784786485, // 28^-144 13835616719528574716, // 28^-138 12418720027433908743, // 28^-132 11146926822720122755, // 28^-126 10005377149705503250, // 28^-120 17961465702601665525, // 28^-114 16122043445170466212, // 28^-108 14470995249030000148, // 28^-102 12989029846596759700, // 28^-96 11658831576707932907, // 28^-90 10464858064026730335, // 28^-84 9393158617970892313, // 28^-78 16862422458582420498, // 28^-72 15135552519453149331, // 28^-66 13585530230416439557, // 28^-60 12194244736314878063, // 28^-54 10945439903127358164, // 28^-48 9824524377159351811, // 28^-42 17636802191900948811, // 28^-36 15830628517722738088, // 28^-30 14209423938610553080, // 28^-24 12754245887402290033, // 28^-18 11448091693168579255, // 28^-12 10275699917675706335, // 28^-6 9223372036854775808, // 28^0 16557624767515983872, // 28^6 14861968965709594624, // 28^12 13339964194082398208, // 28^18 11973826961285400900, // 28^24 10747594971986893695, // 28^30 9646940619348801089, // 28^36 17318007155239366140, // 28^42 15544481077627229210, // 28^48 13952580675520064463, // 28^54 12523705779222565186, // 28^60 11241161050565762112, // 28^66 10089960910324183248, // 28^72 18113308885783841476, // 28^78 16258336464718499495, // 28^84 14593330587292989709, // 28^90 13098836900821174211, // 28^96 11757393360479052160, // 28^102 10553326198326110898, // 28^108 9472566787009190529, // 28^114 17004974516675479989, // 28^120 15263505912112072336, // 28^126 13700379997665963732, // 28^132 12297332812083457696, // 28^138 11037970794744924274, // 28^144 9907579239127697723, // 28^150 17785900724855568076, // 28^156 15964457964924108341, // 28^162 14329547997401095751, // 28^168 12862068117875988113, // 28^174 11544871917724549298, // 28^180 10362568941103939059, // 28^186 9301344858947275744, // 28^192 16697600117649658875, // 28^198 14987609529429357277, // 28^204 13452737987730670580, // 28^210 ]; const BASE28_SMALL_INT_POWERS: [u64; 6] = [1, 28, 784, 21952, 614656, 17210368]; const BASE28_STEP: i32 = 6; const BASE28_BIAS: i32 = 240; const BASE28_LOG2_MULT: i64 = 315055; const BASE28_LOG2_SHIFT: i32 = 16; // BASE29 const BASE29_SMALL_MANTISSA: [u64; 6] = [ 9223372036854775808, // 29^0 16717361816799281152, // 29^1 15150109146474348544, // 29^2 13729786413992378368, // 29^3 12442618937680592896, // 29^4 11276123412273037312, // 29^5 ]; const BASE29_LARGE_MANTISSA: [u64; 76] = [ 9780142334064946636, // 29^-240 10835857583212112985, // 29^-234 12005531775819627369, // 29^-228 13301466184228767173, // 29^-222 14737289938837575007, // 29^-216 16328103363438049788, // 29^-210 18090636782853846909, // 29^-204 10021713236516230810, // 29^-198 11103504802015131117, // 29^-192 12302070113036945059, // 29^-186 13630014285094069421, // 29^-180 15101303090037955289, // 29^-174 16731409831799452344, // 29^-168 9268739038298839376, // 29^-162 10269250974512215384, // 29^-156 11377762945074294339, // 29^-150 12605932989231929836, // 29^-144 13966677570638048918, // 29^-138 15474307417689145256, // 29^-132 17144678027117236568, // 29^-126 9497678206828984163, // 29^-120 10522902929736936910, // 29^-114 11658795303156142066, // 29^-108 12917301321555931503, // 29^-102 14311656487072982013, // 29^-96 15856525005124406387, // 29^-90 17568154005459773215, // 29^-84 9732272205284828726, // 29^-78 10782820124222926001, // 29^-72 11946769200332301461, // 29^-66 13236360495839591806, // 29^-60 14665156431661011058, // 29^-54 16248183421166822582, // 29^-48 18002089900515211938, // 29^-42 9972660708767378680, // 29^-36 11049157310268331325, // 29^-30 12241856093602695018, // 29^-24 13563300476969856592, // 29^-18 15027387875005778139, // 29^-12 16649515855621676607, // 29^-6 9223372036854775808, // 29^0 10218986842372440064, // 29^6 11322073062575009312, // 29^12 12544231674979455490, // 29^18 13898315921993315819, // 29^24 15398566486364679514, // 29^30 17060761258115507449, // 29^36 9451190634016324153, // 29^42 10471397266405980105, // 29^48 11601729872662437745, // 29^54 12854075976092328003, // 29^60 14241606296013212103, // 29^66 15778913262056350490, // 29^72 17482164480364512070, // 29^78 9684636382831873707, // 29^84 10730042263704319491, // 29^90 11888294245613666403, // 29^96 13171573475377840424, // 29^102 14593375990949121808, // 29^108 16168654657039833397, // 29^114 17913976421956996862, // 29^120 9923848274745194421, // 29^126 10995075829111145761, // 29^132 12181936799210906401, // 29^138 13496913207916061440, // 29^144 14953834447230017102, // 29^150 16568022719743769659, // 29^156 18356454179736676324, // 29^162 10168968734308426004, // 29^168 11266655761164621625, // 29^174 12482832365519782645, // 29^180 13830288877980342143, // 29^186 15323196278493163895, // 29^192 16977255230225892037, // 29^198 9404930600437880197, // 29^204 10420143703980341466, // 29^210 ]; const BASE29_SMALL_INT_POWERS: [u64; 6] = [1, 29, 841, 24389, 707281, 20511149]; const BASE29_STEP: i32 = 6; const BASE29_BIAS: i32 = 240; const BASE29_LOG2_MULT: i64 = 318373; const BASE29_LOG2_SHIFT: i32 = 16; // BASE30 const BASE30_SMALL_MANTISSA: [u64; 6] = [ 9223372036854775808, // 30^0 17293822569102704640, // 30^1 16212958658533785600, // 30^2 15199648742375424000, // 30^3 14249670695976960000, // 30^4 13359066277478400000, // 30^5 ]; const BASE30_LARGE_MANTISSA: [u64; 74] = [ 15921395853562858335, // 30^-234 10809579470425214363, // 30^-228 14677985448278451843, // 30^-222 9965385675239368708, // 30^-216 13531681443098000788, // 30^-210 18374241463874359754, // 30^-204 12474900136854879801, // 30^-198 16939271613521887687, // 30^-192 11500650091336533543, // 30^-186 15616368347004676150, // 30^-180 10602485877430447296, // 30^-174 14396779620362065880, // 30^-168 9774465433549085656, // 30^-162 13272436896445757604, // 30^-156 18022221508452589239, // 30^-150 12235901765210495847, // 30^-144 16614743297618723424, // 30^-138 11280316732790367097, // 30^-132 15317184660964044954, // 30^-126 10399359853791807565, // 30^-120 14120961229157126909, // 30^-114 9587202906660312336, // 30^-108 13018159044823362852, // 30^-102 17676945670836105047, // 30^-96 12001482205502242389, // 30^-90 16296432405358431306, // 30^-84 11064204595523231124, // 30^-78 15023732837543702665, // 30^-72 10200125387468709836, // 30^-66 13850427060322257636, // 30^-60 9403528018831206315, // 30^-54 12768752734601403407, // 30^-48 17338284744926585040, // 30^-42 11771553735296689434, // 30^-36 15984219821228248249, // 30^-30 10852232807944894743, // 30^-24 14735903063773789011, // 30^-18 10004707922685045925, // 30^-12 13585075876931470780, // 30^-6 9223372036854775808, // 30^0 12524124635136000000, // 30^6 17006112000000000000, // 30^12 11546030312776565551, // 30^18 15677988711770840524, // 30^24 10644322047830505987, // 30^30 14453587630518598230, // 30^36 9813034332029575584, // 30^42 13324808381590173768, // 30^48 18093335088676282534, // 30^54 12284183203843431517, // 30^60 16680303133282552614, // 30^66 11324827544542942993, // 30^72 15377624481863911156, // 30^78 10440394512637323916, // 30^84 14176680892170610158, // 30^90 9625032889090827484, // 30^96 13069527179276967861, // 30^102 17746696832949127203, // 30^108 12048838651943871501, // 30^114 16360736223435182728, // 30^120 11107862654034279481, // 30^126 15083014731837417449, // 30^132 10240373890390132852, // 30^138 13905079227116716745, // 30^144 9440633241616270046, // 30^150 12819136740897336720, // 30^156 17406699590597596894, // 30^162 11818002910861417777, // 30^168 16047291684929232224, // 30^174 10895054450550498712, // 30^180 14794049215412351417, // 30^186 10044185331124443731, // 30^192 13638680998961850032, // 30^198 9259766385185707988, // 30^204 ]; const BASE30_SMALL_INT_POWERS: [u64; 6] = [1, 30, 900, 27000, 810000, 24300000]; const BASE30_STEP: i32 = 6; const BASE30_BIAS: i32 = 234; const BASE30_LOG2_MULT: i64 = 321578; const BASE30_LOG2_SHIFT: i32 = 16; // BASE31 const BASE31_SMALL_MANTISSA: [u64; 6] = [ 9223372036854775808, // 31^0 17870283321406128128, // 31^1 17311836967612186624, // 31^2 16770842062374305792, // 31^3 16246753247925108736, // 31^4 15739042208927449088, // 31^5 ]; const BASE31_LARGE_MANTISSA: [u64; 74] = [ 15172192345302428421, // 31^-234 12540609161645107233, // 31^-228 10365468257053156090, // 31^-222 17135201456813756829, // 31^-216 14163138687236953263, // 31^-210 11706573627364173290, // 31^-204 9676094340331131706, // 31^-198 15995594383677739926, // 31^-192 13221193938792609146, // 31^-186 10928007110853986174, // 31^-180 18065136926019727780, // 31^-174 14931778907414090897, // 31^-168 12341894902482781431, // 31^-162 10201220546354171409, // 31^-156 16863682839241173595, // 31^-150 13938714372965575021, // 31^-144 11521075213714088050, // 31^-138 9522770215989197442, // 31^-132 15742133595063495983, // 31^-126 13011695363011784957, // 31^-120 10754845599386459585, // 31^-114 17778882864941161542, // 31^-108 14695174979700806287, // 31^-102 12146329402386737855, // 31^-96 10039575449430160254, // 31^-90 16596466614020050649, // 31^-84 13717846210614220387, // 31^-78 11338516145303865769, // 31^-72 9371875613960541536, // 31^-66 15492689060539222513, // 31^-60 12805516430937677459, // 31^-54 10584427946771654325, // 31^-48 17497164689077279120, // 31^-42 14462320197950402007, // 31^-36 11953862767183809017, // 31^-30 9880491726141866768, // 31^-24 16333484606893641287, // 31^-18 13500477850600094178, // 31^-12 11158849846261135900, // 31^-6 9223372036854775808, // 31^0 15247197139898466304, // 31^6 12602604540616796176, // 31^12 10416710674748495795, // 31^18 17219910524322248562, // 31^24 14233155154461633068, // 31^30 11764445893307051548, // 31^36 9723928789827359386, // 31^42 16074669723871456105, // 31^48 13286553836236866995, // 31^54 10982030478739077827, // 31^60 18154443194596327488, // 31^66 15005595201356001156, // 31^72 12402907923608447627, // 31^78 10251650993997756459, // 31^84 16947049635463054782, // 31^90 14007621382887632827, // 31^96 11578030455268066882, // 31^102 9569846696947249770, // 31^108 15819955934111728582, // 31^114 13076019589586139267, // 31^120 10808012931221917147, // 31^126 17866774016535005152, // 31^132 14767821605568725557, // 31^138 12206375631777172937, // 31^144 10089206793225315915, // 31^150 16678512408132988469, // 31^156 13785661343319529298, // 31^162 11394568893327831301, // 31^168 9418206136893990095, // 31^174 15569278253075119325, // 31^180 12868821397533098208, // 31^186 10636752807015729117, // 31^192 17583663147154342787, // 31^198 14533815689909759814, // 31^204 ]; const BASE31_SMALL_INT_POWERS: [u64; 6] = [1, 31, 961, 29791, 923521, 28629151]; const BASE31_STEP: i32 = 6; const BASE31_BIAS: i32 = 234; const BASE31_LOG2_MULT: i64 = 21278111132; const BASE31_LOG2_SHIFT: i32 = 32; // BASE33 const BASE33_SMALL_MANTISSA: [u64; 6] = [ 9223372036854775808, // 33^0 9511602413006487552, // 33^1 9808839988412940288, // 33^2 10115366238050844672, // 33^3 10431471432989933568, // 33^4 10757454915270868992, // 33^5 ]; const BASE33_LARGE_MANTISSA: [u64; 72] = [ 16952605037124200569, // 33^-228 10195070131008495069, // 33^-222 12262357879342609130, // 33^-216 14748836332546310936, // 33^-210 17739506162243888511, // 33^-204 10668301952265249182, // 33^-198 12831548466319904021, // 33^-192 15433443558330863109, // 33^-186 9281466718275888268, // 33^-180 11163500111543439891, // 33^-174 13427159577595330562, // 33^-168 16149828684624228128, // 33^-162 9712291160146516482, // 33^-156 11681684235978010467, // 33^-150 14050417593436164695, // 33^-144 16899466768835551431, // 33^-138 10163113486548439647, // 33^-132 12223921281461810852, // 33^-126 14702605819874780450, // 33^-120 17683901337162836029, // 33^-114 10634861953510936381, // 33^-108 12791327729538214791, // 33^-102 15385067131072375518, // 33^-96 9252373781378705800, // 33^-90 11128507904583594948, // 33^-84 13385071886268464065, // 33^-78 16099206734335173177, // 33^-72 9681847795705762071, // 33^-66 11645067770860388376, // 33^-60 14006376287807173243, // 33^-54 16846495063476347823, // 33^-48 10131257010808365886, // 33^-42 12185605163840289543, // 33^-36 14656520217639143557, // 33^-30 17628470806481188820, // 33^-24 10601526773079323099, // 33^-18 12751233065433685927, // 33^-12 15336842340660548274, // 33^-6 9223372036854775808, // 33^0 11093625381373083648, // 33^6 13343116119623879688, // 33^12 16048743459528137878, // 33^18 9651499856579507665, // 33^24 11608566080760702539, // 33^30 13962473030502269494, // 33^36 16793689398951866695, // 33^42 10099500389807484117, // 33^48 12147409148830342864, // 33^54 14610579071614836924, // 33^60 17573214023869781748, // 33^66 10568296082415350040, // 33^72 12711264078829073096, // 33^78 15288768711786753433, // 33^84 18388922397719682024, // 33^90 11058852198106072831, // 33^96 13301291864141109889, // 33^102 15998438362831755651, // 33^108 9621247043655259795, // 33^114 11572178805914439916, // 33^120 13918707388806312258, // 33^126 16741049254803901004, // 33^132 10067843310549183526, // 33^138 12109332859968012500, // 33^144 14564781929001072895, // 33^150 17518130444711929011, // 33^156 10535169553993820096, // 33^162 12671420375785822681, // 33^168 15240845770632227134, // 33^174 18331281964891256972, // 33^180 11024188012054395372, // 33^186 13259598707595875029, // 33^192 15948290948433680084, // 33^198 ]; const BASE33_SMALL_INT_POWERS: [u64; 6] = [1, 33, 1089, 35937, 1185921, 39135393]; const BASE33_STEP: i32 = 6; const BASE33_BIAS: i32 = 228; const BASE33_LOG2_MULT: i64 = 330590; const BASE33_LOG2_SHIFT: i32 = 16; // BASE34 const BASE34_SMALL_MANTISSA: [u64; 6] = [ 9223372036854775808, // 34^0 9799832789158199296, // 34^1 10412322338480586752, // 34^2 11063092484635623424, // 34^3 11754535764925349888, // 34^4 12489194250233184256, // 34^5 ]; const BASE34_LARGE_MANTISSA: [u64; 72] = [ 9604872659818954289, // 34^-228 13818638119852157632, // 34^-222 9940514895438007254, // 34^-216 14301530372152488549, // 34^-210 10287886147601198282, // 34^-204 14801297292224652053, // 34^-198 10647396286743453217, // 34^-192 15318528565264575918, // 34^-186 11019469506220361724, // 34^-180 15853834483014935870, // 34^-174 11404544822822581011, // 34^-168 16407846663860846991, // 34^-162 11803076594780713339, // 34^-156 16981218798089296108, // 34^-150 12215535057871861844, // 34^-144 17574627419191661979, // 34^-138 12642406880260427750, // 34^-132 18188772702119398880, // 34^-126 13084195736727816960, // 34^-120 9412189644717380884, // 34^-114 13541422902968601381, // 34^-108 9741098573165682574, // 34^-102 14014627870654357169, // 34^-96 10081501222766715924, // 34^-90 14504368983990906269, // 34^-84 10433799241558921201, // 34^-78 15011224098520048145, // 34^-72 10798408313169791102, // 34^-66 15535791262943115320, // 34^-60 11175758647289472494, // 34^-54 16078689424770850259, // 34^-48 11566295487283966163, // 34^-42 16640559160632214299, // 34^-36 11970479635546867736, // 34^-30 17222063432103834911, // 34^-24 12388787997209523031, // 34^-18 17823888367951909878, // 34^-12 12821714142851132552, // 34^-6 9223372036854775808, // 34^0 13269768890872758272, // 34^6 9545682734772404224, // 34^12 13733480910222387686, // 34^18 9879256578703990224, // 34^24 14213397344182222761, // 34^30 10224487159240697338, // 34^36 14710084455954213119, // 34^42 10581781820995279550, // 34^48 15224128296805573036, // 34^54 10951562143236309252, // 34^60 15756135397562640779, // 34^66 11334264437318166304, // 34^72 16306733484268988021, // 34^78 11730340261493716029, // 34^84 16876572218852198941, // 34^90 12140256953717114113, // 34^96 17466323965673246884, // 34^102 12564498183065403345, // 34^108 18076684584862935827, // 34^114 13003564520429535778, // 34^120 9354187126690740272, // 34^126 13457974029148190318, // 34^132 9681069157385005207, // 34^138 13928262876281286641, // 34^144 10019374079298318020, // 34^150 14414985965244449544, // 34^156 10369501065317377529, // 34^162 14918717590550882042, // 34^168 10731863237423767546, // 34^174 15440052115433190547, // 34^180 11106888154145020298, // 34^186 15979604673144701925, // 34^192 11495018315039655259, // 34^198 ]; const BASE34_SMALL_INT_POWERS: [u64; 6] = [1, 34, 1156, 39304, 1336336, 45435424]; const BASE34_STEP: i32 = 6; const BASE34_BIAS: i32 = 228; const BASE34_LOG2_MULT: i64 = 333412; const BASE34_LOG2_SHIFT: i32 = 16; // BASE35 const BASE35_SMALL_MANTISSA: [u64; 6] = [ 9223372036854775808, // 35^0 10088063165309911040, // 35^1 11033819087057715200, // 35^2 12068239626469376000, // 35^3 13199637091450880000, // 35^4 14437103068774400000, // 35^5 ]; const BASE35_LARGE_MANTISSA: [u64; 71] = [ 11348773864264802781, // 35^-222 9714654125541636184, // 35^-216 16631665395337738380, // 35^-210 14236857547774631404, // 35^-204 12186880148060573338, // 35^-198 10432080762542161338, // 35^-192 17859912908640730010, // 35^-186 15288248642090717076, // 35^-180 13086880531724678972, // 35^-174 11202489314578100722, // 35^-168 9589433214356533221, // 35^-162 16417284907013989533, // 35^-156 14053345890899718904, // 35^-150 12029792492965214691, // 35^-144 10297612294415481616, // 35^-138 17629700433836653197, // 35^-132 15091184660126225295, // 35^-126 12918191962520288360, // 35^-120 11058090357972464737, // 35^-114 9465826388078148767, // 35^-108 16205667761547463659, // 35^-102 13872199680760223069, // 35^-96 11874729681889289960, // 35^-90 10164877111271147984, // 35^-84 17402455374597619654, // 35^-78 14896660812999728329, // 35^-72 12751677771947325078, // 35^-66 10915552689343391453, // 35^-60 9343812841314943660, // 35^-54 15996778339727633381, // 35^-48 13693388426986467236, // 35^-42 11721665614797754707, // 35^-36 10033852871240677221, // 35^-30 17178139481236495112, // 35^-24 14704644358629538426, // 35^-18 12587309932484688516, // 35^-12 10774852316876721446, // 35^-6 9223372036854775808, // 35^0 15790581481472000000, // 35^6 13516882032226562500, // 35^12 11570574528082381959, // 35^18 9904517520440015906, // 35^24 16956714997100751955, // 35^30 14515102976976096155, // 35^36 12425060777883196253, // 35^42 10635965558010358334, // 35^48 18208967404416189641, // 35^54 15587042479907979542, // 35^60 13342650787080448100, // 35^66 11421430990225254489, // 35^72 9776849289257450184, // 35^78 16738144652217302890, // 35^84 14328004764601889967, // 35^90 12264902998508825496, // 35^96 10498869035448040891, // 35^102 17974255652391389054, // 35^108 15386127075531072702, // 35^114 13170665365099231511, // 35^120 11274209897518154234, // 35^126 9650826688689364000, // 35^132 16522391657019252092, // 35^138 14143318229301497845, // 35^144 12106809636745979660, // 35^150 10363539673224497244, // 35^156 17742569311160898016, // 35^162 15187801450438335382, // 35^168 13000896817848986534, // 35^174 11128886469837128365, // 35^180 9526428506723229038, // 35^186 16309419696153507876, // 35^192 13961012284800847178, // 35^198 ]; const BASE35_SMALL_INT_POWERS: [u64; 6] = [1, 35, 1225, 42875, 1500625, 52521875]; const BASE35_STEP: i32 = 6; const BASE35_BIAS: i32 = 222; const BASE35_LOG2_MULT: i64 = 336153; const BASE35_LOG2_SHIFT: i32 = 16; // BASE36 const BASE36_SMALL_MANTISSA: [u64; 6] = [ 9223372036854775808, // 36^0 10376293541461622784, // 36^1 11673330234144325632, // 36^2 13132496513412366336, // 36^3 14774058577588912128, // 36^4 16620815899787526144, // 36^5 ]; const BASE36_LARGE_MANTISSA: [u64; 71] = [ 11172994339528645078, // 36^-222 11325430459582219446, // 36^-216 11479946305982273645, // 36^-210 11636570252986002899, // 36^-204 11795331061968106016, // 36^-198 11956257886702331980, // 36^-192 12119380278715084095, // 36^-186 12284728192712064755, // 36^-180 12452331992078957377, // 36^-174 12622222454457155586, // 36^-168 12794430777395563548, // 36^-162 12968988584079505325, // 36^-156 13145927929137795237, // 36^-150 13325281304529035642, // 36^-144 13507081645508223020, // 36^-138 13691362336674758052, // 36^-132 13878157218102970303, // 36^-126 14067500591556283265, // 36^-120 14259427226786160917, // 36^-114 14453972367916992462, // 36^-108 14651171739918087751, // 36^-102 14851061555163971849, // 36^-96 15053678520084183432, // 36^-90 15259059841903798156, // 36^-84 15467243235475914756, // 36^-78 15678266930207358578, // 36^-72 15892169677078874302, // 36^-66 16108990755761097026, // 36^-60 16328769981827608423, // 36^-54 16551547714066402526, // 36^-48 16777364861891103792, // 36^-42 17006262892853298360, // 36^-36 17238283840257358043, // 36^-30 17473470310879155380, // 36^-24 17711865492790087155, // 36^-18 17953513163287843146, // 36^-12 18198457696935376453, // 36^-6 9223372036854775808, // 36^0 9349208943630483456, // 36^6 9476762676643233792, // 36^12 9606056659007943744, // 36^18 9737114633407288801, // 36^24 9869960666451650558, // 36^30 10004619153098548172, // 36^36 10141114821132365302, // 36^42 10279472735705195138, // 36^48 10419718303939637392, // 36^54 10561877279594392463, // 36^60 10705975767793509530, // 36^66 10852040229820157048, // 36^72 11000097487975795902, // 36^78 11150174730505647564, // 36^84 11302299516591361707, // 36^90 11456499781411800112, // 36^96 11612803841272866179, // 36^102 11771240398807322073, // 36^108 11931838548245548344, // 36^114 12094627780758213915, // 36^120 12259637989871837542, // 36^126 12426899476958235198, // 36^132 12596442956798861450, // 36^138 12768299563225066619, // 36^144 12942500854835305460, // 36^150 13119078820790347231, // 36^156 13298065886687551351, // 36^162 13479494920515287357, // 36^168 13663399238688592583, // 36^174 13849812612167175924, // 36^180 14038769272656891137, // 36^186 14230303918895818486, // 36^192 14424451723026109070, // 36^198 ]; const BASE36_SMALL_INT_POWERS: [u64; 6] = [1, 36, 1296, 46656, 1679616, 60466176]; const BASE36_STEP: i32 = 6; const BASE36_BIAS: i32 = 222; const BASE36_LOG2_MULT: i64 = 22204658804; const BASE36_LOG2_SHIFT: i32 = 32; lexical-parse-float-0.8.5/src/table_binary.rs000064400000000000000000000155430072674642500173220ustar 00000000000000//! Pre-computed tables for writing non-decimal strings. #![cfg(feature = "power-of-two")] #![cfg(not(feature = "compact"))] #![doc(hidden)] #[cfg(not(feature = "radix"))] use crate::table_decimal::*; #[cfg(not(feature = "radix"))] use core::hint; #[cfg(not(feature = "radix"))] use lexical_util::assert::debug_assert_radix; use lexical_util::num::Float; // HELPERS // ------- /// Get lookup table for small int powers. /// /// # Safety /// /// Safe as long as the radix provided is valid, and exponent is smaller /// than the table for the radix. #[inline] #[cfg(not(feature = "radix"))] pub unsafe fn get_small_int_power(exponent: usize, radix: u32) -> u64 { // NOTE: don't check the radix since we also use it for half radix, or 5. unsafe { match radix { 2 => get_small_int_power2(exponent), 4 => get_small_int_power4(exponent), 5 => get_small_int_power5(exponent), 8 => get_small_int_power8(exponent), 10 => get_small_int_power10(exponent), 16 => get_small_int_power16(exponent), 32 => get_small_int_power32(exponent), _ => hint::unreachable_unchecked(), } } } /// Get lookup table for small f32 powers. /// /// # Safety /// /// Safe as long as the radix provided is valid, and exponent is smaller /// than the table for the radix. #[inline] #[cfg(not(feature = "radix"))] pub unsafe fn get_small_f32_power(exponent: usize, radix: u32) -> f32 { debug_assert_radix(radix); unsafe { match radix { 2 => get_small_f32_power2(exponent), 4 => get_small_f32_power4(exponent), 8 => get_small_f32_power8(exponent), 10 => get_small_f32_power10(exponent), 16 => get_small_f32_power16(exponent), 32 => get_small_f32_power32(exponent), _ => hint::unreachable_unchecked(), } } } /// Get lookup table for small f64 powers. /// /// # Safety /// /// Safe as long as the radix provided is valid, and exponent is smaller /// than the table for the radix. #[inline] #[cfg(not(feature = "radix"))] pub unsafe fn get_small_f64_power(exponent: usize, radix: u32) -> f64 { debug_assert_radix(radix); unsafe { match radix { 2 => get_small_f64_power2(exponent), 4 => get_small_f64_power4(exponent), 8 => get_small_f64_power8(exponent), 10 => get_small_f64_power10(exponent), 16 => get_small_f64_power16(exponent), 32 => get_small_f64_power32(exponent), _ => hint::unreachable_unchecked(), } } } // NOTE: // These functions use the fact that **all** powers-of-two // can be exactly represented and cheaply using bitshifts for // integers, or by setting the exponent directly. /// Get pre-computed int power of 2. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_int_power2(exponent: usize) -> u64 { 1 << exponent } /// Get pre-computed f32 power of 2. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_f32_power2(exponent: usize) -> f32 { // Can't handle values above the denormal size. debug_assert!(exponent as i32 <= f32::EXPONENT_BIAS - f32::MANTISSA_SIZE); let shift = (f32::EXPONENT_BIAS - f32::MANTISSA_SIZE) as u32; let bits = (exponent as u32 + shift) << f32::MANTISSA_SIZE; f32::from_bits(bits) } /// Get pre-computed f64 power of 2. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_f64_power2(exponent: usize) -> f64 { // Can't handle values above the denormal size. debug_assert!(exponent as i32 <= f64::EXPONENT_BIAS - f64::MANTISSA_SIZE); let shift = (f64::EXPONENT_BIAS - f64::MANTISSA_SIZE) as u64; let bits = (exponent as u64 + shift) << f64::MANTISSA_SIZE; f64::from_bits(bits) } /// Get pre-computed int power of 4. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_int_power4(exponent: usize) -> u64 { unsafe { get_small_int_power2(2 * exponent) } } /// Get pre-computed f32 power of 4. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_f32_power4(exponent: usize) -> f32 { unsafe { get_small_f32_power2(2 * exponent) } } /// Get pre-computed f64 power of 4. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_f64_power4(exponent: usize) -> f64 { unsafe { get_small_f64_power2(2 * exponent) } } /// Get pre-computed int power of 8. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_int_power8(exponent: usize) -> u64 { unsafe { get_small_int_power2(3 * exponent) } } /// Get pre-computed f32 power of 8. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_f32_power8(exponent: usize) -> f32 { unsafe { get_small_f32_power2(3 * exponent) } } /// Get pre-computed f64 power of 8. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_f64_power8(exponent: usize) -> f64 { unsafe { get_small_f64_power2(3 * exponent) } } /// Get pre-computed int power of 16. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_int_power16(exponent: usize) -> u64 { unsafe { get_small_int_power2(4 * exponent) } } /// Get pre-computed f32 power of 16. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_f32_power16(exponent: usize) -> f32 { unsafe { get_small_f32_power2(4 * exponent) } } /// Get pre-computed f64 power of 16. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_f64_power16(exponent: usize) -> f64 { unsafe { get_small_f64_power2(4 * exponent) } } /// Get pre-computed int power of 32. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_int_power32(exponent: usize) -> u64 { unsafe { get_small_int_power2(5 * exponent) } } /// Get pre-computed f32 power of 32. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_f32_power32(exponent: usize) -> f32 { unsafe { get_small_f32_power2(5 * exponent) } } /// Get pre-computed f64 power of 32. /// /// # Safety /// /// Always safe, just marked unsafe for API compatibility. #[inline(always)] pub unsafe fn get_small_f64_power32(exponent: usize) -> f64 { unsafe { get_small_f64_power2(5 * exponent) } } lexical-parse-float-0.8.5/src/table_decimal.rs000064400000000000000000000124210072674642500174240ustar 00000000000000//! Pre-computed tables for writing decimal strings. #![doc(hidden)] #![cfg(not(feature = "compact"))] #[cfg(not(feature = "radix"))] use crate::bigint::Limb; use crate::limits::{f32_exponent_limit, f64_exponent_limit, f64_mantissa_limit, u64_power_limit}; #[cfg(not(feature = "power-of-two"))] use lexical_util::assert::debug_assert_radix; use static_assertions::const_assert; // HELPERS // ------- /// Get lookup table for small int powers. /// /// # Safety /// /// Safe as long as the radix provided is valid, and exponent is smaller /// than the table for the radix. #[inline] #[cfg(not(feature = "power-of-two"))] pub unsafe fn get_small_int_power(exponent: usize, radix: u32) -> u64 { // NOTE: don't check the radix since we also use it for half radix, or 5. match radix { 5 => unsafe { get_small_int_power5(exponent) }, 10 => unsafe { get_small_int_power10(exponent) }, _ => unreachable!(), } } /// Get lookup table for small f32 powers. /// /// # Safety /// /// Safe as long as the radix provided is valid, and exponent is smaller /// than the table for the radix. #[inline] #[cfg(not(feature = "power-of-two"))] pub unsafe fn get_small_f32_power(exponent: usize, radix: u32) -> f32 { debug_assert_radix(radix); unsafe { get_small_f32_power10(exponent) } } /// Get lookup table for small f64 powers. /// /// # Safety /// /// Safe as long as the radix provided is valid, and exponent is smaller /// than the table for the radix. #[inline] #[cfg(not(feature = "power-of-two"))] pub unsafe fn get_small_f64_power(exponent: usize, radix: u32) -> f64 { debug_assert_radix(radix); unsafe { get_small_f64_power10(exponent) } } /// Get pre-computed power for a large power of radix. #[cfg(not(feature = "radix"))] pub const fn get_large_int_power(_: u32) -> (&'static [Limb], u32) { (&LARGE_POW5, LARGE_POW5_STEP) } /// Get pre-computed int power of 5. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW5.len()`. #[inline(always)] pub unsafe fn get_small_int_power5(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW5[exponent]) } } /// Get pre-computed int power of 10. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW10.len()`. #[inline(always)] pub unsafe fn get_small_int_power10(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW10[exponent]) } } /// Get pre-computed f32 power of 10. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW10.len()`. #[inline(always)] pub unsafe fn get_small_f32_power10(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW10[exponent]) } } /// Get pre-computed f64 power of 10. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW10.len()`. #[inline(always)] pub unsafe fn get_small_f64_power10(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW10[exponent]) } } // TABLES // ------ /// Pre-computed, small powers-of-5. pub const SMALL_INT_POW5: [u64; 28] = [ 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125, 6103515625, 30517578125, 152587890625, 762939453125, 3814697265625, 19073486328125, 95367431640625, 476837158203125, 2384185791015625, 11920928955078125, 59604644775390625, 298023223876953125, 1490116119384765625, 7450580596923828125, ]; const_assert!(SMALL_INT_POW5.len() > f64_mantissa_limit(5) as usize); const_assert!(SMALL_INT_POW5.len() == u64_power_limit(5) as usize + 1); /// Pre-computed, small powers-of-10. pub const SMALL_INT_POW10: [u64; 20] = [ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000, 10000000000000000000, ]; const_assert!(SMALL_INT_POW10.len() > f64_mantissa_limit(10) as usize); const_assert!(SMALL_INT_POW10.len() == u64_power_limit(10) as usize + 1); /// Pre-computed, small powers-of-10. pub const SMALL_F32_POW10: [f32; 16] = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.]; const_assert!(SMALL_F32_POW10.len() > f32_exponent_limit(10).1 as usize); /// Pre-computed, small powers-of-10. pub const SMALL_F64_POW10: [f64; 32] = [ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0., ]; const_assert!(SMALL_F64_POW10.len() > f64_exponent_limit(10).1 as usize); /// Pre-computed large power-of-5 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW5: [u32; 10] = [ 4279965485, 329373468, 4020270615, 2137533757, 4287402176, 1057042919, 1071430142, 2440757623, 381945767, 46164893, ]; /// Pre-computed large power-of-5 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW5: [u64; 5] = [ 1414648277510068013, 9180637584431281687, 4539964771860779200, 10482974169319127550, 198276706040285095, ]; /// Step for large power-of-5 for 32-bit limbs. pub const LARGE_POW5_STEP: u32 = 135; lexical-parse-float-0.8.5/src/table_large.rs000064400000000000000000000005150072674642500171210ustar 00000000000000//! Pre-computed large value tables for writing float strings. #![doc(hidden)] // Re-export all the feature-specific files. #[cfg(feature = "compact")] pub use crate::table_bellerophon_decimal::*; #[cfg(feature = "radix")] pub use crate::table_bellerophon_radix::*; #[cfg(not(feature = "compact"))] pub use crate::table_lemire::*; lexical-parse-float-0.8.5/src/table_lemire.rs000064400000000000000000001100770072674642500173110ustar 00000000000000//! Pre-computed tables powers-of-5 for extended-precision representations. //! //! These tables enable fast scaling of the significant digits //! of a float to the decimal exponent, with minimal rounding //! errors, in a 128 or 192-bit representation. //! //! DO NOT MODIFY: Generated by `etc/lemire_table.py` //! //! This adapted from the Rust implementation, based on the fast-float-rust //! implementation, and is similarly subject to an Apache2.0/MIT license. #![doc(hidden)] #![cfg(not(feature = "compact"))] pub const SMALLEST_POWER_OF_FIVE: i32 = -342; pub const LARGEST_POWER_OF_FIVE: i32 = 308; pub const N_POWERS_OF_FIVE: usize = (LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize; // Use static to avoid long compile times: Rust compiler errors // can have the entire table compiled multiple times, and then // emit code multiple times, even if it's stripped out in // the final binary. #[rustfmt::skip] pub static POWER_OF_FIVE_128: [(u64, u64); N_POWERS_OF_FIVE] = [ (0xeef453d6923bd65a, 0x113faa2906a13b3f), // 5^-342 (0x9558b4661b6565f8, 0x4ac7ca59a424c507), // 5^-341 (0xbaaee17fa23ebf76, 0x5d79bcf00d2df649), // 5^-340 (0xe95a99df8ace6f53, 0xf4d82c2c107973dc), // 5^-339 (0x91d8a02bb6c10594, 0x79071b9b8a4be869), // 5^-338 (0xb64ec836a47146f9, 0x9748e2826cdee284), // 5^-337 (0xe3e27a444d8d98b7, 0xfd1b1b2308169b25), // 5^-336 (0x8e6d8c6ab0787f72, 0xfe30f0f5e50e20f7), // 5^-335 (0xb208ef855c969f4f, 0xbdbd2d335e51a935), // 5^-334 (0xde8b2b66b3bc4723, 0xad2c788035e61382), // 5^-333 (0x8b16fb203055ac76, 0x4c3bcb5021afcc31), // 5^-332 (0xaddcb9e83c6b1793, 0xdf4abe242a1bbf3d), // 5^-331 (0xd953e8624b85dd78, 0xd71d6dad34a2af0d), // 5^-330 (0x87d4713d6f33aa6b, 0x8672648c40e5ad68), // 5^-329 (0xa9c98d8ccb009506, 0x680efdaf511f18c2), // 5^-328 (0xd43bf0effdc0ba48, 0x212bd1b2566def2), // 5^-327 (0x84a57695fe98746d, 0x14bb630f7604b57), // 5^-326 (0xa5ced43b7e3e9188, 0x419ea3bd35385e2d), // 5^-325 (0xcf42894a5dce35ea, 0x52064cac828675b9), // 5^-324 (0x818995ce7aa0e1b2, 0x7343efebd1940993), // 5^-323 (0xa1ebfb4219491a1f, 0x1014ebe6c5f90bf8), // 5^-322 (0xca66fa129f9b60a6, 0xd41a26e077774ef6), // 5^-321 (0xfd00b897478238d0, 0x8920b098955522b4), // 5^-320 (0x9e20735e8cb16382, 0x55b46e5f5d5535b0), // 5^-319 (0xc5a890362fddbc62, 0xeb2189f734aa831d), // 5^-318 (0xf712b443bbd52b7b, 0xa5e9ec7501d523e4), // 5^-317 (0x9a6bb0aa55653b2d, 0x47b233c92125366e), // 5^-316 (0xc1069cd4eabe89f8, 0x999ec0bb696e840a), // 5^-315 (0xf148440a256e2c76, 0xc00670ea43ca250d), // 5^-314 (0x96cd2a865764dbca, 0x380406926a5e5728), // 5^-313 (0xbc807527ed3e12bc, 0xc605083704f5ecf2), // 5^-312 (0xeba09271e88d976b, 0xf7864a44c633682e), // 5^-311 (0x93445b8731587ea3, 0x7ab3ee6afbe0211d), // 5^-310 (0xb8157268fdae9e4c, 0x5960ea05bad82964), // 5^-309 (0xe61acf033d1a45df, 0x6fb92487298e33bd), // 5^-308 (0x8fd0c16206306bab, 0xa5d3b6d479f8e056), // 5^-307 (0xb3c4f1ba87bc8696, 0x8f48a4899877186c), // 5^-306 (0xe0b62e2929aba83c, 0x331acdabfe94de87), // 5^-305 (0x8c71dcd9ba0b4925, 0x9ff0c08b7f1d0b14), // 5^-304 (0xaf8e5410288e1b6f, 0x7ecf0ae5ee44dd9), // 5^-303 (0xdb71e91432b1a24a, 0xc9e82cd9f69d6150), // 5^-302 (0x892731ac9faf056e, 0xbe311c083a225cd2), // 5^-301 (0xab70fe17c79ac6ca, 0x6dbd630a48aaf406), // 5^-300 (0xd64d3d9db981787d, 0x92cbbccdad5b108), // 5^-299 (0x85f0468293f0eb4e, 0x25bbf56008c58ea5), // 5^-298 (0xa76c582338ed2621, 0xaf2af2b80af6f24e), // 5^-297 (0xd1476e2c07286faa, 0x1af5af660db4aee1), // 5^-296 (0x82cca4db847945ca, 0x50d98d9fc890ed4d), // 5^-295 (0xa37fce126597973c, 0xe50ff107bab528a0), // 5^-294 (0xcc5fc196fefd7d0c, 0x1e53ed49a96272c8), // 5^-293 (0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7a), // 5^-292 (0x9faacf3df73609b1, 0x77b191618c54e9ac), // 5^-291 (0xc795830d75038c1d, 0xd59df5b9ef6a2417), // 5^-290 (0xf97ae3d0d2446f25, 0x4b0573286b44ad1d), // 5^-289 (0x9becce62836ac577, 0x4ee367f9430aec32), // 5^-288 (0xc2e801fb244576d5, 0x229c41f793cda73f), // 5^-287 (0xf3a20279ed56d48a, 0x6b43527578c1110f), // 5^-286 (0x9845418c345644d6, 0x830a13896b78aaa9), // 5^-285 (0xbe5691ef416bd60c, 0x23cc986bc656d553), // 5^-284 (0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa8), // 5^-283 (0x94b3a202eb1c3f39, 0x7bf7d71432f3d6a9), // 5^-282 (0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc53), // 5^-281 (0xe858ad248f5c22c9, 0xd1b3400f8f9cff68), // 5^-280 (0x91376c36d99995be, 0x23100809b9c21fa1), // 5^-279 (0xb58547448ffffb2d, 0xabd40a0c2832a78a), // 5^-278 (0xe2e69915b3fff9f9, 0x16c90c8f323f516c), // 5^-277 (0x8dd01fad907ffc3b, 0xae3da7d97f6792e3), // 5^-276 (0xb1442798f49ffb4a, 0x99cd11cfdf41779c), // 5^-275 (0xdd95317f31c7fa1d, 0x40405643d711d583), // 5^-274 (0x8a7d3eef7f1cfc52, 0x482835ea666b2572), // 5^-273 (0xad1c8eab5ee43b66, 0xda3243650005eecf), // 5^-272 (0xd863b256369d4a40, 0x90bed43e40076a82), // 5^-271 (0x873e4f75e2224e68, 0x5a7744a6e804a291), // 5^-270 (0xa90de3535aaae202, 0x711515d0a205cb36), // 5^-269 (0xd3515c2831559a83, 0xd5a5b44ca873e03), // 5^-268 (0x8412d9991ed58091, 0xe858790afe9486c2), // 5^-267 (0xa5178fff668ae0b6, 0x626e974dbe39a872), // 5^-266 (0xce5d73ff402d98e3, 0xfb0a3d212dc8128f), // 5^-265 (0x80fa687f881c7f8e, 0x7ce66634bc9d0b99), // 5^-264 (0xa139029f6a239f72, 0x1c1fffc1ebc44e80), // 5^-263 (0xc987434744ac874e, 0xa327ffb266b56220), // 5^-262 (0xfbe9141915d7a922, 0x4bf1ff9f0062baa8), // 5^-261 (0x9d71ac8fada6c9b5, 0x6f773fc3603db4a9), // 5^-260 (0xc4ce17b399107c22, 0xcb550fb4384d21d3), // 5^-259 (0xf6019da07f549b2b, 0x7e2a53a146606a48), // 5^-258 (0x99c102844f94e0fb, 0x2eda7444cbfc426d), // 5^-257 (0xc0314325637a1939, 0xfa911155fefb5308), // 5^-256 (0xf03d93eebc589f88, 0x793555ab7eba27ca), // 5^-255 (0x96267c7535b763b5, 0x4bc1558b2f3458de), // 5^-254 (0xbbb01b9283253ca2, 0x9eb1aaedfb016f16), // 5^-253 (0xea9c227723ee8bcb, 0x465e15a979c1cadc), // 5^-252 (0x92a1958a7675175f, 0xbfacd89ec191ec9), // 5^-251 (0xb749faed14125d36, 0xcef980ec671f667b), // 5^-250 (0xe51c79a85916f484, 0x82b7e12780e7401a), // 5^-249 (0x8f31cc0937ae58d2, 0xd1b2ecb8b0908810), // 5^-248 (0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa15), // 5^-247 (0xdfbdcece67006ac9, 0x67a791e093e1d49a), // 5^-246 (0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e0), // 5^-245 (0xaecc49914078536d, 0x58fae9f773886e18), // 5^-244 (0xda7f5bf590966848, 0xaf39a475506a899e), // 5^-243 (0x888f99797a5e012d, 0x6d8406c952429603), // 5^-242 (0xaab37fd7d8f58178, 0xc8e5087ba6d33b83), // 5^-241 (0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a64), // 5^-240 (0x855c3be0a17fcd26, 0x5cf2eea09a55067f), // 5^-239 (0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481e), // 5^-238 (0xd0601d8efc57b08b, 0xf13b94daf124da26), // 5^-237 (0x823c12795db6ce57, 0x76c53d08d6b70858), // 5^-236 (0xa2cb1717b52481ed, 0x54768c4b0c64ca6e), // 5^-235 (0xcb7ddcdda26da268, 0xa9942f5dcf7dfd09), // 5^-234 (0xfe5d54150b090b02, 0xd3f93b35435d7c4c), // 5^-233 (0x9efa548d26e5a6e1, 0xc47bc5014a1a6daf), // 5^-232 (0xc6b8e9b0709f109a, 0x359ab6419ca1091b), // 5^-231 (0xf867241c8cc6d4c0, 0xc30163d203c94b62), // 5^-230 (0x9b407691d7fc44f8, 0x79e0de63425dcf1d), // 5^-229 (0xc21094364dfb5636, 0x985915fc12f542e4), // 5^-228 (0xf294b943e17a2bc4, 0x3e6f5b7b17b2939d), // 5^-227 (0x979cf3ca6cec5b5a, 0xa705992ceecf9c42), // 5^-226 (0xbd8430bd08277231, 0x50c6ff782a838353), // 5^-225 (0xece53cec4a314ebd, 0xa4f8bf5635246428), // 5^-224 (0x940f4613ae5ed136, 0x871b7795e136be99), // 5^-223 (0xb913179899f68584, 0x28e2557b59846e3f), // 5^-222 (0xe757dd7ec07426e5, 0x331aeada2fe589cf), // 5^-221 (0x9096ea6f3848984f, 0x3ff0d2c85def7621), // 5^-220 (0xb4bca50b065abe63, 0xfed077a756b53a9), // 5^-219 (0xe1ebce4dc7f16dfb, 0xd3e8495912c62894), // 5^-218 (0x8d3360f09cf6e4bd, 0x64712dd7abbbd95c), // 5^-217 (0xb080392cc4349dec, 0xbd8d794d96aacfb3), // 5^-216 (0xdca04777f541c567, 0xecf0d7a0fc5583a0), // 5^-215 (0x89e42caaf9491b60, 0xf41686c49db57244), // 5^-214 (0xac5d37d5b79b6239, 0x311c2875c522ced5), // 5^-213 (0xd77485cb25823ac7, 0x7d633293366b828b), // 5^-212 (0x86a8d39ef77164bc, 0xae5dff9c02033197), // 5^-211 (0xa8530886b54dbdeb, 0xd9f57f830283fdfc), // 5^-210 (0xd267caa862a12d66, 0xd072df63c324fd7b), // 5^-209 (0x8380dea93da4bc60, 0x4247cb9e59f71e6d), // 5^-208 (0xa46116538d0deb78, 0x52d9be85f074e608), // 5^-207 (0xcd795be870516656, 0x67902e276c921f8b), // 5^-206 (0x806bd9714632dff6, 0xba1cd8a3db53b6), // 5^-205 (0xa086cfcd97bf97f3, 0x80e8a40eccd228a4), // 5^-204 (0xc8a883c0fdaf7df0, 0x6122cd128006b2cd), // 5^-203 (0xfad2a4b13d1b5d6c, 0x796b805720085f81), // 5^-202 (0x9cc3a6eec6311a63, 0xcbe3303674053bb0), // 5^-201 (0xc3f490aa77bd60fc, 0xbedbfc4411068a9c), // 5^-200 (0xf4f1b4d515acb93b, 0xee92fb5515482d44), // 5^-199 (0x991711052d8bf3c5, 0x751bdd152d4d1c4a), // 5^-198 (0xbf5cd54678eef0b6, 0xd262d45a78a0635d), // 5^-197 (0xef340a98172aace4, 0x86fb897116c87c34), // 5^-196 (0x9580869f0e7aac0e, 0xd45d35e6ae3d4da0), // 5^-195 (0xbae0a846d2195712, 0x8974836059cca109), // 5^-194 (0xe998d258869facd7, 0x2bd1a438703fc94b), // 5^-193 (0x91ff83775423cc06, 0x7b6306a34627ddcf), // 5^-192 (0xb67f6455292cbf08, 0x1a3bc84c17b1d542), // 5^-191 (0xe41f3d6a7377eeca, 0x20caba5f1d9e4a93), // 5^-190 (0x8e938662882af53e, 0x547eb47b7282ee9c), // 5^-189 (0xb23867fb2a35b28d, 0xe99e619a4f23aa43), // 5^-188 (0xdec681f9f4c31f31, 0x6405fa00e2ec94d4), // 5^-187 (0x8b3c113c38f9f37e, 0xde83bc408dd3dd04), // 5^-186 (0xae0b158b4738705e, 0x9624ab50b148d445), // 5^-185 (0xd98ddaee19068c76, 0x3badd624dd9b0957), // 5^-184 (0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d6), // 5^-183 (0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4c), // 5^-182 (0xd47487cc8470652b, 0x7647c3200069671f), // 5^-181 (0x84c8d4dfd2c63f3b, 0x29ecd9f40041e073), // 5^-180 (0xa5fb0a17c777cf09, 0xf468107100525890), // 5^-179 (0xcf79cc9db955c2cc, 0x7182148d4066eeb4), // 5^-178 (0x81ac1fe293d599bf, 0xc6f14cd848405530), // 5^-177 (0xa21727db38cb002f, 0xb8ada00e5a506a7c), // 5^-176 (0xca9cf1d206fdc03b, 0xa6d90811f0e4851c), // 5^-175 (0xfd442e4688bd304a, 0x908f4a166d1da663), // 5^-174 (0x9e4a9cec15763e2e, 0x9a598e4e043287fe), // 5^-173 (0xc5dd44271ad3cdba, 0x40eff1e1853f29fd), // 5^-172 (0xf7549530e188c128, 0xd12bee59e68ef47c), // 5^-171 (0x9a94dd3e8cf578b9, 0x82bb74f8301958ce), // 5^-170 (0xc13a148e3032d6e7, 0xe36a52363c1faf01), // 5^-169 (0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac1), // 5^-168 (0x96f5600f15a7b7e5, 0x29ab103a5ef8c0b9), // 5^-167 (0xbcb2b812db11a5de, 0x7415d448f6b6f0e7), // 5^-166 (0xebdf661791d60f56, 0x111b495b3464ad21), // 5^-165 (0x936b9fcebb25c995, 0xcab10dd900beec34), // 5^-164 (0xb84687c269ef3bfb, 0x3d5d514f40eea742), // 5^-163 (0xe65829b3046b0afa, 0xcb4a5a3112a5112), // 5^-162 (0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ab), // 5^-161 (0xb3f4e093db73a093, 0x59ed216765690f56), // 5^-160 (0xe0f218b8d25088b8, 0x306869c13ec3532c), // 5^-159 (0x8c974f7383725573, 0x1e414218c73a13fb), // 5^-158 (0xafbd2350644eeacf, 0xe5d1929ef90898fa), // 5^-157 (0xdbac6c247d62a583, 0xdf45f746b74abf39), // 5^-156 (0x894bc396ce5da772, 0x6b8bba8c328eb783), // 5^-155 (0xab9eb47c81f5114f, 0x66ea92f3f326564), // 5^-154 (0xd686619ba27255a2, 0xc80a537b0efefebd), // 5^-153 (0x8613fd0145877585, 0xbd06742ce95f5f36), // 5^-152 (0xa798fc4196e952e7, 0x2c48113823b73704), // 5^-151 (0xd17f3b51fca3a7a0, 0xf75a15862ca504c5), // 5^-150 (0x82ef85133de648c4, 0x9a984d73dbe722fb), // 5^-149 (0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebba), // 5^-148 (0xcc963fee10b7d1b3, 0x318df905079926a8), // 5^-147 (0xffbbcfe994e5c61f, 0xfdf17746497f7052), // 5^-146 (0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa633), // 5^-145 (0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc0), // 5^-144 (0xf9bd690a1b68637b, 0x3dfdce7aa3c673b0), // 5^-143 (0x9c1661a651213e2d, 0x6bea10ca65c084e), // 5^-142 (0xc31bfa0fe5698db8, 0x486e494fcff30a62), // 5^-141 (0xf3e2f893dec3f126, 0x5a89dba3c3efccfa), // 5^-140 (0x986ddb5c6b3a76b7, 0xf89629465a75e01c), // 5^-139 (0xbe89523386091465, 0xf6bbb397f1135823), // 5^-138 (0xee2ba6c0678b597f, 0x746aa07ded582e2c), // 5^-137 (0x94db483840b717ef, 0xa8c2a44eb4571cdc), // 5^-136 (0xba121a4650e4ddeb, 0x92f34d62616ce413), // 5^-135 (0xe896a0d7e51e1566, 0x77b020baf9c81d17), // 5^-134 (0x915e2486ef32cd60, 0xace1474dc1d122e), // 5^-133 (0xb5b5ada8aaff80b8, 0xd819992132456ba), // 5^-132 (0xe3231912d5bf60e6, 0x10e1fff697ed6c69), // 5^-131 (0x8df5efabc5979c8f, 0xca8d3ffa1ef463c1), // 5^-130 (0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb2), // 5^-129 (0xddd0467c64bce4a0, 0xac7cb3f6d05ddbde), // 5^-128 (0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96b), // 5^-127 (0xad4ab7112eb3929d, 0x86c16c98d2c953c6), // 5^-126 (0xd89d64d57a607744, 0xe871c7bf077ba8b7), // 5^-125 (0x87625f056c7c4a8b, 0x11471cd764ad4972), // 5^-124 (0xa93af6c6c79b5d2d, 0xd598e40d3dd89bcf), // 5^-123 (0xd389b47879823479, 0x4aff1d108d4ec2c3), // 5^-122 (0x843610cb4bf160cb, 0xcedf722a585139ba), // 5^-121 (0xa54394fe1eedb8fe, 0xc2974eb4ee658828), // 5^-120 (0xce947a3da6a9273e, 0x733d226229feea32), // 5^-119 (0x811ccc668829b887, 0x806357d5a3f525f), // 5^-118 (0xa163ff802a3426a8, 0xca07c2dcb0cf26f7), // 5^-117 (0xc9bcff6034c13052, 0xfc89b393dd02f0b5), // 5^-116 (0xfc2c3f3841f17c67, 0xbbac2078d443ace2), // 5^-115 (0x9d9ba7832936edc0, 0xd54b944b84aa4c0d), // 5^-114 (0xc5029163f384a931, 0xa9e795e65d4df11), // 5^-113 (0xf64335bcf065d37d, 0x4d4617b5ff4a16d5), // 5^-112 (0x99ea0196163fa42e, 0x504bced1bf8e4e45), // 5^-111 (0xc06481fb9bcf8d39, 0xe45ec2862f71e1d6), // 5^-110 (0xf07da27a82c37088, 0x5d767327bb4e5a4c), // 5^-109 (0x964e858c91ba2655, 0x3a6a07f8d510f86f), // 5^-108 (0xbbe226efb628afea, 0x890489f70a55368b), // 5^-107 (0xeadab0aba3b2dbe5, 0x2b45ac74ccea842e), // 5^-106 (0x92c8ae6b464fc96f, 0x3b0b8bc90012929d), // 5^-105 (0xb77ada0617e3bbcb, 0x9ce6ebb40173744), // 5^-104 (0xe55990879ddcaabd, 0xcc420a6a101d0515), // 5^-103 (0x8f57fa54c2a9eab6, 0x9fa946824a12232d), // 5^-102 (0xb32df8e9f3546564, 0x47939822dc96abf9), // 5^-101 (0xdff9772470297ebd, 0x59787e2b93bc56f7), // 5^-100 (0x8bfbea76c619ef36, 0x57eb4edb3c55b65a), // 5^-99 (0xaefae51477a06b03, 0xede622920b6b23f1), // 5^-98 (0xdab99e59958885c4, 0xe95fab368e45eced), // 5^-97 (0x88b402f7fd75539b, 0x11dbcb0218ebb414), // 5^-96 (0xaae103b5fcd2a881, 0xd652bdc29f26a119), // 5^-95 (0xd59944a37c0752a2, 0x4be76d3346f0495f), // 5^-94 (0x857fcae62d8493a5, 0x6f70a4400c562ddb), // 5^-93 (0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb952), // 5^-92 (0xd097ad07a71f26b2, 0x7e2000a41346a7a7), // 5^-91 (0x825ecc24c873782f, 0x8ed400668c0c28c8), // 5^-90 (0xa2f67f2dfa90563b, 0x728900802f0f32fa), // 5^-89 (0xcbb41ef979346bca, 0x4f2b40a03ad2ffb9), // 5^-88 (0xfea126b7d78186bc, 0xe2f610c84987bfa8), // 5^-87 (0x9f24b832e6b0f436, 0xdd9ca7d2df4d7c9), // 5^-86 (0xc6ede63fa05d3143, 0x91503d1c79720dbb), // 5^-85 (0xf8a95fcf88747d94, 0x75a44c6397ce912a), // 5^-84 (0x9b69dbe1b548ce7c, 0xc986afbe3ee11aba), // 5^-83 (0xc24452da229b021b, 0xfbe85badce996168), // 5^-82 (0xf2d56790ab41c2a2, 0xfae27299423fb9c3), // 5^-81 (0x97c560ba6b0919a5, 0xdccd879fc967d41a), // 5^-80 (0xbdb6b8e905cb600f, 0x5400e987bbc1c920), // 5^-79 (0xed246723473e3813, 0x290123e9aab23b68), // 5^-78 (0x9436c0760c86e30b, 0xf9a0b6720aaf6521), // 5^-77 (0xb94470938fa89bce, 0xf808e40e8d5b3e69), // 5^-76 (0xe7958cb87392c2c2, 0xb60b1d1230b20e04), // 5^-75 (0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c2), // 5^-74 (0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af3), // 5^-73 (0xe2280b6c20dd5232, 0x25c6da63c38de1b0), // 5^-72 (0x8d590723948a535f, 0x579c487e5a38ad0e), // 5^-71 (0xb0af48ec79ace837, 0x2d835a9df0c6d851), // 5^-70 (0xdcdb1b2798182244, 0xf8e431456cf88e65), // 5^-69 (0x8a08f0f8bf0f156b, 0x1b8e9ecb641b58ff), // 5^-68 (0xac8b2d36eed2dac5, 0xe272467e3d222f3f), // 5^-67 (0xd7adf884aa879177, 0x5b0ed81dcc6abb0f), // 5^-66 (0x86ccbb52ea94baea, 0x98e947129fc2b4e9), // 5^-65 (0xa87fea27a539e9a5, 0x3f2398d747b36224), // 5^-64 (0xd29fe4b18e88640e, 0x8eec7f0d19a03aad), // 5^-63 (0x83a3eeeef9153e89, 0x1953cf68300424ac), // 5^-62 (0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd7), // 5^-61 (0xcdb02555653131b6, 0x3792f412cb06794d), // 5^-60 (0x808e17555f3ebf11, 0xe2bbd88bbee40bd0), // 5^-59 (0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec4), // 5^-58 (0xc8de047564d20a8b, 0xf245825a5a445275), // 5^-57 (0xfb158592be068d2e, 0xeed6e2f0f0d56712), // 5^-56 (0x9ced737bb6c4183d, 0x55464dd69685606b), // 5^-55 (0xc428d05aa4751e4c, 0xaa97e14c3c26b886), // 5^-54 (0xf53304714d9265df, 0xd53dd99f4b3066a8), // 5^-53 (0x993fe2c6d07b7fab, 0xe546a8038efe4029), // 5^-52 (0xbf8fdb78849a5f96, 0xde98520472bdd033), // 5^-51 (0xef73d256a5c0f77c, 0x963e66858f6d4440), // 5^-50 (0x95a8637627989aad, 0xdde7001379a44aa8), // 5^-49 (0xbb127c53b17ec159, 0x5560c018580d5d52), // 5^-48 (0xe9d71b689dde71af, 0xaab8f01e6e10b4a6), // 5^-47 (0x9226712162ab070d, 0xcab3961304ca70e8), // 5^-46 (0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d22), // 5^-45 (0xe45c10c42a2b3b05, 0x8cb89a7db77c506a), // 5^-44 (0x8eb98a7a9a5b04e3, 0x77f3608e92adb242), // 5^-43 (0xb267ed1940f1c61c, 0x55f038b237591ed3), // 5^-42 (0xdf01e85f912e37a3, 0x6b6c46dec52f6688), // 5^-41 (0x8b61313bbabce2c6, 0x2323ac4b3b3da015), // 5^-40 (0xae397d8aa96c1b77, 0xabec975e0a0d081a), // 5^-39 (0xd9c7dced53c72255, 0x96e7bd358c904a21), // 5^-38 (0x881cea14545c7575, 0x7e50d64177da2e54), // 5^-37 (0xaa242499697392d2, 0xdde50bd1d5d0b9e9), // 5^-36 (0xd4ad2dbfc3d07787, 0x955e4ec64b44e864), // 5^-35 (0x84ec3c97da624ab4, 0xbd5af13bef0b113e), // 5^-34 (0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58e), // 5^-33 (0xcfb11ead453994ba, 0x67de18eda5814af2), // 5^-32 (0x81ceb32c4b43fcf4, 0x80eacf948770ced7), // 5^-31 (0xa2425ff75e14fc31, 0xa1258379a94d028d), // 5^-30 (0xcad2f7f5359a3b3e, 0x96ee45813a04330), // 5^-29 (0xfd87b5f28300ca0d, 0x8bca9d6e188853fc), // 5^-28 (0x9e74d1b791e07e48, 0x775ea264cf55347e), // 5^-27 (0xc612062576589dda, 0x95364afe032a819e), // 5^-26 (0xf79687aed3eec551, 0x3a83ddbd83f52205), // 5^-25 (0x9abe14cd44753b52, 0xc4926a9672793543), // 5^-24 (0xc16d9a0095928a27, 0x75b7053c0f178294), // 5^-23 (0xf1c90080baf72cb1, 0x5324c68b12dd6339), // 5^-22 (0x971da05074da7bee, 0xd3f6fc16ebca5e04), // 5^-21 (0xbce5086492111aea, 0x88f4bb1ca6bcf585), // 5^-20 (0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6), // 5^-19 (0x9392ee8e921d5d07, 0x3aff322e62439fd0), // 5^-18 (0xb877aa3236a4b449, 0x9befeb9fad487c3), // 5^-17 (0xe69594bec44de15b, 0x4c2ebe687989a9b4), // 5^-16 (0x901d7cf73ab0acd9, 0xf9d37014bf60a11), // 5^-15 (0xb424dc35095cd80f, 0x538484c19ef38c95), // 5^-14 (0xe12e13424bb40e13, 0x2865a5f206b06fba), // 5^-13 (0x8cbccc096f5088cb, 0xf93f87b7442e45d4), // 5^-12 (0xafebff0bcb24aafe, 0xf78f69a51539d749), // 5^-11 (0xdbe6fecebdedd5be, 0xb573440e5a884d1c), // 5^-10 (0x89705f4136b4a597, 0x31680a88f8953031), // 5^-9 (0xabcc77118461cefc, 0xfdc20d2b36ba7c3e), // 5^-8 (0xd6bf94d5e57a42bc, 0x3d32907604691b4d), // 5^-7 (0x8637bd05af6c69b5, 0xa63f9a49c2c1b110), // 5^-6 (0xa7c5ac471b478423, 0xfcf80dc33721d54), // 5^-5 (0xd1b71758e219652b, 0xd3c36113404ea4a9), // 5^-4 (0x83126e978d4fdf3b, 0x645a1cac083126ea), // 5^-3 (0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4), // 5^-2 (0xcccccccccccccccc, 0xcccccccccccccccd), // 5^-1 (0x8000000000000000, 0x0), // 5^0 (0xa000000000000000, 0x0), // 5^1 (0xc800000000000000, 0x0), // 5^2 (0xfa00000000000000, 0x0), // 5^3 (0x9c40000000000000, 0x0), // 5^4 (0xc350000000000000, 0x0), // 5^5 (0xf424000000000000, 0x0), // 5^6 (0x9896800000000000, 0x0), // 5^7 (0xbebc200000000000, 0x0), // 5^8 (0xee6b280000000000, 0x0), // 5^9 (0x9502f90000000000, 0x0), // 5^10 (0xba43b74000000000, 0x0), // 5^11 (0xe8d4a51000000000, 0x0), // 5^12 (0x9184e72a00000000, 0x0), // 5^13 (0xb5e620f480000000, 0x0), // 5^14 (0xe35fa931a0000000, 0x0), // 5^15 (0x8e1bc9bf04000000, 0x0), // 5^16 (0xb1a2bc2ec5000000, 0x0), // 5^17 (0xde0b6b3a76400000, 0x0), // 5^18 (0x8ac7230489e80000, 0x0), // 5^19 (0xad78ebc5ac620000, 0x0), // 5^20 (0xd8d726b7177a8000, 0x0), // 5^21 (0x878678326eac9000, 0x0), // 5^22 (0xa968163f0a57b400, 0x0), // 5^23 (0xd3c21bcecceda100, 0x0), // 5^24 (0x84595161401484a0, 0x0), // 5^25 (0xa56fa5b99019a5c8, 0x0), // 5^26 (0xcecb8f27f4200f3a, 0x0), // 5^27 (0x813f3978f8940984, 0x4000000000000000), // 5^28 (0xa18f07d736b90be5, 0x5000000000000000), // 5^29 (0xc9f2c9cd04674ede, 0xa400000000000000), // 5^30 (0xfc6f7c4045812296, 0x4d00000000000000), // 5^31 (0x9dc5ada82b70b59d, 0xf020000000000000), // 5^32 (0xc5371912364ce305, 0x6c28000000000000), // 5^33 (0xf684df56c3e01bc6, 0xc732000000000000), // 5^34 (0x9a130b963a6c115c, 0x3c7f400000000000), // 5^35 (0xc097ce7bc90715b3, 0x4b9f100000000000), // 5^36 (0xf0bdc21abb48db20, 0x1e86d40000000000), // 5^37 (0x96769950b50d88f4, 0x1314448000000000), // 5^38 (0xbc143fa4e250eb31, 0x17d955a000000000), // 5^39 (0xeb194f8e1ae525fd, 0x5dcfab0800000000), // 5^40 (0x92efd1b8d0cf37be, 0x5aa1cae500000000), // 5^41 (0xb7abc627050305ad, 0xf14a3d9e40000000), // 5^42 (0xe596b7b0c643c719, 0x6d9ccd05d0000000), // 5^43 (0x8f7e32ce7bea5c6f, 0xe4820023a2000000), // 5^44 (0xb35dbf821ae4f38b, 0xdda2802c8a800000), // 5^45 (0xe0352f62a19e306e, 0xd50b2037ad200000), // 5^46 (0x8c213d9da502de45, 0x4526f422cc340000), // 5^47 (0xaf298d050e4395d6, 0x9670b12b7f410000), // 5^48 (0xdaf3f04651d47b4c, 0x3c0cdd765f114000), // 5^49 (0x88d8762bf324cd0f, 0xa5880a69fb6ac800), // 5^50 (0xab0e93b6efee0053, 0x8eea0d047a457a00), // 5^51 (0xd5d238a4abe98068, 0x72a4904598d6d880), // 5^52 (0x85a36366eb71f041, 0x47a6da2b7f864750), // 5^53 (0xa70c3c40a64e6c51, 0x999090b65f67d924), // 5^54 (0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d), // 5^55 (0x82818f1281ed449f, 0xbff8f10e7a8921a4), // 5^56 (0xa321f2d7226895c7, 0xaff72d52192b6a0d), // 5^57 (0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490), // 5^58 (0xfee50b7025c36a08, 0x2f236d04753d5b4), // 5^59 (0x9f4f2726179a2245, 0x1d762422c946590), // 5^60 (0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5), // 5^61 (0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2), // 5^62 (0x9b934c3b330c8577, 0x63cc55f49f88eb2f), // 5^63 (0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb), // 5^64 (0xf316271c7fc3908a, 0x8bef464e3945ef7a), // 5^65 (0x97edd871cfda3a56, 0x97758bf0e3cbb5ac), // 5^66 (0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317), // 5^67 (0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd), // 5^68 (0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a), // 5^69 (0xb975d6b6ee39e436, 0xb3e2fd538e122b44), // 5^70 (0xe7d34c64a9c85d44, 0x60dbbca87196b616), // 5^71 (0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd), // 5^72 (0xb51d13aea4a488dd, 0x6babab6398bdbe41), // 5^73 (0xe264589a4dcdab14, 0xc696963c7eed2dd1), // 5^74 (0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2), // 5^75 (0xb0de65388cc8ada8, 0x3b25a55f43294bcb), // 5^76 (0xdd15fe86affad912, 0x49ef0eb713f39ebe), // 5^77 (0x8a2dbf142dfcc7ab, 0x6e3569326c784337), // 5^78 (0xacb92ed9397bf996, 0x49c2c37f07965404), // 5^79 (0xd7e77a8f87daf7fb, 0xdc33745ec97be906), // 5^80 (0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3), // 5^81 (0xa8acd7c0222311bc, 0xc40832ea0d68ce0c), // 5^82 (0xd2d80db02aabd62b, 0xf50a3fa490c30190), // 5^83 (0x83c7088e1aab65db, 0x792667c6da79e0fa), // 5^84 (0xa4b8cab1a1563f52, 0x577001b891185938), // 5^85 (0xcde6fd5e09abcf26, 0xed4c0226b55e6f86), // 5^86 (0x80b05e5ac60b6178, 0x544f8158315b05b4), // 5^87 (0xa0dc75f1778e39d6, 0x696361ae3db1c721), // 5^88 (0xc913936dd571c84c, 0x3bc3a19cd1e38e9), // 5^89 (0xfb5878494ace3a5f, 0x4ab48a04065c723), // 5^90 (0x9d174b2dcec0e47b, 0x62eb0d64283f9c76), // 5^91 (0xc45d1df942711d9a, 0x3ba5d0bd324f8394), // 5^92 (0xf5746577930d6500, 0xca8f44ec7ee36479), // 5^93 (0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb), // 5^94 (0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e), // 5^95 (0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e), // 5^96 (0x95d04aee3b80ece5, 0xbba1f1d158724a12), // 5^97 (0xbb445da9ca61281f, 0x2a8a6e45ae8edc97), // 5^98 (0xea1575143cf97226, 0xf52d09d71a3293bd), // 5^99 (0x924d692ca61be758, 0x593c2626705f9c56), // 5^100 (0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c), // 5^101 (0xe498f455c38b997a, 0xb6dfb9c0f956447), // 5^102 (0x8edf98b59a373fec, 0x4724bd4189bd5eac), // 5^103 (0xb2977ee300c50fe7, 0x58edec91ec2cb657), // 5^104 (0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed), // 5^105 (0x8b865b215899f46c, 0xbd79e0d20082ee74), // 5^106 (0xae67f1e9aec07187, 0xecd8590680a3aa11), // 5^107 (0xda01ee641a708de9, 0xe80e6f4820cc9495), // 5^108 (0x884134fe908658b2, 0x3109058d147fdcdd), // 5^109 (0xaa51823e34a7eede, 0xbd4b46f0599fd415), // 5^110 (0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a), // 5^111 (0x850fadc09923329e, 0x3e2cf6bc604ddb0), // 5^112 (0xa6539930bf6bff45, 0x84db8346b786151c), // 5^113 (0xcfe87f7cef46ff16, 0xe612641865679a63), // 5^114 (0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e), // 5^115 (0xa26da3999aef7749, 0xe3be5e330f38f09d), // 5^116 (0xcb090c8001ab551c, 0x5cadf5bfd3072cc5), // 5^117 (0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6), // 5^118 (0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa), // 5^119 (0xc646d63501a1511d, 0xb281e1fd541501b8), // 5^120 (0xf7d88bc24209a565, 0x1f225a7ca91a4226), // 5^121 (0x9ae757596946075f, 0x3375788de9b06958), // 5^122 (0xc1a12d2fc3978937, 0x52d6b1641c83ae), // 5^123 (0xf209787bb47d6b84, 0xc0678c5dbd23a49a), // 5^124 (0x9745eb4d50ce6332, 0xf840b7ba963646e0), // 5^125 (0xbd176620a501fbff, 0xb650e5a93bc3d898), // 5^126 (0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe), // 5^127 (0x93ba47c980e98cdf, 0xc66f336c36b10137), // 5^128 (0xb8a8d9bbe123f017, 0xb80b0047445d4184), // 5^129 (0xe6d3102ad96cec1d, 0xa60dc059157491e5), // 5^130 (0x9043ea1ac7e41392, 0x87c89837ad68db2f), // 5^131 (0xb454e4a179dd1877, 0x29babe4598c311fb), // 5^132 (0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a), // 5^133 (0x8ce2529e2734bb1d, 0x1899e4a65f58660c), // 5^134 (0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f), // 5^135 (0xdc21a1171d42645d, 0x76707543f4fa1f73), // 5^136 (0x899504ae72497eba, 0x6a06494a791c53a8), // 5^137 (0xabfa45da0edbde69, 0x487db9d17636892), // 5^138 (0xd6f8d7509292d603, 0x45a9d2845d3c42b6), // 5^139 (0x865b86925b9bc5c2, 0xb8a2392ba45a9b2), // 5^140 (0xa7f26836f282b732, 0x8e6cac7768d7141e), // 5^141 (0xd1ef0244af2364ff, 0x3207d795430cd926), // 5^142 (0x8335616aed761f1f, 0x7f44e6bd49e807b8), // 5^143 (0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6), // 5^144 (0xcd036837130890a1, 0x36dba887c37a8c0f), // 5^145 (0x802221226be55a64, 0xc2494954da2c9789), // 5^146 (0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c), // 5^147 (0xc83553c5c8965d3d, 0x6f92829494e5acc7), // 5^148 (0xfa42a8b73abbf48c, 0xcb772339ba1f17f9), // 5^149 (0x9c69a97284b578d7, 0xff2a760414536efb), // 5^150 (0xc38413cf25e2d70d, 0xfef5138519684aba), // 5^151 (0xf46518c2ef5b8cd1, 0x7eb258665fc25d69), // 5^152 (0x98bf2f79d5993802, 0xef2f773ffbd97a61), // 5^153 (0xbeeefb584aff8603, 0xaafb550ffacfd8fa), // 5^154 (0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38), // 5^155 (0x952ab45cfa97a0b2, 0xdd945a747bf26183), // 5^156 (0xba756174393d88df, 0x94f971119aeef9e4), // 5^157 (0xe912b9d1478ceb17, 0x7a37cd5601aab85d), // 5^158 (0x91abb422ccb812ee, 0xac62e055c10ab33a), // 5^159 (0xb616a12b7fe617aa, 0x577b986b314d6009), // 5^160 (0xe39c49765fdf9d94, 0xed5a7e85fda0b80b), // 5^161 (0x8e41ade9fbebc27d, 0x14588f13be847307), // 5^162 (0xb1d219647ae6b31c, 0x596eb2d8ae258fc8), // 5^163 (0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb), // 5^164 (0x8aec23d680043bee, 0x25de7bb9480d5854), // 5^165 (0xada72ccc20054ae9, 0xaf561aa79a10ae6a), // 5^166 (0xd910f7ff28069da4, 0x1b2ba1518094da04), // 5^167 (0x87aa9aff79042286, 0x90fb44d2f05d0842), // 5^168 (0xa99541bf57452b28, 0x353a1607ac744a53), // 5^169 (0xd3fa922f2d1675f2, 0x42889b8997915ce8), // 5^170 (0x847c9b5d7c2e09b7, 0x69956135febada11), // 5^171 (0xa59bc234db398c25, 0x43fab9837e699095), // 5^172 (0xcf02b2c21207ef2e, 0x94f967e45e03f4bb), // 5^173 (0x8161afb94b44f57d, 0x1d1be0eebac278f5), // 5^174 (0xa1ba1ba79e1632dc, 0x6462d92a69731732), // 5^175 (0xca28a291859bbf93, 0x7d7b8f7503cfdcfe), // 5^176 (0xfcb2cb35e702af78, 0x5cda735244c3d43e), // 5^177 (0x9defbf01b061adab, 0x3a0888136afa64a7), // 5^178 (0xc56baec21c7a1916, 0x88aaa1845b8fdd0), // 5^179 (0xf6c69a72a3989f5b, 0x8aad549e57273d45), // 5^180 (0x9a3c2087a63f6399, 0x36ac54e2f678864b), // 5^181 (0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd), // 5^182 (0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5), // 5^183 (0x969eb7c47859e743, 0x9f644ae5a4b1b325), // 5^184 (0xbc4665b596706114, 0x873d5d9f0dde1fee), // 5^185 (0xeb57ff22fc0c7959, 0xa90cb506d155a7ea), // 5^186 (0x9316ff75dd87cbd8, 0x9a7f12442d588f2), // 5^187 (0xb7dcbf5354e9bece, 0xc11ed6d538aeb2f), // 5^188 (0xe5d3ef282a242e81, 0x8f1668c8a86da5fa), // 5^189 (0x8fa475791a569d10, 0xf96e017d694487bc), // 5^190 (0xb38d92d760ec4455, 0x37c981dcc395a9ac), // 5^191 (0xe070f78d3927556a, 0x85bbe253f47b1417), // 5^192 (0x8c469ab843b89562, 0x93956d7478ccec8e), // 5^193 (0xaf58416654a6babb, 0x387ac8d1970027b2), // 5^194 (0xdb2e51bfe9d0696a, 0x6997b05fcc0319e), // 5^195 (0x88fcf317f22241e2, 0x441fece3bdf81f03), // 5^196 (0xab3c2fddeeaad25a, 0xd527e81cad7626c3), // 5^197 (0xd60b3bd56a5586f1, 0x8a71e223d8d3b074), // 5^198 (0x85c7056562757456, 0xf6872d5667844e49), // 5^199 (0xa738c6bebb12d16c, 0xb428f8ac016561db), // 5^200 (0xd106f86e69d785c7, 0xe13336d701beba52), // 5^201 (0x82a45b450226b39c, 0xecc0024661173473), // 5^202 (0xa34d721642b06084, 0x27f002d7f95d0190), // 5^203 (0xcc20ce9bd35c78a5, 0x31ec038df7b441f4), // 5^204 (0xff290242c83396ce, 0x7e67047175a15271), // 5^205 (0x9f79a169bd203e41, 0xf0062c6e984d386), // 5^206 (0xc75809c42c684dd1, 0x52c07b78a3e60868), // 5^207 (0xf92e0c3537826145, 0xa7709a56ccdf8a82), // 5^208 (0x9bbcc7a142b17ccb, 0x88a66076400bb691), // 5^209 (0xc2abf989935ddbfe, 0x6acff893d00ea435), // 5^210 (0xf356f7ebf83552fe, 0x583f6b8c4124d43), // 5^211 (0x98165af37b2153de, 0xc3727a337a8b704a), // 5^212 (0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c), // 5^213 (0xeda2ee1c7064130c, 0x1162def06f79df73), // 5^214 (0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8), // 5^215 (0xb9a74a0637ce2ee1, 0x6d953e2bd7173692), // 5^216 (0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437), // 5^217 (0x910ab1d4db9914a0, 0x1d9c9892400a22a2), // 5^218 (0xb54d5e4a127f59c8, 0x2503beb6d00cab4b), // 5^219 (0xe2a0b5dc971f303a, 0x2e44ae64840fd61d), // 5^220 (0x8da471a9de737e24, 0x5ceaecfed289e5d2), // 5^221 (0xb10d8e1456105dad, 0x7425a83e872c5f47), // 5^222 (0xdd50f1996b947518, 0xd12f124e28f77719), // 5^223 (0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f), // 5^224 (0xace73cbfdc0bfb7b, 0x636cc64d1001550b), // 5^225 (0xd8210befd30efa5a, 0x3c47f7e05401aa4e), // 5^226 (0x8714a775e3e95c78, 0x65acfaec34810a71), // 5^227 (0xa8d9d1535ce3b396, 0x7f1839a741a14d0d), // 5^228 (0xd31045a8341ca07c, 0x1ede48111209a050), // 5^229 (0x83ea2b892091e44d, 0x934aed0aab460432), // 5^230 (0xa4e4b66b68b65d60, 0xf81da84d5617853f), // 5^231 (0xce1de40642e3f4b9, 0x36251260ab9d668e), // 5^232 (0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019), // 5^233 (0xa1075a24e4421730, 0xb24cf65b8612f81f), // 5^234 (0xc94930ae1d529cfc, 0xdee033f26797b627), // 5^235 (0xfb9b7cd9a4a7443c, 0x169840ef017da3b1), // 5^236 (0x9d412e0806e88aa5, 0x8e1f289560ee864e), // 5^237 (0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2), // 5^238 (0xf5b5d7ec8acb58a2, 0xae10af696774b1db), // 5^239 (0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29), // 5^240 (0xbff610b0cc6edd3f, 0x17fd090a58d32af3), // 5^241 (0xeff394dcff8a948e, 0xddfc4b4cef07f5b0), // 5^242 (0x95f83d0a1fb69cd9, 0x4abdaf101564f98e), // 5^243 (0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1), // 5^244 (0xea53df5fd18d5513, 0x84c86189216dc5ed), // 5^245 (0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4), // 5^246 (0xb7118682dbb66a77, 0x3fbc8c33221dc2a1), // 5^247 (0xe4d5e82392a40515, 0xfabaf3feaa5334a), // 5^248 (0x8f05b1163ba6832d, 0x29cb4d87f2a7400e), // 5^249 (0xb2c71d5bca9023f8, 0x743e20e9ef511012), // 5^250 (0xdf78e4b2bd342cf6, 0x914da9246b255416), // 5^251 (0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e), // 5^252 (0xae9672aba3d0c320, 0xa184ac2473b529b1), // 5^253 (0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e), // 5^254 (0x8865899617fb1871, 0x7e2fa67c7a658892), // 5^255 (0xaa7eebfb9df9de8d, 0xddbb901b98feeab7), // 5^256 (0xd51ea6fa85785631, 0x552a74227f3ea565), // 5^257 (0x8533285c936b35de, 0xd53a88958f87275f), // 5^258 (0xa67ff273b8460356, 0x8a892abaf368f137), // 5^259 (0xd01fef10a657842c, 0x2d2b7569b0432d85), // 5^260 (0x8213f56a67f6b29b, 0x9c3b29620e29fc73), // 5^261 (0xa298f2c501f45f42, 0x8349f3ba91b47b8f), // 5^262 (0xcb3f2f7642717713, 0x241c70a936219a73), // 5^263 (0xfe0efb53d30dd4d7, 0xed238cd383aa0110), // 5^264 (0x9ec95d1463e8a506, 0xf4363804324a40aa), // 5^265 (0xc67bb4597ce2ce48, 0xb143c6053edcd0d5), // 5^266 (0xf81aa16fdc1b81da, 0xdd94b7868e94050a), // 5^267 (0x9b10a4e5e9913128, 0xca7cf2b4191c8326), // 5^268 (0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0), // 5^269 (0xf24a01a73cf2dccf, 0xbc633b39673c8cec), // 5^270 (0x976e41088617ca01, 0xd5be0503e085d813), // 5^271 (0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18), // 5^272 (0xec9c459d51852ba2, 0xddf8e7d60ed1219e), // 5^273 (0x93e1ab8252f33b45, 0xcabb90e5c942b503), // 5^274 (0xb8da1662e7b00a17, 0x3d6a751f3b936243), // 5^275 (0xe7109bfba19c0c9d, 0xcc512670a783ad4), // 5^276 (0x906a617d450187e2, 0x27fb2b80668b24c5), // 5^277 (0xb484f9dc9641e9da, 0xb1f9f660802dedf6), // 5^278 (0xe1a63853bbd26451, 0x5e7873f8a0396973), // 5^279 (0x8d07e33455637eb2, 0xdb0b487b6423e1e8), // 5^280 (0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62), // 5^281 (0xdc5c5301c56b75f7, 0x7641a140cc7810fb), // 5^282 (0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d), // 5^283 (0xac2820d9623bf429, 0x546345fa9fbdcd44), // 5^284 (0xd732290fbacaf133, 0xa97c177947ad4095), // 5^285 (0x867f59a9d4bed6c0, 0x49ed8eabcccc485d), // 5^286 (0xa81f301449ee8c70, 0x5c68f256bfff5a74), // 5^287 (0xd226fc195c6a2f8c, 0x73832eec6fff3111), // 5^288 (0x83585d8fd9c25db7, 0xc831fd53c5ff7eab), // 5^289 (0xa42e74f3d032f525, 0xba3e7ca8b77f5e55), // 5^290 (0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb), // 5^291 (0x80444b5e7aa7cf85, 0x7980d163cf5b81b3), // 5^292 (0xa0555e361951c366, 0xd7e105bcc332621f), // 5^293 (0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7), // 5^294 (0xfa856334878fc150, 0xb14f98f6f0feb951), // 5^295 (0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3), // 5^296 (0xc3b8358109e84f07, 0xa862f80ec4700c8), // 5^297 (0xf4a642e14c6262c8, 0xcd27bb612758c0fa), // 5^298 (0x98e7e9cccfbd7dbd, 0x8038d51cb897789c), // 5^299 (0xbf21e44003acdd2c, 0xe0470a63e6bd56c3), // 5^300 (0xeeea5d5004981478, 0x1858ccfce06cac74), // 5^301 (0x95527a5202df0ccb, 0xf37801e0c43ebc8), // 5^302 (0xbaa718e68396cffd, 0xd30560258f54e6ba), // 5^303 (0xe950df20247c83fd, 0x47c6b82ef32a2069), // 5^304 (0x91d28b7416cdd27e, 0x4cdc331d57fa5441), // 5^305 (0xb6472e511c81471d, 0xe0133fe4adf8e952), // 5^306 (0xe3d8f9e563a198e5, 0x58180fddd97723a6), // 5^307 (0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648), // 5^308 ]; lexical-parse-float-0.8.5/src/table_radix.rs000064400000000000000000002237640072674642500171530ustar 00000000000000//! Pre-computed tables for writing non-decimal strings. #![cfg(feature = "radix")] #![cfg(not(feature = "compact"))] #![doc(hidden)] #![allow(clippy::excessive_precision)] use crate::bigint::Limb; use crate::limits::{f32_exponent_limit, f64_exponent_limit, f64_mantissa_limit, u64_power_limit}; use crate::table_binary::*; use crate::table_decimal::*; use core::hint; use lexical_util::assert::debug_assert_radix; use static_assertions::const_assert; // HELPERS // ------- /// Get lookup table for 2 digit radix conversions. /// /// # Safety /// /// Safe as long as the radix provided is valid, and exponent is smaller /// than the table for the radix. #[inline] pub unsafe fn get_small_int_power(exponent: usize, radix: u32) -> u64 { debug_assert_radix(radix); unsafe { match radix { 2 => get_small_int_power2(exponent), 3 => get_small_int_power3(exponent), 4 => get_small_int_power4(exponent), 5 => get_small_int_power5(exponent), 6 => get_small_int_power6(exponent), 7 => get_small_int_power7(exponent), 8 => get_small_int_power8(exponent), 9 => get_small_int_power9(exponent), 10 => get_small_int_power10(exponent), 11 => get_small_int_power11(exponent), 12 => get_small_int_power12(exponent), 13 => get_small_int_power13(exponent), 14 => get_small_int_power14(exponent), 15 => get_small_int_power15(exponent), 16 => get_small_int_power16(exponent), 17 => get_small_int_power17(exponent), 18 => get_small_int_power18(exponent), 19 => get_small_int_power19(exponent), 20 => get_small_int_power20(exponent), 21 => get_small_int_power21(exponent), 22 => get_small_int_power22(exponent), 23 => get_small_int_power23(exponent), 24 => get_small_int_power24(exponent), 25 => get_small_int_power25(exponent), 26 => get_small_int_power26(exponent), 27 => get_small_int_power27(exponent), 28 => get_small_int_power28(exponent), 29 => get_small_int_power29(exponent), 30 => get_small_int_power30(exponent), 31 => get_small_int_power31(exponent), 32 => get_small_int_power32(exponent), 33 => get_small_int_power33(exponent), 34 => get_small_int_power34(exponent), 35 => get_small_int_power35(exponent), 36 => get_small_int_power36(exponent), _ => hint::unreachable_unchecked(), } } } /// Get lookup table for small f32 powers. /// /// # Safety /// /// Safe as long as the radix provided is valid, and exponent is smaller /// than the table for the radix. #[inline] pub unsafe fn get_small_f32_power(exponent: usize, radix: u32) -> f32 { debug_assert_radix(radix); unsafe { match radix { 2 => get_small_f32_power2(exponent), 3 => get_small_f32_power3(exponent), 4 => get_small_f32_power4(exponent), 5 => get_small_f32_power5(exponent), 6 => get_small_f32_power6(exponent), 7 => get_small_f32_power7(exponent), 8 => get_small_f32_power8(exponent), 9 => get_small_f32_power9(exponent), 10 => get_small_f32_power10(exponent), 11 => get_small_f32_power11(exponent), 12 => get_small_f32_power12(exponent), 13 => get_small_f32_power13(exponent), 14 => get_small_f32_power14(exponent), 15 => get_small_f32_power15(exponent), 16 => get_small_f32_power16(exponent), 17 => get_small_f32_power17(exponent), 18 => get_small_f32_power18(exponent), 19 => get_small_f32_power19(exponent), 20 => get_small_f32_power20(exponent), 21 => get_small_f32_power21(exponent), 22 => get_small_f32_power22(exponent), 23 => get_small_f32_power23(exponent), 24 => get_small_f32_power24(exponent), 25 => get_small_f32_power25(exponent), 26 => get_small_f32_power26(exponent), 27 => get_small_f32_power27(exponent), 28 => get_small_f32_power28(exponent), 29 => get_small_f32_power29(exponent), 30 => get_small_f32_power30(exponent), 31 => get_small_f32_power31(exponent), 32 => get_small_f32_power32(exponent), 33 => get_small_f32_power33(exponent), 34 => get_small_f32_power34(exponent), 35 => get_small_f32_power35(exponent), 36 => get_small_f32_power36(exponent), _ => hint::unreachable_unchecked(), } } } /// Get lookup table for small f64 powers. /// /// # Safety /// /// Safe as long as the radix provided is valid, and exponent is smaller /// than the table for the radix. #[inline] pub unsafe fn get_small_f64_power(exponent: usize, radix: u32) -> f64 { debug_assert_radix(radix); unsafe { match radix { 2 => get_small_f64_power2(exponent), 3 => get_small_f64_power3(exponent), 4 => get_small_f64_power4(exponent), 5 => get_small_f64_power5(exponent), 6 => get_small_f64_power6(exponent), 7 => get_small_f64_power7(exponent), 8 => get_small_f64_power8(exponent), 9 => get_small_f64_power9(exponent), 10 => get_small_f64_power10(exponent), 11 => get_small_f64_power11(exponent), 12 => get_small_f64_power12(exponent), 13 => get_small_f64_power13(exponent), 14 => get_small_f64_power14(exponent), 15 => get_small_f64_power15(exponent), 16 => get_small_f64_power16(exponent), 17 => get_small_f64_power17(exponent), 18 => get_small_f64_power18(exponent), 19 => get_small_f64_power19(exponent), 20 => get_small_f64_power20(exponent), 21 => get_small_f64_power21(exponent), 22 => get_small_f64_power22(exponent), 23 => get_small_f64_power23(exponent), 24 => get_small_f64_power24(exponent), 25 => get_small_f64_power25(exponent), 26 => get_small_f64_power26(exponent), 27 => get_small_f64_power27(exponent), 28 => get_small_f64_power28(exponent), 29 => get_small_f64_power29(exponent), 30 => get_small_f64_power30(exponent), 31 => get_small_f64_power31(exponent), 32 => get_small_f64_power32(exponent), 33 => get_small_f64_power33(exponent), 34 => get_small_f64_power34(exponent), 35 => get_small_f64_power35(exponent), 36 => get_small_f64_power36(exponent), _ => hint::unreachable_unchecked(), } } } /// Get pre-computed power for a large power of radix. pub const fn get_large_int_power(radix: u32) -> (&'static [Limb], u32) { match radix { 3 => (&LARGE_POW3, LARGE_POW3_STEP), 5 => (&LARGE_POW5, LARGE_POW5_STEP), 7 => (&LARGE_POW7, LARGE_POW7_STEP), 9 => (&LARGE_POW9, LARGE_POW9_STEP), 11 => (&LARGE_POW11, LARGE_POW11_STEP), 13 => (&LARGE_POW13, LARGE_POW13_STEP), 15 => (&LARGE_POW15, LARGE_POW15_STEP), 17 => (&LARGE_POW17, LARGE_POW17_STEP), 19 => (&LARGE_POW19, LARGE_POW19_STEP), 21 => (&LARGE_POW21, LARGE_POW21_STEP), 23 => (&LARGE_POW23, LARGE_POW23_STEP), 25 => (&LARGE_POW25, LARGE_POW25_STEP), 27 => (&LARGE_POW27, LARGE_POW27_STEP), 29 => (&LARGE_POW29, LARGE_POW29_STEP), 31 => (&LARGE_POW31, LARGE_POW31_STEP), 33 => (&LARGE_POW33, LARGE_POW33_STEP), // Remaining radix: must be 35. _ => (&LARGE_POW35, LARGE_POW35_STEP), } } /// Get pre-computed int power of 3. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW3.len()`. #[inline(always)] pub unsafe fn get_small_int_power3(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW3[exponent]) } } /// Get pre-computed f32 power of 3. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW3.len()`. #[inline(always)] pub unsafe fn get_small_f32_power3(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW3[exponent]) } } /// Get pre-computed f64 power of 3. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW3.len()`. #[inline(always)] pub unsafe fn get_small_f64_power3(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW3[exponent]) } } /// Get pre-computed f32 power of 5. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW5.len()`. #[inline(always)] pub unsafe fn get_small_f32_power5(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW5[exponent]) } } /// Get pre-computed f64 power of 5. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW5.len()`. #[inline(always)] pub unsafe fn get_small_f64_power5(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW5[exponent]) } } /// Get pre-computed int power of 6. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW6.len()`. #[inline(always)] pub unsafe fn get_small_int_power6(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW6[exponent]) } } /// Get pre-computed f32 power of 6. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW6.len()`. #[inline(always)] pub unsafe fn get_small_f32_power6(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW6[exponent]) } } /// Get pre-computed f64 power of 6. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW6.len()`. #[inline(always)] pub unsafe fn get_small_f64_power6(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW6[exponent]) } } /// Get pre-computed int power of 7. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW7.len()`. #[inline(always)] pub unsafe fn get_small_int_power7(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW7[exponent]) } } /// Get pre-computed f32 power of 7. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW7.len()`. #[inline(always)] pub unsafe fn get_small_f32_power7(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW7[exponent]) } } /// Get pre-computed f64 power of 7. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW7.len()`. #[inline(always)] pub unsafe fn get_small_f64_power7(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW7[exponent]) } } /// Get pre-computed int power of 9. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW9.len()`. #[inline(always)] pub unsafe fn get_small_int_power9(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW9[exponent]) } } /// Get pre-computed f32 power of 9. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW9.len()`. #[inline(always)] pub unsafe fn get_small_f32_power9(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW9[exponent]) } } /// Get pre-computed f64 power of 9. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW9.len()`. #[inline(always)] pub unsafe fn get_small_f64_power9(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW9[exponent]) } } /// Get pre-computed int power of 11. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW11.len()`. #[inline(always)] pub unsafe fn get_small_int_power11(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW11[exponent]) } } /// Get pre-computed f32 power of 11. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW11.len()`. #[inline(always)] pub unsafe fn get_small_f32_power11(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW11[exponent]) } } /// Get pre-computed f64 power of 11. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW11.len()`. #[inline(always)] pub unsafe fn get_small_f64_power11(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW11[exponent]) } } /// Get pre-computed int power of 12. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW12.len()`. #[inline(always)] pub unsafe fn get_small_int_power12(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW12[exponent]) } } /// Get pre-computed f32 power of 12. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW12.len()`. #[inline(always)] pub unsafe fn get_small_f32_power12(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW12[exponent]) } } /// Get pre-computed f64 power of 12. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW12.len()`. #[inline(always)] pub unsafe fn get_small_f64_power12(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW12[exponent]) } } /// Get pre-computed int power of 13. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW13.len()`. #[inline(always)] pub unsafe fn get_small_int_power13(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW13[exponent]) } } /// Get pre-computed f32 power of 13. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW13.len()`. #[inline(always)] pub unsafe fn get_small_f32_power13(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW13[exponent]) } } /// Get pre-computed f64 power of 13. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW13.len()`. #[inline(always)] pub unsafe fn get_small_f64_power13(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW13[exponent]) } } /// Get pre-computed int power of 14. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW14.len()`. #[inline(always)] pub unsafe fn get_small_int_power14(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW14[exponent]) } } /// Get pre-computed f32 power of 14. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW14.len()`. #[inline(always)] pub unsafe fn get_small_f32_power14(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW14[exponent]) } } /// Get pre-computed f64 power of 14. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW14.len()`. #[inline(always)] pub unsafe fn get_small_f64_power14(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW14[exponent]) } } /// Get pre-computed int power of 15. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW15.len()`. #[inline(always)] pub unsafe fn get_small_int_power15(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW15[exponent]) } } /// Get pre-computed f32 power of 15. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW15.len()`. #[inline(always)] pub unsafe fn get_small_f32_power15(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW15[exponent]) } } /// Get pre-computed f64 power of 15. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW15.len()`. #[inline(always)] pub unsafe fn get_small_f64_power15(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW15[exponent]) } } /// Get pre-computed int power of 17. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW17.len()`. #[inline(always)] pub unsafe fn get_small_int_power17(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW17[exponent]) } } /// Get pre-computed f32 power of 17. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW17.len()`. #[inline(always)] pub unsafe fn get_small_f32_power17(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW17[exponent]) } } /// Get pre-computed f64 power of 17. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW17.len()`. #[inline(always)] pub unsafe fn get_small_f64_power17(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW17[exponent]) } } /// Get pre-computed int power of 18. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW18.len()`. #[inline(always)] pub unsafe fn get_small_int_power18(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW18[exponent]) } } /// Get pre-computed f32 power of 18. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW18.len()`. #[inline(always)] pub unsafe fn get_small_f32_power18(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW18[exponent]) } } /// Get pre-computed f64 power of 18. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW18.len()`. #[inline(always)] pub unsafe fn get_small_f64_power18(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW18[exponent]) } } /// Get pre-computed int power of 19. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW19.len()`. #[inline(always)] pub unsafe fn get_small_int_power19(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW19[exponent]) } } /// Get pre-computed f32 power of 19. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW19.len()`. #[inline(always)] pub unsafe fn get_small_f32_power19(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW19[exponent]) } } /// Get pre-computed f64 power of 19. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW19.len()`. #[inline(always)] pub unsafe fn get_small_f64_power19(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW19[exponent]) } } /// Get pre-computed int power of 20. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW20.len()`. #[inline(always)] pub unsafe fn get_small_int_power20(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW20[exponent]) } } /// Get pre-computed f32 power of 20. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW20.len()`. #[inline(always)] pub unsafe fn get_small_f32_power20(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW20[exponent]) } } /// Get pre-computed f64 power of 20. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW20.len()`. #[inline(always)] pub unsafe fn get_small_f64_power20(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW20[exponent]) } } /// Get pre-computed int power of 21. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW21.len()`. #[inline(always)] pub unsafe fn get_small_int_power21(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW21[exponent]) } } /// Get pre-computed f32 power of 21. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW21.len()`. #[inline(always)] pub unsafe fn get_small_f32_power21(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW21[exponent]) } } /// Get pre-computed f64 power of 21. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW21.len()`. #[inline(always)] pub unsafe fn get_small_f64_power21(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW21[exponent]) } } /// Get pre-computed int power of 22. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW22.len()`. #[inline(always)] pub unsafe fn get_small_int_power22(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW22[exponent]) } } /// Get pre-computed f32 power of 22. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW22.len()`. #[inline(always)] pub unsafe fn get_small_f32_power22(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW22[exponent]) } } /// Get pre-computed f64 power of 22. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW22.len()`. #[inline(always)] pub unsafe fn get_small_f64_power22(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW22[exponent]) } } /// Get pre-computed int power of 23. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW23.len()`. #[inline(always)] pub unsafe fn get_small_int_power23(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW23[exponent]) } } /// Get pre-computed f32 power of 23. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW23.len()`. #[inline(always)] pub unsafe fn get_small_f32_power23(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW23[exponent]) } } /// Get pre-computed f64 power of 23. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW23.len()`. #[inline(always)] pub unsafe fn get_small_f64_power23(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW23[exponent]) } } /// Get pre-computed int power of 24. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW24.len()`. #[inline(always)] pub unsafe fn get_small_int_power24(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW24[exponent]) } } /// Get pre-computed f32 power of 24. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW24.len()`. #[inline(always)] pub unsafe fn get_small_f32_power24(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW24[exponent]) } } /// Get pre-computed f64 power of 24. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW24.len()`. #[inline(always)] pub unsafe fn get_small_f64_power24(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW24[exponent]) } } /// Get pre-computed int power of 25. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW25.len()`. #[inline(always)] pub unsafe fn get_small_int_power25(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW25[exponent]) } } /// Get pre-computed f32 power of 25. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW25.len()`. #[inline(always)] pub unsafe fn get_small_f32_power25(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW25[exponent]) } } /// Get pre-computed f64 power of 25. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW25.len()`. #[inline(always)] pub unsafe fn get_small_f64_power25(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW25[exponent]) } } /// Get pre-computed int power of 26. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW26.len()`. #[inline(always)] pub unsafe fn get_small_int_power26(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW26[exponent]) } } /// Get pre-computed f32 power of 26. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW26.len()`. #[inline(always)] pub unsafe fn get_small_f32_power26(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW26[exponent]) } } /// Get pre-computed f64 power of 26. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW26.len()`. #[inline(always)] pub unsafe fn get_small_f64_power26(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW26[exponent]) } } /// Get pre-computed int power of 27. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW27.len()`. #[inline(always)] pub unsafe fn get_small_int_power27(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW27[exponent]) } } /// Get pre-computed f32 power of 27. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW27.len()`. #[inline(always)] pub unsafe fn get_small_f32_power27(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW27[exponent]) } } /// Get pre-computed f64 power of 27. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW27.len()`. #[inline(always)] pub unsafe fn get_small_f64_power27(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW27[exponent]) } } /// Get pre-computed int power of 28. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW28.len()`. #[inline(always)] pub unsafe fn get_small_int_power28(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW28[exponent]) } } /// Get pre-computed f32 power of 28. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW28.len()`. #[inline(always)] pub unsafe fn get_small_f32_power28(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW28[exponent]) } } /// Get pre-computed f64 power of 28. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW28.len()`. #[inline(always)] pub unsafe fn get_small_f64_power28(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW28[exponent]) } } /// Get pre-computed int power of 29. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW29.len()`. #[inline(always)] pub unsafe fn get_small_int_power29(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW29[exponent]) } } /// Get pre-computed f32 power of 29. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW29.len()`. #[inline(always)] pub unsafe fn get_small_f32_power29(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW29[exponent]) } } /// Get pre-computed f64 power of 29. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW29.len()`. #[inline(always)] pub unsafe fn get_small_f64_power29(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW29[exponent]) } } /// Get pre-computed int power of 30. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW30.len()`. #[inline(always)] pub unsafe fn get_small_int_power30(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW30[exponent]) } } /// Get pre-computed f32 power of 30. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW30.len()`. #[inline(always)] pub unsafe fn get_small_f32_power30(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW30[exponent]) } } /// Get pre-computed f64 power of 30. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW30.len()`. #[inline(always)] pub unsafe fn get_small_f64_power30(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW30[exponent]) } } /// Get pre-computed int power of 31. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW31.len()`. #[inline(always)] pub unsafe fn get_small_int_power31(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW31[exponent]) } } /// Get pre-computed f32 power of 31. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW31.len()`. #[inline(always)] pub unsafe fn get_small_f32_power31(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW31[exponent]) } } /// Get pre-computed f64 power of 31. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW31.len()`. #[inline(always)] pub unsafe fn get_small_f64_power31(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW31[exponent]) } } /// Get pre-computed int power of 33. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW33.len()`. #[inline(always)] pub unsafe fn get_small_int_power33(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW33[exponent]) } } /// Get pre-computed f32 power of 33. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW33.len()`. #[inline(always)] pub unsafe fn get_small_f32_power33(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW33[exponent]) } } /// Get pre-computed f64 power of 33. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW33.len()`. #[inline(always)] pub unsafe fn get_small_f64_power33(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW33[exponent]) } } /// Get pre-computed int power of 34. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW34.len()`. #[inline(always)] pub unsafe fn get_small_int_power34(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW34[exponent]) } } /// Get pre-computed f32 power of 34. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW34.len()`. #[inline(always)] pub unsafe fn get_small_f32_power34(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW34[exponent]) } } /// Get pre-computed f64 power of 34. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW34.len()`. #[inline(always)] pub unsafe fn get_small_f64_power34(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW34[exponent]) } } /// Get pre-computed int power of 35. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW35.len()`. #[inline(always)] pub unsafe fn get_small_int_power35(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW35[exponent]) } } /// Get pre-computed f32 power of 35. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW35.len()`. #[inline(always)] pub unsafe fn get_small_f32_power35(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW35[exponent]) } } /// Get pre-computed f64 power of 35. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW35.len()`. #[inline(always)] pub unsafe fn get_small_f64_power35(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW35[exponent]) } } /// Get pre-computed int power of 36. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_INT_POW36.len()`. #[inline(always)] pub unsafe fn get_small_int_power36(exponent: usize) -> u64 { unsafe { index_unchecked!(SMALL_INT_POW36[exponent]) } } /// Get pre-computed f32 power of 36. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F32_POW36.len()`. #[inline(always)] pub unsafe fn get_small_f32_power36(exponent: usize) -> f32 { unsafe { index_unchecked!(SMALL_F32_POW36[exponent]) } } /// Get pre-computed f64 power of 36. /// /// # Safety /// /// Safe as long as the `exponent < SMALL_F64_POW36.len()`. #[inline(always)] pub unsafe fn get_small_f64_power36(exponent: usize) -> f64 { unsafe { index_unchecked!(SMALL_F64_POW36[exponent]) } } // TABLES // ------ // NOTE: // These tables were automatically generated using `etc/powers_table.py`. // Do not modify them unless you have a very good reason to. /// Pre-computed, small powers-of-3. pub const SMALL_INT_POW3: [u64; 41] = [ 1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721, 129140163, 387420489, 1162261467, 3486784401, 10460353203, 31381059609, 94143178827, 282429536481, 847288609443, 2541865828329, 7625597484987, 22876792454961, 68630377364883, 205891132094649, 617673396283947, 1853020188851841, 5559060566555523, 16677181699666569, 50031545098999707, 150094635296999121, 450283905890997363, 1350851717672992089, 4052555153018976267, 12157665459056928801, ]; const_assert!(SMALL_INT_POW3.len() > f64_mantissa_limit(3) as usize); const_assert!(SMALL_INT_POW3.len() == u64_power_limit(3) as usize + 1); /// Pre-computed, small powers-of-3. pub const SMALL_F32_POW3: [f32; 16] = [ 1.0, 3.0, 9.0, 27.0, 81.0, 243.0, 729.0, 2187.0, 6561.0, 19683.0, 59049.0, 177147.0, 531441.0, 1594323.0, 4782969.0, 14348907.0, ]; const_assert!(SMALL_F32_POW3.len() > f32_exponent_limit(3).1 as usize); /// Pre-computed, small powers-of-3. pub const SMALL_F64_POW3: [f64; 34] = [ 1.0, 3.0, 9.0, 27.0, 81.0, 243.0, 729.0, 2187.0, 6561.0, 19683.0, 59049.0, 177147.0, 531441.0, 1594323.0, 4782969.0, 14348907.0, 43046721.0, 129140163.0, 387420489.0, 1162261467.0, 3486784401.0, 10460353203.0, 31381059609.0, 94143178827.0, 282429536481.0, 847288609443.0, 2541865828329.0, 7625597484987.0, 22876792454961.0, 68630377364883.0, 205891132094649.0, 617673396283947.0, 1853020188851841.0, 5559060566555523.0, ]; const_assert!(SMALL_F64_POW3.len() > f64_exponent_limit(3).1 as usize); /// Pre-computed large power-of-3 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW3: [u32; 10] = [ 2868424865, 1543175966, 3836194338, 2213345014, 1148585654, 4252227966, 1995653935, 3256521594, 1051739806, 534087228, ]; /// Pre-computed large power-of-3 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW3: [u64; 5] = [ 6627890308811632801, 9506244453730856482, 18263180050255185590, 13986653746943443759, 2293887178523035294, ]; /// Step for large power-of-3 for 32-bit limbs. pub const LARGE_POW3_STEP: u32 = 200; /// Pre-computed, small powers-of-5. pub const SMALL_F32_POW5: [f32; 11] = [1.0, 5.0, 25.0, 125.0, 625.0, 3125.0, 15625.0, 78125.0, 390625.0, 1953125.0, 9765625.0]; const_assert!(SMALL_F32_POW5.len() > f32_exponent_limit(5).1 as usize); /// Pre-computed, small powers-of-5. pub const SMALL_F64_POW5: [f64; 23] = [ 1.0, 5.0, 25.0, 125.0, 625.0, 3125.0, 15625.0, 78125.0, 390625.0, 1953125.0, 9765625.0, 48828125.0, 244140625.0, 1220703125.0, 6103515625.0, 30517578125.0, 152587890625.0, 762939453125.0, 3814697265625.0, 19073486328125.0, 95367431640625.0, 476837158203125.0, 2384185791015625.0, ]; const_assert!(SMALL_F64_POW5.len() > f64_exponent_limit(5).1 as usize); /// Pre-computed, small powers-of-6. pub const SMALL_INT_POW6: [u64; 25] = [ 1, 6, 36, 216, 1296, 7776, 46656, 279936, 1679616, 10077696, 60466176, 362797056, 2176782336, 13060694016, 78364164096, 470184984576, 2821109907456, 16926659444736, 101559956668416, 609359740010496, 3656158440062976, 21936950640377856, 131621703842267136, 789730223053602816, 4738381338321616896, ]; const_assert!(SMALL_INT_POW6.len() > f64_mantissa_limit(6) as usize); const_assert!(SMALL_INT_POW6.len() == u64_power_limit(6) as usize + 1); /// Pre-computed, small powers-of-6. pub const SMALL_F32_POW6: [f32; 16] = [ 1.0, 6.0, 36.0, 216.0, 1296.0, 7776.0, 46656.0, 279936.0, 1679616.0, 10077696.0, 60466176.0, 362797056.0, 2176782336.0, 13060694016.0, 78364164096.0, 470184984576.0, ]; const_assert!(SMALL_F32_POW6.len() > f32_exponent_limit(6).1 as usize); /// Pre-computed, small powers-of-6. pub const SMALL_F64_POW6: [f64; 34] = [ 1.0, 6.0, 36.0, 216.0, 1296.0, 7776.0, 46656.0, 279936.0, 1679616.0, 10077696.0, 60466176.0, 362797056.0, 2176782336.0, 13060694016.0, 78364164096.0, 470184984576.0, 2821109907456.0, 16926659444736.0, 101559956668416.0, 609359740010496.0, 3656158440062976.0, 2.1936950640377856e+16, 1.3162170384226714e+17, 7.897302230536028e+17, 4.738381338321617e+18, 2.84302880299297e+19, 1.705817281795782e+20, 1.0234903690774692e+21, 6.140942214464815e+21, 3.6845653286788893e+22, 2.2107391972073336e+23, 1.3264435183244001e+24, 7.958661109946401e+24, 4.7751966659678405e+25, ]; const_assert!(SMALL_F64_POW6.len() > f64_exponent_limit(6).1 as usize); /// Pre-computed, small powers-of-7. pub const SMALL_INT_POW7: [u64; 23] = [ 1, 7, 49, 343, 2401, 16807, 117649, 823543, 5764801, 40353607, 282475249, 1977326743, 13841287201, 96889010407, 678223072849, 4747561509943, 33232930569601, 232630513987207, 1628413597910449, 11398895185373143, 79792266297612001, 558545864083284007, 3909821048582988049, ]; const_assert!(SMALL_INT_POW7.len() > f64_mantissa_limit(7) as usize); const_assert!(SMALL_INT_POW7.len() == u64_power_limit(7) as usize + 1); /// Pre-computed, small powers-of-7. pub const SMALL_F32_POW7: [f32; 9] = [1.0, 7.0, 49.0, 343.0, 2401.0, 16807.0, 117649.0, 823543.0, 5764801.0]; const_assert!(SMALL_F32_POW7.len() > f32_exponent_limit(7).1 as usize); /// Pre-computed, small powers-of-7. pub const SMALL_F64_POW7: [f64; 19] = [ 1.0, 7.0, 49.0, 343.0, 2401.0, 16807.0, 117649.0, 823543.0, 5764801.0, 40353607.0, 282475249.0, 1977326743.0, 13841287201.0, 96889010407.0, 678223072849.0, 4747561509943.0, 33232930569601.0, 232630513987207.0, 1628413597910449.0, ]; const_assert!(SMALL_F64_POW7.len() > f64_exponent_limit(7).1 as usize); /// Pre-computed large power-of-7 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW7: [u32; 10] = [ 3938635601, 4013708425, 513691597, 1762742544, 3619207677, 480247883, 3793395133, 740892944, 1592317061, 1837154, ]; /// Pre-computed large power-of-7 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW7: [u64; 5] = [ 17238746424993304401, 7570921578261532621, 2062648955077442045, 3182110968110554557, 7890517940032645, ]; /// Step for large power-of-7 for 32-bit limbs. pub const LARGE_POW7_STEP: u32 = 110; /// Pre-computed, small powers-of-9. pub const SMALL_INT_POW9: [u64; 21] = [ 1, 9, 81, 729, 6561, 59049, 531441, 4782969, 43046721, 387420489, 3486784401, 31381059609, 282429536481, 2541865828329, 22876792454961, 205891132094649, 1853020188851841, 16677181699666569, 150094635296999121, 1350851717672992089, 12157665459056928801, ]; const_assert!(SMALL_INT_POW9.len() > f64_mantissa_limit(9) as usize); const_assert!(SMALL_INT_POW9.len() == u64_power_limit(9) as usize + 1); /// Pre-computed, small powers-of-9. pub const SMALL_F32_POW9: [f32; 8] = [1.0, 9.0, 81.0, 729.0, 6561.0, 59049.0, 531441.0, 4782969.0]; const_assert!(SMALL_F32_POW9.len() > f32_exponent_limit(9).1 as usize); /// Pre-computed, small powers-of-9. pub const SMALL_F64_POW9: [f64; 17] = [ 1.0, 9.0, 81.0, 729.0, 6561.0, 59049.0, 531441.0, 4782969.0, 43046721.0, 387420489.0, 3486784401.0, 31381059609.0, 282429536481.0, 2541865828329.0, 22876792454961.0, 205891132094649.0, 1853020188851841.0, ]; const_assert!(SMALL_F64_POW9.len() > f64_exponent_limit(9).1 as usize); /// Pre-computed large power-of-9 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW9: [u32; 10] = [ 2868424865, 1543175966, 3836194338, 2213345014, 1148585654, 4252227966, 1995653935, 3256521594, 1051739806, 534087228, ]; /// Pre-computed large power-of-9 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW9: [u64; 5] = [ 6627890308811632801, 9506244453730856482, 18263180050255185590, 13986653746943443759, 2293887178523035294, ]; /// Step for large power-of-9 for 32-bit limbs. pub const LARGE_POW9_STEP: u32 = 100; /// Pre-computed, small powers-of-11. pub const SMALL_INT_POW11: [u64; 19] = [ 1, 11, 121, 1331, 14641, 161051, 1771561, 19487171, 214358881, 2357947691, 25937424601, 285311670611, 3138428376721, 34522712143931, 379749833583241, 4177248169415651, 45949729863572161, 505447028499293771, 5559917313492231481, ]; const_assert!(SMALL_INT_POW11.len() > f64_mantissa_limit(11) as usize); const_assert!(SMALL_INT_POW11.len() == u64_power_limit(11) as usize + 1); /// Pre-computed, small powers-of-11. pub const SMALL_F32_POW11: [f32; 7] = [1.0, 11.0, 121.0, 1331.0, 14641.0, 161051.0, 1771561.0]; const_assert!(SMALL_F32_POW11.len() > f32_exponent_limit(11).1 as usize); /// Pre-computed, small powers-of-11. pub const SMALL_F64_POW11: [f64; 16] = [ 1.0, 11.0, 121.0, 1331.0, 14641.0, 161051.0, 1771561.0, 19487171.0, 214358881.0, 2357947691.0, 25937424601.0, 285311670611.0, 3138428376721.0, 34522712143931.0, 379749833583241.0, 4177248169415651.0, ]; const_assert!(SMALL_F64_POW11.len() > f64_exponent_limit(11).1 as usize); /// Pre-computed large power-of-11 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW11: [u32; 10] = [ 2172432537, 2346616081, 1851665372, 2301834192, 1763429507, 4086589879, 4002403721, 2932076170, 987565374, 10683238, ]; /// Pre-computed large power-of-11 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW11: [u64; 5] = [ 10078639326335119513, 9886302577306250204, 17551769884233026691, 12593171263533340041, 45884158812949822, ]; /// Step for large power-of-11 for 32-bit limbs. pub const LARGE_POW11_STEP: u32 = 90; /// Pre-computed, small powers-of-12. pub const SMALL_INT_POW12: [u64; 18] = [ 1, 12, 144, 1728, 20736, 248832, 2985984, 35831808, 429981696, 5159780352, 61917364224, 743008370688, 8916100448256, 106993205379072, 1283918464548864, 15407021574586368, 184884258895036416, 2218611106740436992, ]; const_assert!(SMALL_INT_POW12.len() > f64_mantissa_limit(12) as usize); const_assert!(SMALL_INT_POW12.len() == u64_power_limit(12) as usize + 1); /// Pre-computed, small powers-of-12. pub const SMALL_F32_POW12: [f32; 16] = [ 1.0, 12.0, 144.0, 1728.0, 20736.0, 248832.0, 2985984.0, 35831808.0, 429981696.0, 5159780352.0, 61917364224.0, 743008370688.0, 8916100448256.0, 106993205379072.0, 1283918464548864.0, 1.5407021574586368e+16, ]; const_assert!(SMALL_F32_POW12.len() > f32_exponent_limit(12).1 as usize); /// Pre-computed, small powers-of-12. pub const SMALL_F64_POW12: [f64; 34] = [ 1.0, 12.0, 144.0, 1728.0, 20736.0, 248832.0, 2985984.0, 35831808.0, 429981696.0, 5159780352.0, 61917364224.0, 743008370688.0, 8916100448256.0, 106993205379072.0, 1283918464548864.0, 1.5407021574586368e+16, 1.848842588950364e+17, 2.218611106740437e+18, 2.6623333280885244e+19, 3.194799993706229e+20, 3.833759992447475e+21, 4.60051199093697e+22, 5.520614389124364e+23, 6.624737266949237e+24, 7.949684720339084e+25, 9.539621664406901e+26, 1.1447545997288282e+28, 1.3737055196745938e+29, 1.6484466236095125e+30, 1.978135948331415e+31, 2.373763137997698e+32, 2.8485157655972377e+33, 3.418218918716685e+34, 4.101862702460022e+35, ]; const_assert!(SMALL_F64_POW12.len() > f64_exponent_limit(12).1 as usize); /// Pre-computed, small powers-of-13. pub const SMALL_INT_POW13: [u64; 18] = [ 1, 13, 169, 2197, 28561, 371293, 4826809, 62748517, 815730721, 10604499373, 137858491849, 1792160394037, 23298085122481, 302875106592253, 3937376385699289, 51185893014090757, 665416609183179841, 8650415919381337933, ]; const_assert!(SMALL_INT_POW13.len() > f64_mantissa_limit(13) as usize); const_assert!(SMALL_INT_POW13.len() == u64_power_limit(13) as usize + 1); /// Pre-computed, small powers-of-13. pub const SMALL_F32_POW13: [f32; 7] = [1.0, 13.0, 169.0, 2197.0, 28561.0, 371293.0, 4826809.0]; const_assert!(SMALL_F32_POW13.len() > f32_exponent_limit(13).1 as usize); /// Pre-computed, small powers-of-13. pub const SMALL_F64_POW13: [f64; 15] = [ 1.0, 13.0, 169.0, 2197.0, 28561.0, 371293.0, 4826809.0, 62748517.0, 815730721.0, 10604499373.0, 137858491849.0, 1792160394037.0, 23298085122481.0, 302875106592253.0, 3937376385699289.0, ]; const_assert!(SMALL_F64_POW13.len() > f64_exponent_limit(13).1 as usize); /// Pre-computed large power-of-13 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW13: [u32; 10] = [ 3146523293, 4222426932, 2977536293, 1295813598, 1909522258, 1606005718, 3366933208, 327990755, 3779976816, 97397137, ]; /// Pre-computed large power-of-13 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW13: [u64; 5] = [ 18135185585836139165, 5565477028099627301, 6897742037908520786, 1408709569482281688, 418317521919008368, ]; /// Step for large power-of-13 for 32-bit limbs. pub const LARGE_POW13_STEP: u32 = 85; /// Pre-computed, small powers-of-14. pub const SMALL_INT_POW14: [u64; 17] = [ 1, 14, 196, 2744, 38416, 537824, 7529536, 105413504, 1475789056, 20661046784, 289254654976, 4049565169664, 56693912375296, 793714773254144, 11112006825558016, 155568095557812224, 2177953337809371136, ]; const_assert!(SMALL_INT_POW14.len() > f64_mantissa_limit(14) as usize); const_assert!(SMALL_INT_POW14.len() == u64_power_limit(14) as usize + 1); /// Pre-computed, small powers-of-14. pub const SMALL_F32_POW14: [f32; 9] = [1.0, 14.0, 196.0, 2744.0, 38416.0, 537824.0, 7529536.0, 105413504.0, 1475789056.0]; const_assert!(SMALL_F32_POW14.len() > f32_exponent_limit(14).1 as usize); /// Pre-computed, small powers-of-14. pub const SMALL_F64_POW14: [f64; 19] = [ 1.0, 14.0, 196.0, 2744.0, 38416.0, 537824.0, 7529536.0, 105413504.0, 1475789056.0, 20661046784.0, 289254654976.0, 4049565169664.0, 56693912375296.0, 793714773254144.0, 1.1112006825558016e+16, 1.5556809555781222e+17, 2.1779533378093711e+18, 3.0491346729331196e+19, 4.2687885421063674e+20, ]; const_assert!(SMALL_F64_POW14.len() > f64_exponent_limit(14).1 as usize); /// Pre-computed, small powers-of-15. pub const SMALL_INT_POW15: [u64; 17] = [ 1, 15, 225, 3375, 50625, 759375, 11390625, 170859375, 2562890625, 38443359375, 576650390625, 8649755859375, 129746337890625, 1946195068359375, 29192926025390625, 437893890380859375, 6568408355712890625, ]; const_assert!(SMALL_INT_POW15.len() > f64_mantissa_limit(15) as usize); const_assert!(SMALL_INT_POW15.len() == u64_power_limit(15) as usize + 1); /// Pre-computed, small powers-of-15. pub const SMALL_F32_POW15: [f32; 7] = [1.0, 15.0, 225.0, 3375.0, 50625.0, 759375.0, 11390625.0]; const_assert!(SMALL_F32_POW15.len() > f32_exponent_limit(15).1 as usize); /// Pre-computed, small powers-of-15. pub const SMALL_F64_POW15: [f64; 14] = [ 1.0, 15.0, 225.0, 3375.0, 50625.0, 759375.0, 11390625.0, 170859375.0, 2562890625.0, 38443359375.0, 576650390625.0, 8649755859375.0, 129746337890625.0, 1946195068359375.0, ]; const_assert!(SMALL_F64_POW15.len() > f64_exponent_limit(15).1 as usize); /// Pre-computed large power-of-15 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW15: [u32; 10] = [ 3507049217, 2300028134, 3886839708, 4190270956, 1622122702, 1947334599, 204338878, 3105278257, 2490561006, 24584533, ]; /// Pre-computed large power-of-15 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW15: [u64; 5] = [ 9878545618916954881, 17997076721285494684, 8363738418696397006, 13337068558999221950, 105589767712993774, ]; /// Step for large power-of-15 for 32-bit limbs. pub const LARGE_POW15_STEP: u32 = 80; /// Pre-computed, small powers-of-17. pub const SMALL_INT_POW17: [u64; 16] = [ 1, 17, 289, 4913, 83521, 1419857, 24137569, 410338673, 6975757441, 118587876497, 2015993900449, 34271896307633, 582622237229761, 9904578032905937, 168377826559400929, 2862423051509815793, ]; const_assert!(SMALL_INT_POW17.len() > f64_mantissa_limit(17) as usize); const_assert!(SMALL_INT_POW17.len() == u64_power_limit(17) as usize + 1); /// Pre-computed, small powers-of-17. pub const SMALL_F32_POW17: [f32; 6] = [1.0, 17.0, 289.0, 4913.0, 83521.0, 1419857.0]; const_assert!(SMALL_F32_POW17.len() > f32_exponent_limit(17).1 as usize); /// Pre-computed, small powers-of-17. pub const SMALL_F64_POW17: [f64; 13] = [ 1.0, 17.0, 289.0, 4913.0, 83521.0, 1419857.0, 24137569.0, 410338673.0, 6975757441.0, 118587876497.0, 2015993900449.0, 34271896307633.0, 582622237229761.0, ]; const_assert!(SMALL_F64_POW17.len() > f64_exponent_limit(17).1 as usize); /// Pre-computed large power-of-17 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW17: [u32; 10] = [ 2990615473, 2810986799, 4066186761, 2554374905, 4073187723, 2831536001, 529177471, 3891721527, 4211495815, 386393, ]; /// Pre-computed large power-of-17 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW17: [u64; 5] = [ 12073096374183340977, 10970956682764293641, 12161354525814811019, 16714816684133358463, 1659549509899143, ]; /// Step for large power-of-17 for 32-bit limbs. pub const LARGE_POW17_STEP: u32 = 75; /// Pre-computed, small powers-of-18. pub const SMALL_INT_POW18: [u64; 16] = [ 1, 18, 324, 5832, 104976, 1889568, 34012224, 612220032, 11019960576, 198359290368, 3570467226624, 64268410079232, 1156831381426176, 20822964865671168, 374813367582081024, 6746640616477458432, ]; const_assert!(SMALL_INT_POW18.len() > f64_mantissa_limit(18) as usize); const_assert!(SMALL_INT_POW18.len() == u64_power_limit(18) as usize + 1); /// Pre-computed, small powers-of-18. pub const SMALL_F32_POW18: [f32; 8] = [1.0, 18.0, 324.0, 5832.0, 104976.0, 1889568.0, 34012224.0, 612220032.0]; const_assert!(SMALL_F32_POW18.len() > f32_exponent_limit(18).1 as usize); /// Pre-computed, small powers-of-18. pub const SMALL_F64_POW18: [f64; 17] = [ 1.0, 18.0, 324.0, 5832.0, 104976.0, 1889568.0, 34012224.0, 612220032.0, 11019960576.0, 198359290368.0, 3570467226624.0, 64268410079232.0, 1156831381426176.0, 2.082296486567117e+16, 3.74813367582081e+17, 6.746640616477458e+18, 1.2143953109659425e+20, ]; const_assert!(SMALL_F64_POW18.len() > f64_exponent_limit(18).1 as usize); /// Pre-computed, small powers-of-19. pub const SMALL_INT_POW19: [u64; 16] = [ 1, 19, 361, 6859, 130321, 2476099, 47045881, 893871739, 16983563041, 322687697779, 6131066257801, 116490258898219, 2213314919066161, 42052983462257059, 799006685782884121, 15181127029874798299, ]; const_assert!(SMALL_INT_POW19.len() > f64_mantissa_limit(19) as usize); const_assert!(SMALL_INT_POW19.len() == u64_power_limit(19) as usize + 1); /// Pre-computed, small powers-of-19. pub const SMALL_F32_POW19: [f32; 6] = [1.0, 19.0, 361.0, 6859.0, 130321.0, 2476099.0]; const_assert!(SMALL_F32_POW19.len() > f32_exponent_limit(19).1 as usize); /// Pre-computed, small powers-of-19. pub const SMALL_F64_POW19: [f64; 13] = [ 1.0, 19.0, 361.0, 6859.0, 130321.0, 2476099.0, 47045881.0, 893871739.0, 16983563041.0, 322687697779.0, 6131066257801.0, 116490258898219.0, 2213314919066161.0, ]; const_assert!(SMALL_F64_POW19.len() > f64_exponent_limit(19).1 as usize); /// Pre-computed large power-of-19 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW19: [u32; 10] = [ 844079147, 4109067463, 2265902219, 1405351247, 3107957240, 2205473157, 271286156, 2969717342, 1924040718, 1621366965, ]; /// Pre-computed large power-of-19 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW19: [u64; 5] = [ 17648310371486769195, 6035937647523720331, 9472435084628830712, 12754838862525333388, 6963718091413817358, ]; /// Step for large power-of-19 for 32-bit limbs. pub const LARGE_POW19_STEP: u32 = 75; /// Pre-computed, small powers-of-20. pub const SMALL_INT_POW20: [u64; 15] = [ 1, 20, 400, 8000, 160000, 3200000, 64000000, 1280000000, 25600000000, 512000000000, 10240000000000, 204800000000000, 4096000000000000, 81920000000000000, 1638400000000000000, ]; const_assert!(SMALL_INT_POW20.len() > f64_mantissa_limit(20) as usize); const_assert!(SMALL_INT_POW20.len() == u64_power_limit(20) as usize + 1); /// Pre-computed, small powers-of-20. pub const SMALL_F32_POW20: [f32; 11] = [ 1.0, 20.0, 400.0, 8000.0, 160000.0, 3200000.0, 64000000.0, 1280000000.0, 25600000000.0, 512000000000.0, 10240000000000.0, ]; const_assert!(SMALL_F32_POW20.len() > f32_exponent_limit(20).1 as usize); /// Pre-computed, small powers-of-20. pub const SMALL_F64_POW20: [f64; 23] = [ 1.0, 20.0, 400.0, 8000.0, 160000.0, 3200000.0, 64000000.0, 1280000000.0, 25600000000.0, 512000000000.0, 10240000000000.0, 204800000000000.0, 4096000000000000.0, 8.192e+16, 1.6384e+18, 3.2768e+19, 6.5536e+20, 1.31072e+22, 2.62144e+23, 5.24288e+24, 1.048576e+26, 2.097152e+27, 4.194304e+28, ]; const_assert!(SMALL_F64_POW20.len() > f64_exponent_limit(20).1 as usize); /// Pre-computed, small powers-of-21. pub const SMALL_INT_POW21: [u64; 15] = [ 1, 21, 441, 9261, 194481, 4084101, 85766121, 1801088541, 37822859361, 794280046581, 16679880978201, 350277500542221, 7355827511386641, 154472377739119461, 3243919932521508681, ]; const_assert!(SMALL_INT_POW21.len() > f64_mantissa_limit(21) as usize); const_assert!(SMALL_INT_POW21.len() == u64_power_limit(21) as usize + 1); /// Pre-computed, small powers-of-21. pub const SMALL_F32_POW21: [f32; 6] = [1.0, 21.0, 441.0, 9261.0, 194481.0, 4084101.0]; const_assert!(SMALL_F32_POW21.len() > f32_exponent_limit(21).1 as usize); /// Pre-computed, small powers-of-21. pub const SMALL_F64_POW21: [f64; 13] = [ 1.0, 21.0, 441.0, 9261.0, 194481.0, 4084101.0, 85766121.0, 1801088541.0, 37822859361.0, 794280046581.0, 16679880978201.0, 350277500542221.0, 7355827511386641.0, ]; const_assert!(SMALL_F64_POW21.len() > f64_exponent_limit(21).1 as usize); /// Pre-computed large power-of-21 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW21: [u32; 10] = [ 138418921, 1265804130, 2218244279, 959999061, 1977606600, 816701562, 1115590038, 3476226057, 1985711423, 722290, ]; /// Pre-computed large power-of-21 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW21: [u64; 5] = [ 5436587341630151401, 4123164573403953335, 3507706501359722952, 14930277229433621910, 3102213913939263, ]; /// Step for large power-of-21 for 32-bit limbs. pub const LARGE_POW21_STEP: u32 = 70; /// Pre-computed, small powers-of-22. pub const SMALL_INT_POW22: [u64; 15] = [ 1, 22, 484, 10648, 234256, 5153632, 113379904, 2494357888, 54875873536, 1207269217792, 26559922791424, 584318301411328, 12855002631049216, 282810057883082752, 6221821273427820544, ]; const_assert!(SMALL_INT_POW22.len() > f64_mantissa_limit(22) as usize); const_assert!(SMALL_INT_POW22.len() == u64_power_limit(22) as usize + 1); /// Pre-computed, small powers-of-22. pub const SMALL_F32_POW22: [f32; 7] = [1.0, 22.0, 484.0, 10648.0, 234256.0, 5153632.0, 113379904.0]; const_assert!(SMALL_F32_POW22.len() > f32_exponent_limit(22).1 as usize); /// Pre-computed, small powers-of-22. pub const SMALL_F64_POW22: [f64; 16] = [ 1.0, 22.0, 484.0, 10648.0, 234256.0, 5153632.0, 113379904.0, 2494357888.0, 54875873536.0, 1207269217792.0, 26559922791424.0, 584318301411328.0, 1.2855002631049216e+16, 2.8281005788308275e+17, 6.221821273427821e+18, 1.3688006801541205e+20, ]; const_assert!(SMALL_F64_POW22.len() > f64_exponent_limit(22).1 as usize); /// Pre-computed, small powers-of-23. pub const SMALL_INT_POW23: [u64; 15] = [ 1, 23, 529, 12167, 279841, 6436343, 148035889, 3404825447, 78310985281, 1801152661463, 41426511213649, 952809757913927, 21914624432020321, 504036361936467383, 11592836324538749809, ]; const_assert!(SMALL_INT_POW23.len() > f64_mantissa_limit(23) as usize); const_assert!(SMALL_INT_POW23.len() == u64_power_limit(23) as usize + 1); /// Pre-computed, small powers-of-23. pub const SMALL_F32_POW23: [f32; 6] = [1.0, 23.0, 529.0, 12167.0, 279841.0, 6436343.0]; const_assert!(SMALL_F32_POW23.len() > f32_exponent_limit(23).1 as usize); /// Pre-computed, small powers-of-23. pub const SMALL_F64_POW23: [f64; 12] = [ 1.0, 23.0, 529.0, 12167.0, 279841.0, 6436343.0, 148035889.0, 3404825447.0, 78310985281.0, 1801152661463.0, 41426511213649.0, 952809757913927.0, ]; const_assert!(SMALL_F64_POW23.len() > f64_exponent_limit(23).1 as usize); /// Pre-computed large power-of-23 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW23: [u32; 10] = [ 1403677489, 2801905613, 3028338484, 1469351396, 2741227823, 193620048, 1084942677, 2905110101, 3742230796, 421026827, ]; /// Pre-computed large power-of-23 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW23: [u64; 5] = [ 12034092975717509937, 6310816195180283700, 831591776751178031, 12477352876159199573, 1808296456445880588, ]; /// Step for large power-of-23 for 32-bit limbs. pub const LARGE_POW23_STEP: u32 = 70; /// Pre-computed, small powers-of-24. pub const SMALL_INT_POW24: [u64; 14] = [ 1, 24, 576, 13824, 331776, 7962624, 191102976, 4586471424, 110075314176, 2641807540224, 63403380965376, 1521681143169024, 36520347436056576, 876488338465357824, ]; const_assert!(SMALL_INT_POW24.len() > f64_mantissa_limit(24) as usize); const_assert!(SMALL_INT_POW24.len() == u64_power_limit(24) as usize + 1); /// Pre-computed, small powers-of-24. pub const SMALL_F32_POW24: [f32; 16] = [ 1.0, 24.0, 576.0, 13824.0, 331776.0, 7962624.0, 191102976.0, 4586471424.0, 110075314176.0, 2641807540224.0, 63403380965376.0, 1521681143169024.0, 3.652034743605658e+16, 8.764883384653578e+17, 2.1035720123168588e+19, 5.048572829560461e+20, ]; const_assert!(SMALL_F32_POW24.len() > f32_exponent_limit(24).1 as usize); /// Pre-computed, small powers-of-24. pub const SMALL_F64_POW24: [f64; 34] = [ 1.0, 24.0, 576.0, 13824.0, 331776.0, 7962624.0, 191102976.0, 4586471424.0, 110075314176.0, 2641807540224.0, 63403380965376.0, 1521681143169024.0, 3.652034743605658e+16, 8.764883384653578e+17, 2.1035720123168588e+19, 5.048572829560461e+20, 1.2116574790945107e+22, 2.9079779498268256e+23, 6.979147079584381e+24, 1.6749952991002515e+26, 4.0199887178406037e+27, 9.647972922817449e+28, 2.3155135014761877e+30, 5.5572324035428505e+31, 1.333735776850284e+33, 3.200965864440682e+34, 7.682318074657637e+35, 1.8437563379178328e+37, 4.425015211002799e+38, 1.0620036506406717e+40, 2.548808761537612e+41, 6.117141027690269e+42, 1.4681138466456645e+44, 3.523473231949595e+45, ]; const_assert!(SMALL_F64_POW24.len() > f64_exponent_limit(24).1 as usize); /// Pre-computed, small powers-of-25. pub const SMALL_INT_POW25: [u64; 14] = [ 1, 25, 625, 15625, 390625, 9765625, 244140625, 6103515625, 152587890625, 3814697265625, 95367431640625, 2384185791015625, 59604644775390625, 1490116119384765625, ]; const_assert!(SMALL_INT_POW25.len() > f64_mantissa_limit(25) as usize); const_assert!(SMALL_INT_POW25.len() == u64_power_limit(25) as usize + 1); /// Pre-computed, small powers-of-25. pub const SMALL_F32_POW25: [f32; 6] = [1.0, 25.0, 625.0, 15625.0, 390625.0, 9765625.0]; const_assert!(SMALL_F32_POW25.len() > f32_exponent_limit(25).1 as usize); /// Pre-computed, small powers-of-25. pub const SMALL_F64_POW25: [f64; 12] = [ 1.0, 25.0, 625.0, 15625.0, 390625.0, 9765625.0, 244140625.0, 6103515625.0, 152587890625.0, 3814697265625.0, 95367431640625.0, 2384185791015625.0, ]; const_assert!(SMALL_F64_POW25.len() > f64_exponent_limit(25).1 as usize); /// Pre-computed large power-of-25 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW25: [u32; 10] = [ 2358447641, 1624633829, 2031259829, 1986676888, 2941191183, 611941596, 1880507741, 990341507, 3289036379, 14772, ]; /// Pre-computed large power-of-25 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW25: [u64; 5] = [ 6977749165888704025, 8532712263710314677, 2628269144823235599, 4253484386316862813, 63448545932891, ]; /// Step for large power-of-25 for 32-bit limbs. pub const LARGE_POW25_STEP: u32 = 65; /// Pre-computed, small powers-of-26. pub const SMALL_INT_POW26: [u64; 14] = [ 1, 26, 676, 17576, 456976, 11881376, 308915776, 8031810176, 208827064576, 5429503678976, 141167095653376, 3670344486987776, 95428956661682176, 2481152873203736576, ]; const_assert!(SMALL_INT_POW26.len() > f64_mantissa_limit(26) as usize); const_assert!(SMALL_INT_POW26.len() == u64_power_limit(26) as usize + 1); /// Pre-computed, small powers-of-26. pub const SMALL_F32_POW26: [f32; 7] = [1.0, 26.0, 676.0, 17576.0, 456976.0, 11881376.0, 308915776.0]; const_assert!(SMALL_F32_POW26.len() > f32_exponent_limit(26).1 as usize); /// Pre-computed, small powers-of-26. pub const SMALL_F64_POW26: [f64; 15] = [ 1.0, 26.0, 676.0, 17576.0, 456976.0, 11881376.0, 308915776.0, 8031810176.0, 208827064576.0, 5429503678976.0, 141167095653376.0, 3670344486987776.0, 9.542895666168218e+16, 2.4811528732037366e+18, 6.450997470329715e+19, ]; const_assert!(SMALL_F64_POW26.len() > f64_exponent_limit(26).1 as usize); /// Pre-computed, small powers-of-27. pub const SMALL_INT_POW27: [u64; 14] = [ 1, 27, 729, 19683, 531441, 14348907, 387420489, 10460353203, 282429536481, 7625597484987, 205891132094649, 5559060566555523, 150094635296999121, 4052555153018976267, ]; const_assert!(SMALL_INT_POW27.len() > f64_mantissa_limit(27) as usize); const_assert!(SMALL_INT_POW27.len() == u64_power_limit(27) as usize + 1); /// Pre-computed, small powers-of-27. pub const SMALL_F32_POW27: [f32; 6] = [1.0, 27.0, 729.0, 19683.0, 531441.0, 14348907.0]; const_assert!(SMALL_F32_POW27.len() > f32_exponent_limit(27).1 as usize); /// Pre-computed, small powers-of-27. pub const SMALL_F64_POW27: [f64; 12] = [ 1.0, 27.0, 729.0, 19683.0, 531441.0, 14348907.0, 387420489.0, 10460353203.0, 282429536481.0, 7625597484987.0, 205891132094649.0, 5559060566555523.0, ]; const_assert!(SMALL_F64_POW27.len() > f64_exponent_limit(27).1 as usize); /// Pre-computed large power-of-27 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW27: [u32; 10] = [ 1249037595, 465894344, 2861423576, 2518924695, 4122946360, 4029669975, 3949684612, 3795800505, 3556955416, 2197889, ]; /// Pre-computed large power-of-27 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW27: [u64; 5] = [ 2001000972120411419, 10818699188973198296, 17307300760421083960, 16302839035064969092, 9439864932193560, ]; /// Step for large power-of-27 for 32-bit limbs. pub const LARGE_POW27_STEP: u32 = 65; /// Pre-computed, small powers-of-28. pub const SMALL_INT_POW28: [u64; 14] = [ 1, 28, 784, 21952, 614656, 17210368, 481890304, 13492928512, 377801998336, 10578455953408, 296196766695424, 8293509467471872, 232218265089212416, 6502111422497947648, ]; const_assert!(SMALL_INT_POW28.len() > f64_mantissa_limit(28) as usize); const_assert!(SMALL_INT_POW28.len() == u64_power_limit(28) as usize + 1); /// Pre-computed, small powers-of-28. pub const SMALL_F32_POW28: [f32; 9] = [1.0, 28.0, 784.0, 21952.0, 614656.0, 17210368.0, 481890304.0, 13492928512.0, 377801998336.0]; const_assert!(SMALL_F32_POW28.len() > f32_exponent_limit(28).1 as usize); /// Pre-computed, small powers-of-28. pub const SMALL_F64_POW28: [f64; 19] = [ 1.0, 28.0, 784.0, 21952.0, 614656.0, 17210368.0, 481890304.0, 13492928512.0, 377801998336.0, 10578455953408.0, 296196766695424.0, 8293509467471872.0, 2.322182650892124e+17, 6.502111422497948e+18, 1.8205911982994253e+20, 5.097655355238391e+21, 1.4273434994667495e+23, 3.9965617985068985e+24, 1.1190373035819316e+26, ]; const_assert!(SMALL_F64_POW28.len() > f64_exponent_limit(28).1 as usize); /// Pre-computed, small powers-of-29. pub const SMALL_INT_POW29: [u64; 14] = [ 1, 29, 841, 24389, 707281, 20511149, 594823321, 17249876309, 500246412961, 14507145975869, 420707233300201, 12200509765705829, 353814783205469041, 10260628712958602189, ]; const_assert!(SMALL_INT_POW29.len() > f64_mantissa_limit(29) as usize); const_assert!(SMALL_INT_POW29.len() == u64_power_limit(29) as usize + 1); /// Pre-computed, small powers-of-29. pub const SMALL_F32_POW29: [f32; 5] = [1.0, 29.0, 841.0, 24389.0, 707281.0]; const_assert!(SMALL_F32_POW29.len() > f32_exponent_limit(29).1 as usize); /// Pre-computed, small powers-of-29. pub const SMALL_F64_POW29: [f64; 11] = [ 1.0, 29.0, 841.0, 24389.0, 707281.0, 20511149.0, 594823321.0, 17249876309.0, 500246412961.0, 14507145975869.0, 420707233300201.0, ]; const_assert!(SMALL_F64_POW29.len() > f64_exponent_limit(29).1 as usize); /// Pre-computed large power-of-29 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW29: [u32; 10] = [ 3437097245, 219578399, 3191687836, 3061529344, 4005823358, 3201416410, 694756510, 1988053185, 463784885, 228681542, ]; /// Pre-computed large power-of-29 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW29: [u64; 5] = [ 943082046050136349, 13149168411416021660, 13749978785833550718, 8538623412978394270, 982179744552635317, ]; /// Step for large power-of-29 for 32-bit limbs. pub const LARGE_POW29_STEP: u32 = 65; /// Pre-computed, small powers-of-30. pub const SMALL_INT_POW30: [u64; 14] = [ 1, 30, 900, 27000, 810000, 24300000, 729000000, 21870000000, 656100000000, 19683000000000, 590490000000000, 17714700000000000, 531441000000000000, 15943230000000000000, ]; const_assert!(SMALL_INT_POW30.len() > f64_mantissa_limit(30) as usize); const_assert!(SMALL_INT_POW30.len() == u64_power_limit(30) as usize + 1); /// Pre-computed, small powers-of-30. pub const SMALL_F32_POW30: [f32; 7] = [1.0, 30.0, 900.0, 27000.0, 810000.0, 24300000.0, 729000000.0]; const_assert!(SMALL_F32_POW30.len() > f32_exponent_limit(30).1 as usize); /// Pre-computed, small powers-of-30. pub const SMALL_F64_POW30: [f64; 14] = [ 1.0, 30.0, 900.0, 27000.0, 810000.0, 24300000.0, 729000000.0, 21870000000.0, 656100000000.0, 19683000000000.0, 590490000000000.0, 1.77147e+16, 5.31441e+17, 1.594323e+19, ]; const_assert!(SMALL_F64_POW30.len() > f64_exponent_limit(30).1 as usize); /// Pre-computed, small powers-of-31. pub const SMALL_INT_POW31: [u64; 13] = [ 1, 31, 961, 29791, 923521, 28629151, 887503681, 27512614111, 852891037441, 26439622160671, 819628286980801, 25408476896404831, 787662783788549761, ]; const_assert!(SMALL_INT_POW31.len() > f64_mantissa_limit(31) as usize); const_assert!(SMALL_INT_POW31.len() == u64_power_limit(31) as usize + 1); /// Pre-computed, small powers-of-31. pub const SMALL_F32_POW31: [f32; 5] = [1.0, 31.0, 961.0, 29791.0, 923521.0]; const_assert!(SMALL_F32_POW31.len() > f32_exponent_limit(31).1 as usize); /// Pre-computed, small powers-of-31. pub const SMALL_F64_POW31: [f64; 11] = [ 1.0, 31.0, 961.0, 29791.0, 923521.0, 28629151.0, 887503681.0, 27512614111.0, 852891037441.0, 26439622160671.0, 819628286980801.0, ]; const_assert!(SMALL_F64_POW31.len() > f64_exponent_limit(31).1 as usize); /// Pre-computed large power-of-31 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW31: [u32; 10] = [ 3128270977, 627186439, 3737223222, 1519964902, 4275419645, 1305227997, 3310009113, 99290790, 2685019127, 609, ]; /// Pre-computed large power-of-31 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW31: [u64; 5] = [ 2693745247127969921, 6528199548895068214, 5605911565214005757, 426450699154012953, 2618320102391, ]; /// Step for large power-of-31 for 32-bit limbs. pub const LARGE_POW31_STEP: u32 = 60; /// Pre-computed, small powers-of-33. pub const SMALL_INT_POW33: [u64; 13] = [ 1, 33, 1089, 35937, 1185921, 39135393, 1291467969, 42618442977, 1406408618241, 46411484401953, 1531578985264449, 50542106513726817, 1667889514952984961, ]; const_assert!(SMALL_INT_POW33.len() > f64_mantissa_limit(33) as usize); const_assert!(SMALL_INT_POW33.len() == u64_power_limit(33) as usize + 1); /// Pre-computed, small powers-of-33. pub const SMALL_F32_POW33: [f32; 5] = [1.0, 33.0, 1089.0, 35937.0, 1185921.0]; const_assert!(SMALL_F32_POW33.len() > f32_exponent_limit(33).1 as usize); /// Pre-computed, small powers-of-33. pub const SMALL_F64_POW33: [f64; 11] = [ 1.0, 33.0, 1089.0, 35937.0, 1185921.0, 39135393.0, 1291467969.0, 42618442977.0, 1406408618241.0, 46411484401953.0, 1531578985264449.0, ]; const_assert!(SMALL_F64_POW33.len() > f64_exponent_limit(33).1 as usize); /// Pre-computed large power-of-33 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW33: [u32; 10] = [ 1612820353, 1081423072, 127566253, 3291061608, 3338225311, 2497994496, 2486573331, 4032720849, 2585834285, 25953, ]; /// Pre-computed large power-of-33 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW33: [u64; 5] = [ 4644676728992673665, 14135001975608738221, 10728804669246228127, 17320404162838927635, 111469872067373, ]; /// Step for large power-of-33 for 32-bit limbs. pub const LARGE_POW33_STEP: u32 = 60; /// Pre-computed, small powers-of-34. pub const SMALL_INT_POW34: [u64; 13] = [ 1, 34, 1156, 39304, 1336336, 45435424, 1544804416, 52523350144, 1785793904896, 60716992766464, 2064377754059776, 70188843638032384, 2386420683693101056, ]; const_assert!(SMALL_INT_POW34.len() > f64_mantissa_limit(34) as usize); const_assert!(SMALL_INT_POW34.len() == u64_power_limit(34) as usize + 1); /// Pre-computed, small powers-of-34. pub const SMALL_F32_POW34: [f32; 6] = [1.0, 34.0, 1156.0, 39304.0, 1336336.0, 45435424.0]; const_assert!(SMALL_F32_POW34.len() > f32_exponent_limit(34).1 as usize); /// Pre-computed, small powers-of-34. pub const SMALL_F64_POW34: [f64; 13] = [ 1.0, 34.0, 1156.0, 39304.0, 1336336.0, 45435424.0, 1544804416.0, 52523350144.0, 1785793904896.0, 60716992766464.0, 2064377754059776.0, 7.018884363803238e+16, 2.386420683693101e+18, ]; const_assert!(SMALL_F64_POW34.len() > f64_exponent_limit(34).1 as usize); /// Pre-computed, small powers-of-35. pub const SMALL_INT_POW35: [u64; 13] = [ 1, 35, 1225, 42875, 1500625, 52521875, 1838265625, 64339296875, 2251875390625, 78815638671875, 2758547353515625, 96549157373046875, 3379220508056640625, ]; const_assert!(SMALL_INT_POW35.len() > f64_mantissa_limit(35) as usize); const_assert!(SMALL_INT_POW35.len() == u64_power_limit(35) as usize + 1); /// Pre-computed, small powers-of-35. pub const SMALL_F32_POW35: [f32; 5] = [1.0, 35.0, 1225.0, 42875.0, 1500625.0]; const_assert!(SMALL_F32_POW35.len() > f32_exponent_limit(35).1 as usize); /// Pre-computed, small powers-of-35. pub const SMALL_F64_POW35: [f64; 11] = [ 1.0, 35.0, 1225.0, 42875.0, 1500625.0, 52521875.0, 1838265625.0, 64339296875.0, 2251875390625.0, 78815638671875.0, 2758547353515625.0, ]; const_assert!(SMALL_F64_POW35.len() > f64_exponent_limit(35).1 as usize); /// Pre-computed large power-of-35 for 32-bit limbs. #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] pub const LARGE_POW35: [u32; 10] = [ 2481068081, 3589182317, 2073348182, 2214889340, 548239849, 1614245998, 4081052795, 291764764, 3369344364, 886020, ]; /// Pre-computed large power-of-35 for 64-bit limbs. #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] pub const LARGE_POW35: [u64; 5] = [ 15415420673377572913, 9512877281632372822, 6933133769657121257, 1253120123586210939, 3805430292946284, ]; /// Step for large power-of-35 for 32-bit limbs. pub const LARGE_POW35_STEP: u32 = 60; /// Pre-computed, small powers-of-36. pub const SMALL_INT_POW36: [u64; 13] = [ 1, 36, 1296, 46656, 1679616, 60466176, 2176782336, 78364164096, 2821109907456, 101559956668416, 3656158440062976, 131621703842267136, 4738381338321616896, ]; const_assert!(SMALL_INT_POW36.len() > f64_mantissa_limit(36) as usize); const_assert!(SMALL_INT_POW36.len() == u64_power_limit(36) as usize + 1); /// Pre-computed, small powers-of-36. pub const SMALL_F32_POW36: [f32; 8] = [1.0, 36.0, 1296.0, 46656.0, 1679616.0, 60466176.0, 2176782336.0, 78364164096.0]; const_assert!(SMALL_F32_POW36.len() > f32_exponent_limit(36).1 as usize); /// Pre-computed, small powers-of-36. pub const SMALL_F64_POW36: [f64; 17] = [ 1.0, 36.0, 1296.0, 46656.0, 1679616.0, 60466176.0, 2176782336.0, 78364164096.0, 2821109907456.0, 101559956668416.0, 3656158440062976.0, 1.3162170384226714e+17, 4.738381338321617e+18, 1.705817281795782e+20, 6.140942214464815e+21, 2.2107391972073336e+23, 7.958661109946401e+24, ]; const_assert!(SMALL_F64_POW36.len() > f64_exponent_limit(36).1 as usize); lexical-parse-float-0.8.5/src/table_small.rs000064400000000000000000000004730072674642500171420ustar 00000000000000//! Pre-computed small value tables for writing float strings. #![cfg(not(feature = "compact"))] #![doc(hidden)] // Re-export all the feature-specific files. #[cfg(feature = "power-of-two")] pub use crate::table_binary::*; pub use crate::table_decimal::*; #[cfg(feature = "radix")] pub use crate::table_radix::*; lexical-parse-float-0.8.5/tests/api_tests.rs000064400000000000000000002602220072674642500172310ustar 00000000000000#[cfg(feature = "format")] use core::num; use lexical_parse_float::{FromLexical, FromLexicalWithOptions, Options}; #[cfg(feature = "f16")] use lexical_util::bf16::bf16; use lexical_util::error::Error; #[cfg(feature = "f16")] use lexical_util::f16::f16; #[cfg(feature = "format")] use lexical_util::format; #[cfg(any(feature = "format", feature = "power-of-two"))] use lexical_util::format::NumberFormatBuilder; use lexical_util::format::STANDARD; use lexical_util::num::Float; use proptest::prelude::*; use quickcheck::quickcheck; #[test] fn special_bytes_test() { const FORMAT: u128 = STANDARD; // Test serializing and deserializing special strings. assert!(f32::from_lexical(b"NaN").unwrap().is_nan()); assert!(f32::from_lexical(b"nan").unwrap().is_nan()); assert!(f32::from_lexical(b"NAN").unwrap().is_nan()); assert!(f32::from_lexical(b"inf").unwrap().is_infinite()); assert!(f32::from_lexical(b"INF").unwrap().is_infinite()); assert!(f32::from_lexical(b"Infinity").unwrap().is_infinite()); let options = Options::builder().nan_string(Some(b"nan")).inf_string(Some(b"Infinity")).build().unwrap(); // The error message depends on whether the radix feature is enabled. assert!(f32::from_lexical_with_options::(b"inf", &options).is_err()); assert!(f32::from_lexical_with_options::(b"Infinity", &options).unwrap().is_infinite()); } #[test] #[cfg(feature = "power-of-two")] fn invalid_format_test() { const FORMAT: u128 = NumberFormatBuilder::from_radix(40); let options = Options::new(); let res = f32::from_lexical_with_options::(b"inf", &options); assert!(res.is_err()); assert_eq!(res, Err(Error::InvalidMantissaRadix)); } #[test] #[cfg(all(feature = "power-of-two", feature = "format"))] fn invalid_punctuation_test() { const FORMAT: u128 = NumberFormatBuilder::new() .digit_separator(num::NonZeroU8::new(b'h')) .base_prefix(num::NonZeroU8::new(b'h')) .integer_internal_digit_separator(true) .build(); let options = Options::new(); let res = f32::from_lexical_with_options::(b"inf", &options); assert!(res.is_err()); assert_eq!(res, Err(Error::InvalidPunctuation)); } #[test] fn f32_decimal_test() { // integer test assert_eq!(0.0, f32::from_lexical(b"0").unwrap()); assert_eq!(1.0, f32::from_lexical(b"1").unwrap()); assert_eq!(12.0, f32::from_lexical(b"12").unwrap()); assert_eq!(123.0, f32::from_lexical(b"123").unwrap()); assert_eq!(1234.0, f32::from_lexical(b"1234").unwrap()); assert_eq!(12345.0, f32::from_lexical(b"12345").unwrap()); assert_eq!(123456.0, f32::from_lexical(b"123456").unwrap()); assert_eq!(1234567.0, f32::from_lexical(b"1234567").unwrap()); assert_eq!(12345678.0, f32::from_lexical(b"12345678").unwrap()); // No fraction after decimal point test assert_eq!(1.0, f32::from_lexical(b"1.").unwrap()); assert_eq!(12.0, f32::from_lexical(b"12.").unwrap()); assert_eq!(1234567.0, f32::from_lexical(b"1234567.").unwrap()); // No integer before decimal point test assert_eq!(0.1, f32::from_lexical(b".1").unwrap()); assert_eq!(0.12, f32::from_lexical(b".12").unwrap()); assert_eq!(0.1234567, f32::from_lexical(b".1234567").unwrap()); // decimal test assert_eq!(123.1, f32::from_lexical(b"123.1").unwrap()); assert_eq!(123.12, f32::from_lexical(b"123.12").unwrap()); assert_eq!(123.123, f32::from_lexical(b"123.123").unwrap()); assert_eq!(123.1234, f32::from_lexical(b"123.1234").unwrap()); assert_eq!(123.12345, f32::from_lexical(b"123.12345").unwrap()); // rounding test assert_eq!(123456790.0, f32::from_lexical(b"123456789").unwrap()); assert_eq!(123456790.0, f32::from_lexical(b"123456789.1").unwrap()); assert_eq!(123456790.0, f32::from_lexical(b"123456789.12").unwrap()); assert_eq!(123456790.0, f32::from_lexical(b"123456789.123").unwrap()); assert_eq!(123456790.0, f32::from_lexical(b"123456789.1234").unwrap()); assert_eq!(123456790.0, f32::from_lexical(b"123456789.12345").unwrap()); // exponent test assert_eq!(123456789.12345, f32::from_lexical(b"1.2345678912345e8").unwrap()); assert_eq!(123450000.0, f32::from_lexical(b"1.2345e+8").unwrap()); assert_eq!(1.2345e+11, f32::from_lexical(b"1.2345e+11").unwrap()); assert_eq!(1.2345e+11, f32::from_lexical(b"123450000000").unwrap()); assert_eq!(1.2345e+38, f32::from_lexical(b"1.2345e+38").unwrap()); assert_eq!(1.2345e+38, f32::from_lexical(b"123450000000000000000000000000000000000").unwrap()); assert_eq!(1.2345e-8, f32::from_lexical(b"1.2345e-8").unwrap()); assert_eq!(1.2345e-8, f32::from_lexical(b"0.000000012345").unwrap()); assert_eq!(1.2345e-38, f32::from_lexical(b"1.2345e-38").unwrap()); assert_eq!( 1.2345e-38, f32::from_lexical(b"0.000000000000000000000000000000000000012345").unwrap() ); assert!(f32::from_lexical(b"NaN").unwrap().is_nan()); assert!(f32::from_lexical(b"nan").unwrap().is_nan()); assert!(f32::from_lexical(b"NAN").unwrap().is_nan()); assert!(f32::from_lexical(b"inf").unwrap().is_infinite()); assert!(f32::from_lexical(b"INF").unwrap().is_infinite()); assert!(f32::from_lexical(b"+inf").unwrap().is_infinite()); assert!(f32::from_lexical(b"-inf").unwrap().is_infinite()); // Check various expected failures. assert_eq!(Err(Error::Empty(0)), f32::from_lexical(b"")); assert_eq!(Err(Error::EmptyMantissa(0)), f32::from_lexical(b"e")); assert_eq!(Err(Error::EmptyMantissa(0)), f32::from_lexical(b"E")); assert_eq!(Err(Error::EmptyMantissa(1)), f32::from_lexical(b".e1")); assert_eq!(Err(Error::EmptyMantissa(1)), f32::from_lexical(b".e-1")); assert_eq!(Err(Error::EmptyMantissa(0)), f32::from_lexical(b"e1")); assert_eq!(Err(Error::EmptyMantissa(0)), f32::from_lexical(b"e-1")); assert_eq!(Err(Error::Empty(1)), f32::from_lexical(b"+")); assert_eq!(Err(Error::Empty(1)), f32::from_lexical(b"-")); // Bug fix for Issue #8 assert_eq!(Ok(5.002868148396374), f32::from_lexical(b"5.002868148396374")); // Other bug fixes assert_eq!(Ok(7.2625224e+37), f32::from_lexical(b"72625224000000000000000000000000000000")); assert_eq!(Ok(7.2625224e+37), f32::from_lexical(b"72625224000000000000000000000000000000.0")); assert_eq!(Ok(-7.2625224e+37), f32::from_lexical(b"-72625224000000000000000000000000000000")); assert_eq!(Ok(-7.2625224e+37), f32::from_lexical(b"-72625224000000000000000000000000000000.0")); } #[test] #[cfg(feature = "radix")] fn f32_radix_test() { const BASE36: u128 = NumberFormatBuilder::from_radix(36); let options = Options::builder().exponent(b'^').build().unwrap(); assert_eq!(1234.0, f32::from_lexical_with_options::(b"YA", &options).unwrap()); let options = options.rebuild().lossy(true).build().unwrap(); assert_eq!(1234.0, f32::from_lexical_with_options::(b"YA", &options).unwrap()); const BASE21: u128 = NumberFormatBuilder::from_radix(21); assert_eq!( 2879628700000000000000000.0, f32::from_lexical_with_options::(b"4.BHJ97^I", &options).unwrap() ); assert_eq!( 48205230000000000000000000000000000000.0, f32::from_lexical_with_options::(b"4.C4407^17", &options).unwrap() ); assert_eq!( 105861930000000000000000000000000000000.0, f32::from_lexical_with_options::(b"A.15A^17", &options).unwrap() ); assert_eq!( 63900540000000000000000000000000000000.0, f32::from_lexical_with_options::(b"6.1AK^17", &options).unwrap() ); assert_eq!( 48205210000000000000000000000000000000.0, f32::from_lexical_with_options::(b"4.C44^17", &options).unwrap() ); assert_eq!( 48205230000000000000000000000000000000.0, f32::from_lexical_with_options::(b"4C440700000000000000000000000.0", &options) .unwrap() ); } #[test] #[cfg_attr(miri, ignore)] fn parse_f32_test() { let parse = move |x| f32::from_lexical_partial(x); assert_eq!(Ok((0.0, 1)), parse(b"0")); assert_eq!(Ok((1.2345, 6)), parse(b"1.2345")); assert_eq!(Ok((12.345, 6)), parse(b"12.345")); assert_eq!(Ok((12345.6789, 10)), parse(b"12345.6789")); assert_eq!(Ok((1.2345e10, 9)), parse(b"1.2345e10")); assert_eq!(Ok((1.2345e-38, 10)), parse(b"1.2345e-38")); // Check expected rounding, using borderline cases. // Round-down, halfway assert_eq!(Ok((16777216.0, 8)), parse(b"16777216")); assert_eq!(Ok((16777216.0, 8)), parse(b"16777217")); assert_eq!(Ok((16777218.0, 8)), parse(b"16777218")); assert_eq!(Ok((33554432.0, 8)), parse(b"33554432")); assert_eq!(Ok((33554432.0, 8)), parse(b"33554434")); assert_eq!(Ok((33554436.0, 8)), parse(b"33554436")); assert_eq!(Ok((17179869184.0, 11)), parse(b"17179869184")); assert_eq!(Ok((17179869184.0, 11)), parse(b"17179870208")); assert_eq!(Ok((17179871232.0, 11)), parse(b"17179871232")); // Round-up, halfway assert_eq!(Ok((16777218.0, 8)), parse(b"16777218")); assert_eq!(Ok((16777220.0, 8)), parse(b"16777219")); assert_eq!(Ok((16777220.0, 8)), parse(b"16777220")); assert_eq!(Ok((33554436.0, 8)), parse(b"33554436")); assert_eq!(Ok((33554440.0, 8)), parse(b"33554438")); assert_eq!(Ok((33554440.0, 8)), parse(b"33554440")); assert_eq!(Ok((17179871232.0, 11)), parse(b"17179871232")); assert_eq!(Ok((17179873280.0, 11)), parse(b"17179872256")); assert_eq!(Ok((17179873280.0, 11)), parse(b"17179873280")); // Round-up, above halfway assert_eq!(Ok((33554436.0, 8)), parse(b"33554435")); assert_eq!(Ok((17179871232.0, 11)), parse(b"17179870209")); // Check exactly halfway, round-up at halfway assert_eq!(Ok((1.0000001, 28)), parse(b"1.00000017881393432617187499")); assert_eq!(Ok((1.0000002, 26)), parse(b"1.000000178813934326171875")); assert_eq!(Ok((1.0000002, 28)), parse(b"1.00000017881393432617187501")); // Invalid or partially-parsed assert_eq!(Err(Error::EmptyMantissa(0)), parse(b"e10")); assert_eq!(Err(Error::EmptyMantissa(1)), parse(b".")); assert_eq!(Err(Error::EmptyMantissa(1)), parse(b".e10")); assert_eq!(Err(Error::EmptyExponent(2)), parse(b"0e")); assert_eq!(Ok((1.23, 4)), parse(b"1.23/")); // Errors identified via test-parse-random. assert_eq!(Ok((0.0, 21)), parse(b"1.565385248817619e-82")); assert_eq!(Ok((5.483634359675252e34, 20)), parse(b"5.483634359675252e34")); // Test a case from fast_float basictest. assert_eq!(Ok((1.1754941e-38, 1118)), parse(b"1.17549414062751785924617589866280818433124586473279624003138594271817467598606476997247227700427174568176269531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-38")); assert_eq!(Ok((f32::INFINITY, 6)), parse(b"1e1000")); // Errors identified via test-parse-golang. assert_eq!(Ok((0, 25)), parse(b"1.00000000001e-2147483638").map(|(x, y)| (x.to_bits(), y))); } #[test] #[cfg_attr(miri, ignore)] fn parse_f64_test() { let parse = move |x| f64::from_lexical_partial(x); #[cfg(feature = "power-of-two")] let parse_binary = move |x| { const BINARY: u128 = NumberFormatBuilder::from_radix(2); let options = Options::builder().exponent(b'^').build().unwrap(); f64::from_lexical_partial_with_options::(x, &options) }; assert_eq!(Ok((0.0, 1)), parse(b"0")); assert_eq!(Ok((1.2345, 6)), parse(b"1.2345")); assert_eq!(Ok((12.345, 6)), parse(b"12.345")); assert_eq!(Ok((12345.6789, 10)), parse(b"12345.6789")); assert_eq!(Ok((1.2345e10, 9)), parse(b"1.2345e10")); assert_eq!(Ok((1e-323, 6)), parse(b"1e-323")); assert_eq!(Ok((1.2345e-308, 11)), parse(b"1.2345e-308")); // Check expected rounding, using borderline cases. // Round-down, halfway assert_eq!(Ok((9007199254740992.0, 16)), parse(b"9007199254740992")); assert_eq!(Ok((9007199254740992.0, 16)), parse(b"9007199254740993")); assert_eq!(Ok((9007199254740994.0, 16)), parse(b"9007199254740994")); assert_eq!(Ok((18014398509481984.0, 17)), parse(b"18014398509481984")); assert_eq!(Ok((18014398509481984.0, 17)), parse(b"18014398509481986")); assert_eq!(Ok((18014398509481988.0, 17)), parse(b"18014398509481988")); assert_eq!(Ok((9223372036854775808.0, 19)), parse(b"9223372036854775808")); assert_eq!(Ok((9223372036854775808.0, 19)), parse(b"9223372036854776832")); assert_eq!(Ok((9223372036854777856.0, 19)), parse(b"9223372036854777856")); assert_eq!( Ok((11417981541647679048466287755595961091061972992.0, 47)), parse(b"11417981541647679048466287755595961091061972992") ); assert_eq!( Ok((11417981541647679048466287755595961091061972992.0, 47)), parse(b"11417981541647680316116887983825362587765178368") ); assert_eq!( Ok((11417981541647681583767488212054764084468383744.0, 47)), parse(b"11417981541647681583767488212054764084468383744") ); // Round-up, halfway assert_eq!(Ok((9007199254740994.0, 16)), parse(b"9007199254740994")); assert_eq!(Ok((9007199254740996.0, 16)), parse(b"9007199254740995")); assert_eq!(Ok((9007199254740996.0, 16)), parse(b"9007199254740996")); assert_eq!(Ok((18014398509481988.0, 17)), parse(b"18014398509481988")); assert_eq!(Ok((18014398509481992.0, 17)), parse(b"18014398509481990")); assert_eq!(Ok((18014398509481992.0, 17)), parse(b"18014398509481992")); assert_eq!(Ok((9223372036854777856.0, 19)), parse(b"9223372036854777856")); assert_eq!(Ok((9223372036854779904.0, 19)), parse(b"9223372036854778880")); assert_eq!(Ok((9223372036854779904.0, 19)), parse(b"9223372036854779904")); assert_eq!( Ok((11417981541647681583767488212054764084468383744.0, 47)), parse(b"11417981541647681583767488212054764084468383744") ); assert_eq!( Ok((11417981541647684119068688668513567077874794496.0, 47)), parse(b"11417981541647682851418088440284165581171589120") ); assert_eq!( Ok((11417981541647684119068688668513567077874794496.0, 47)), parse(b"11417981541647684119068688668513567077874794496") ); // Round-up, above halfway assert_eq!(Ok((9223372036854777856.0, 19)), parse(b"9223372036854776833")); assert_eq!( Ok((11417981541647681583767488212054764084468383744.0, 47)), parse(b"11417981541647680316116887983825362587765178369") ); // Rounding error // Adapted from failures in strtod. assert_eq!(Ok((2.2250738585072014e-308, 23)), parse(b"2.2250738585072014e-308")); assert_eq!(Ok((2.225073858507201e-308, 776)), parse(b"2.2250738585072011360574097967091319759348195463516456480234261097248222220210769455165295239081350879141491589130396211068700864386945946455276572074078206217433799881410632673292535522868813721490129811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306666559949382757725720157630626906633326475653000092458883164330377797918696120494973903778297049050510806099407302629371289589500035837999672072543043602840788957717961509455167482434710307026091446215722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844239002654981983854879482922068947216898310996983658468140228542433306603398508864458040010349339704275671864433837704860378616227717385456230658746790140867233276367187499e-308")); assert_eq!(Ok((2.2250738585072014e-308, 774)), parse(b"2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508791414915891303962110687008643869459464552765720740782062174337998814106326732925355228688137214901298112245145188984905722230728525513315575501591439747639798341180199932396254828901710708185069063066665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505108060994073026293712895895000358379996720725430436028407889577179615094551674824347103070260914462157228988025818254518032570701886087211312807951223342628836862232150377566662250398253433597456888442390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042756718644338377048603786162277173854562306587467901408672332763671875e-308")); assert_eq!(Ok((2.2250738585072014e-308, 776)), parse(b"2.2250738585072011360574097967091319759348195463516456480234261097248222220210769455165295239081350879141491589130396211068700864386945946455276572074078206217433799881410632673292535522868813721490129811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306666559949382757725720157630626906633326475653000092458883164330377797918696120494973903778297049050510806099407302629371289589500035837999672072543043602840788957717961509455167482434710307026091446215722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844239002654981983854879482922068947216898310996983658468140228542433306603398508864458040010349339704275671864433837704860378616227717385456230658746790140867233276367187501e-308")); assert_eq!(Ok((1.7976931348623157e+308, 380)), parse(b"179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.9999999999999999999999999999999999999999999999999999999999999999999999")); assert_eq!(Ok((5e-324, 761)), parse(b"7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984374999e-324")); assert_eq!(Ok((1e-323, 758)), parse(b"7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375e-324")); assert_eq!(Ok((1e-323, 761)), parse(b"7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375001e-324")); assert_eq!(Ok((1e-320, 6)), parse(b"1e-320")); // Highest denormal float. assert_eq!(Ok((2.2250738585072009e-308, 23)), parse(b"2.2250738585072009e-308")); // Rounding error // Adapted from: // https://www.exploringbinary.com/glibc-strtod-incorrectly-converts-2-to-the-negative-1075/ #[cfg(feature = "power-of-two")] assert_eq!(Ok((5e-324, 14)), parse_binary(b"1^-10000110010")); #[cfg(feature = "power-of-two")] assert_eq!(Ok((0.0, 14)), parse_binary(b"1^-10000110011")); assert_eq!(Ok((0.0, 1077)), parse(b"0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125")); assert_eq!(Ok((5e-324, 1081)), parse(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281250001")); assert_eq!(Ok((5e-324, 1078)), parse(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281251")); // Check with trailing zeros too, before the max number. assert_eq!(Ok((0.0, 1024)), parse(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210200000000")); assert_eq!(Ok((5e-324, 1024)), parse(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210300000000")); assert_eq!(Ok((5e-324, 1024)), parse(b"0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210310000000")); assert_eq!(Ok((0.0, 705)), parse(b"2.47032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210200000000e-324")); assert_eq!(Ok((5e-324, 705)), parse(b"2.47032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210300000000e-324")); assert_eq!(Ok((5e-324, 705)), parse(b"2.47032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210310000000e-324")); // Rounding error // Adapted from: // https://www.exploringbinary.com/how-glibc-strtod-works/ assert_eq!(Ok((2.2250738585072011e-308, 1076)), parse(b"0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375")); // Rounding error // Adapted from test-parse-random failures. assert_eq!(Ok((1.009e-28, 8)), parse(b"1009e-31")); assert_eq!(Ok((f64::INFINITY, 9)), parse(b"18294e304")); // Rounding error // Adapted from a @dangrabcad's issue #20. assert_eq!(Ok((7.689539722041643e164, 21)), parse(b"7.689539722041643e164")); assert_eq!(Ok((7.689539722041643e164, 165)), parse(b"768953972204164300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); assert_eq!(Ok((7.689539722041643e164, 167)), parse(b"768953972204164300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0")); // Check other cases similar to @dangrabcad's issue #20. assert_eq!(Ok((9223372036854777856.0, 21)), parse(b"9223372036854776833.0")); assert_eq!( Ok((11417981541647681583767488212054764084468383744.0, 49)), parse(b"11417981541647680316116887983825362587765178369.0") ); assert_eq!(Ok((9007199254740996.0, 18)), parse(b"9007199254740995.0")); assert_eq!(Ok((18014398509481992.0, 19)), parse(b"18014398509481990.0")); assert_eq!(Ok((9223372036854779904.0, 21)), parse(b"9223372036854778880.0")); assert_eq!( Ok((11417981541647684119068688668513567077874794496.0, 49)), parse(b"11417981541647682851418088440284165581171589120.0") ); // Check other cases ostensibly identified via proptest. assert_eq!(Ok((71610528364411830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 310)), parse(b"71610528364411830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0")); assert_eq!(Ok((126769393745745060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 311)), parse(b"126769393745745060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0")); assert_eq!(Ok((38652960461239320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 310)), parse(b"38652960461239320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0")); // Round-trip for base2. #[cfg(feature = "power-of-two")] { assert_eq!( Ok((f64::from_bits(0x3bcd261840000000), 33)), parse_binary(b"1.1101001001100001100001^-1000011") ); } // Check other bugs in Golang. assert_eq!(Ok((1.0905441441816094e+30, 31)), parse(b"1090544144181609348835077142190")); // Errors identified via test-parse-random. assert_eq!(Ok((-7.014172639932773e-283, 23)), parse(b"-7.014172639932773e-283")); assert_eq!(Ok((1.565385248817619e-82, 21)), parse(b"1.565385248817619e-82")); // Errors identified in fast_float assert_eq!(Ok((1.0905441441816094e+30, 31)), parse(b"1090544144181609348835077142190")); assert_eq!(Ok((f64::INFINITY, 6)), parse(b"1e1000")); assert_eq!( Ok((-2.2400841322710136e+18, 57)), parse(b"-2240084132271013504.131248280843119943687942846658579428") ); // Errors identified via test-parse-golang. assert_eq!(Ok((0.0, 25)), parse(b"1.00000000001e-2147483638")); assert_eq!(Ok((0, 25)), parse(b"1.00000000001e-2147483638").map(|(x, y)| (x.to_bits(), y))); } #[test] fn f64_decimal_test() { // integer test assert_eq!(0.0, f64::from_lexical(b"0").unwrap()); assert_eq!(1.0, f64::from_lexical(b"1").unwrap()); assert_eq!(12.0, f64::from_lexical(b"12").unwrap()); assert_eq!(123.0, f64::from_lexical(b"123").unwrap()); assert_eq!(1234.0, f64::from_lexical(b"1234").unwrap()); assert_eq!(12345.0, f64::from_lexical(b"12345").unwrap()); assert_eq!(123456.0, f64::from_lexical(b"123456").unwrap()); assert_eq!(1234567.0, f64::from_lexical(b"1234567").unwrap()); assert_eq!(12345678.0, f64::from_lexical(b"12345678").unwrap()); // No fraction after decimal point test assert_eq!(1.0, f64::from_lexical(b"1.").unwrap()); assert_eq!(12.0, f64::from_lexical(b"12.").unwrap()); assert_eq!(1234567.0, f64::from_lexical(b"1234567.").unwrap()); // No integer before decimal point test assert_eq!(0.1, f64::from_lexical(b".1").unwrap()); assert_eq!(0.12, f64::from_lexical(b".12").unwrap()); assert_eq!(0.1234567, f64::from_lexical(b".1234567").unwrap()); // decimal test assert_eq!(123456789.0, f64::from_lexical(b"123456789").unwrap()); assert_eq!(123456789.1, f64::from_lexical(b"123456789.1").unwrap()); assert_eq!(123456789.12, f64::from_lexical(b"123456789.12").unwrap()); assert_eq!(123456789.123, f64::from_lexical(b"123456789.123").unwrap()); assert_eq!(123456789.1234, f64::from_lexical(b"123456789.1234").unwrap()); assert_eq!(123456789.12345, f64::from_lexical(b"123456789.12345").unwrap()); assert_eq!(123456789.123456, f64::from_lexical(b"123456789.123456").unwrap()); assert_eq!(123456789.1234567, f64::from_lexical(b"123456789.1234567").unwrap()); assert_eq!(123456789.12345678, f64::from_lexical(b"123456789.12345678").unwrap()); // rounding test assert_eq!(123456789.12345679, f64::from_lexical(b"123456789.123456789").unwrap()); assert_eq!(123456789.12345679, f64::from_lexical(b"123456789.1234567890").unwrap()); assert_eq!(123456789.12345679, f64::from_lexical(b"123456789.123456789012").unwrap()); assert_eq!(123456789.12345679, f64::from_lexical(b"123456789.1234567890123").unwrap()); assert_eq!(123456789.12345679, f64::from_lexical(b"123456789.12345678901234").unwrap()); // exponent test assert_eq!(123456789.12345, f64::from_lexical(b"1.2345678912345e8").unwrap()); assert_eq!(123450000.0, f64::from_lexical(b"1.2345e+8").unwrap()); assert_eq!(1.2345e+11, f64::from_lexical(b"123450000000").unwrap()); assert_eq!(1.2345e+11, f64::from_lexical(b"1.2345e+11").unwrap()); assert_eq!(1.2345e+38, f64::from_lexical(b"1.2345e+38").unwrap()); assert_eq!(1.2345e+38, f64::from_lexical(b"123450000000000000000000000000000000000").unwrap()); assert_eq!(1.2345e+308, f64::from_lexical(b"1.2345e+308").unwrap()); assert_eq!(1.2345e+308, f64::from_lexical(b"123450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()); assert_eq!(0.000000012345, f64::from_lexical(b"1.2345e-8").unwrap()); assert_eq!(1.2345e-8, f64::from_lexical(b"0.000000012345").unwrap()); assert_eq!(1.2345e-38, f64::from_lexical(b"1.2345e-38").unwrap()); assert_eq!( 1.2345e-38, f64::from_lexical(b"0.000000000000000000000000000000000000012345").unwrap() ); // denormalized (try extremely low values) assert_eq!(1.2345e-308, f64::from_lexical(b"1.2345e-308").unwrap()); // due to issues in how the data is parsed, manually extracting // non-exponents of 1.(b"YA", &options).unwrap()); let options = options.rebuild().lossy(true).build().unwrap(); assert_eq!(1234.0, f64::from_lexical_with_options::(b"YA", &options).unwrap()); } #[test] fn parse_f64_large_zeros_test() { // Test numbers with a massive number of 0s in the integer component. let parse = move |x| f64::from_lexical_partial(x); assert_eq!(Ok((71610528364411830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 308)), parse(b"71610528364411830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); assert_eq!(Ok((126769393745745060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 309)), parse(b"126769393745745060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); assert_eq!(Ok((38652960461239320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0, 308)), parse(b"38652960461239320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); } #[test] #[cfg(feature = "power-of-two")] fn parse_binary_f64_test() { #[cfg(feature = "power-of-two")] let parse_binary = move |x| { const BINARY: u128 = NumberFormatBuilder::from_radix(2); let options = Options::builder().exponent(b'^').build().unwrap(); f64::from_lexical_partial_with_options::(x, &options) }; // Test a wide variety of denormal floats here. // Halfway, round-up. assert_eq!( Ok((2.2250738585072009e-308, 65)), parse_binary(b"1111111111111111111111111111111111111111111111111111^-10000110010") ); assert_eq!( Ok((2.2250738585072014e-308, 66)), parse_binary(b"10000000000000000000000000000000000000000000000000000^-10000110010") ); assert_eq!( Ok((2.2250738585072009e-308, 66)), parse_binary(b"11111111111111111111111111111111111111111111111111110^-10000110011") ); assert_eq!( Ok((2.2250738585072014e-308, 66)), parse_binary(b"11111111111111111111111111111111111111111111111111111^-10000110011") ); // Halfway, round-down. assert_eq!( Ok((2.2250738585072004e-308, 65)), parse_binary(b"1111111111111111111111111111111111111111111111111110^-10000110010") ); assert_eq!( Ok((2.2250738585072004e-308, 66)), parse_binary(b"11111111111111111111111111111111111111111111111111101^-10000110011") ); // Force the moderate path (round-up). assert_eq!( Ok((2.2250738585072009e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111100000^-10000110111") ); assert_eq!( Ok((2.2250738585072009e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111101000^-10000110111") ); assert_eq!( Ok((2.2250738585072009e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111101111^-10000110111") ); assert_eq!( Ok((2.2250738585072014e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111110000^-10000110111") ); assert_eq!( Ok((2.2250738585072014e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111111111^-10000110111") ); assert_eq!( Ok((2.2250738585072014e-308, 70)), parse_binary(b"100000000000000000000000000000000000000000000000000000000^-10000110110") ); // Force the moderate path (round-down). assert_eq!( Ok((2.2250738585072004e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111000000^-10000110111") ); assert_eq!( Ok((2.2250738585072004e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111001000^-10000110111") ); assert_eq!( Ok((2.2250738585072004e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111001111^-10000110111") ); assert_eq!( Ok((2.2250738585072004e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111010000^-10000110111") ); assert_eq!( Ok((2.2250738585072009e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111010001^-10000110111") ); assert_eq!( Ok((2.2250738585072009e-308, 70)), parse_binary(b"111111111111111111111111111111111111111111111111111011111^-10000110111") ); // Let's test comically long digits (round-up). assert_eq!(Ok((2.225073858507201e-308, 170)), parse_binary(b"1111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000^-10010011011")); assert_eq!(Ok((2.225073858507201e-308, 170)), parse_binary(b"1111111111111111111111111111111111111111111111111111011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111^-10010011011")); assert_eq!(Ok((2.2250738585072014e-308, 170)), parse_binary(b"1111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000^-10010011011")); assert_eq!(Ok((2.2250738585072014e-308, 170)), parse_binary(b"1111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000^-10010011011")); } #[test] fn parse_f32_lossy_test() { const FORMAT: u128 = STANDARD; let options = Options::builder().lossy(true).build().unwrap(); let parse = move |x| f32::from_lexical_partial_with_options::(x, &options); assert_eq!(Ok((1.2345, 6)), parse(b"1.2345")); assert_eq!(Ok((12.345, 6)), parse(b"12.345")); assert_eq!(Ok((12345.6789, 10)), parse(b"12345.6789")); assert_eq!(Ok((1.2345e10, 9)), parse(b"1.2345e10")); } #[test] fn parse_f64_lossy_test() { const FORMAT: u128 = STANDARD; let options = Options::builder().lossy(true).build().unwrap(); let parse = move |x| f64::from_lexical_partial_with_options::(x, &options); assert_eq!(Ok((1.2345, 6)), parse(b"1.2345")); assert_eq!(Ok((12.345, 6)), parse(b"12.345")); assert_eq!(Ok((12345.6789, 10)), parse(b"12345.6789")); assert_eq!(Ok((1.2345e10, 9)), parse(b"1.2345e10")); } #[test] fn f32_lossy_decimal_test() { const FORMAT: u128 = STANDARD; let options = Options::builder().lossy(true).build().unwrap(); assert_eq!( Err(Error::EmptyMantissa(1)), f32::from_lexical_with_options::(b".", &options) ); assert_eq!(Err(Error::Empty(0)), f32::from_lexical_with_options::(b"", &options)); assert_eq!(Ok(0.0), f32::from_lexical_with_options::(b"0.0", &options)); assert_eq!( Err((Error::InvalidDigit(1)).into()), f32::from_lexical_with_options::(b"1a", &options) ); // Bug fix for Issue #8 assert_eq!( Ok(5.002868148396374), f32::from_lexical_with_options::(b"5.002868148396374", &options) ); } #[test] fn f64_lossy_decimal_test() { const FORMAT: u128 = STANDARD; let options = Options::builder().lossy(true).build().unwrap(); assert_eq!( Err(Error::EmptyMantissa(1)), f64::from_lexical_with_options::(b".", &options) ); assert_eq!(Err(Error::Empty(0)), f64::from_lexical_with_options::(b"", &options)); assert_eq!(Ok(0.0), f64::from_lexical_with_options::(b"0.0", &options)); assert_eq!( Err((Error::InvalidDigit(1)).into()), f64::from_lexical_with_options::(b"1a", &options) ); // Bug fix for Issue #8 assert_eq!( Ok(5.002868148396374), f64::from_lexical_with_options::(b"5.002868148396374", &options) ); } #[cfg(feature = "format")] const fn rebuild(format: u128) -> NumberFormatBuilder { NumberFormatBuilder::rebuild(format) } #[test] #[cfg(feature = "format")] fn f64_special_test() { // Comments match (no_special, case_sensitive, has_sep) const F1: u128 = STANDARD; const F2: u128 = format::IGNORE; const F3: u128 = rebuild(F1).no_special(true).build(); const F4: u128 = rebuild(F1).case_sensitive_special(true).build(); const F5: u128 = rebuild(F2).case_sensitive_special(true).build(); let opts = Options::new(); // Easy NaN assert!(f64::from_lexical_with_options::(b"NaN", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"NaN", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"NaN", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"NaN", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"NaN", &opts).unwrap().is_nan()); // Case-sensitive NaN. assert!(f64::from_lexical_with_options::(b"nan", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"nan", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"nan", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"nan", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"nan", &opts).is_err()); // Digit-separator NaN. assert!(f64::from_lexical_with_options::(b"N_aN", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"N_aN", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"N_aN", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"N_aN", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"N_aN", &opts).unwrap().is_nan()); // Digit-separator + case-sensitive NaN. assert!(f64::from_lexical_with_options::(b"n_an", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_an", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"n_an", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_an", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_an", &opts).is_err()); // Leading digit separator + case-sensitive NaN. assert!(f64::from_lexical_with_options::(b"_n_a_n", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"_n_a_n", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"_n_a_n", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"_n_a_n", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"_n_a_n", &opts).is_err()); // Trailing digit separator + case-sensitive NaN. assert!(f64::from_lexical_with_options::(b"n_a_n_", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_a_n_", &opts).unwrap().is_nan()); assert!(f64::from_lexical_with_options::(b"n_a_n_", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_a_n_", &opts).is_err()); assert!(f64::from_lexical_with_options::(b"n_a_n_", &opts).is_err()); } #[test] #[cfg(feature = "format")] fn case_sensitive_exponent_test() { const FORMAT: u128 = NumberFormatBuilder::new().case_sensitive_exponent(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e+300", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0E+300", &options).is_err()); assert!(f64::from_lexical(b"+3.0e+300").is_ok()); assert!(f64::from_lexical(b"+3.0E+300").is_ok()); } #[test] #[cfg(feature = "format")] fn f64_required_integer_digits_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_integer_digits(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b".0", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_required_fraction_digits_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_fraction_digits(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_required_digits_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_digits(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3", &options).is_ok()); assert!(f64::from_lexical_with_options::(b".0", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_no_positive_mantissa_sign_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).no_positive_mantissa_sign(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_err()); assert!(f64::from_lexical_with_options::(b"-3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_required_mantissa_sign_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_mantissa_sign(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"-3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_no_exponent_notation_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).no_exponent_notation(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3.0e-7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3e", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3e-", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_optional_exponent_test() { const FORMAT: u128 = format::PERMISSIVE; let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e-7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e-", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_required_exponent_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_exponent_digits(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e-7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3.0e-", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_no_positive_exponent_sign_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).no_positive_exponent_sign(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0e+7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3.0e-7", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_required_exponent_sign_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).required_exponent_sign(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3.0e+7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.0e-7", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_no_exponent_without_fraction_test() { const F1: u128 = rebuild(format::PERMISSIVE).no_exponent_without_fraction(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3e7", &options).is_err()); const F2: u128 = rebuild(F1).required_fraction_digits(true).build(); assert!(f64::from_lexical_with_options::(b"3.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"3.e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_no_leading_zeros_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE).no_float_leading_zeros(true).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"1.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"0.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"01.0", &options).is_err()); assert!(f64::from_lexical_with_options::(b"10.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"010.0", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_required_exponent_notation_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .required_exponent_digits(false) .required_exponent_notation(true) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_err()); assert!(f64::from_lexical_with_options::(b"3.0e", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"0.e", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_integer_internal_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .integer_internal_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3_1.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"_31.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31_.0e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_fraction_internal_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .fraction_internal_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.0_1e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31._01e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01_e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_exponent_internal_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .exponent_internal_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.01e7_1", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31.01e_71", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01e71_", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_integer_leading_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .integer_leading_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3_1.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"_31.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31_.0e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_fraction_leading_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .fraction_leading_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.0_1e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31._01e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31.01_e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_exponent_leading_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .exponent_leading_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.01e7_1", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01e_71", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31.01e71_", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_integer_trailing_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .integer_trailing_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3_1.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"_31.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31_.0e7", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_fraction_trailing_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .fraction_trailing_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.0_1e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31._01e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01_e7", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_exponent_trailing_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .exponent_trailing_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.01e7_1", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01e_71", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01e71_", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_integer_consecutive_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .integer_internal_digit_separator(true) .integer_consecutive_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"3__1.0e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"_31.0e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31_.0e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_fraction_consecutive_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .fraction_internal_digit_separator(true) .fraction_consecutive_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.0__1e7", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31._01e7", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01_e7", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_exponent_consecutive_digit_separator_test() { const FORMAT: u128 = rebuild(format::PERMISSIVE) .exponent_internal_digit_separator(true) .exponent_consecutive_digit_separator(true) .digit_separator(num::NonZeroU8::new(b'_')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"31.01e7__1", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"31.01e_71", &options).is_err()); assert!(f64::from_lexical_with_options::(b"31.01e71_", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_json_exponent_without_dot() { // Tests courtesy of @ijl: // https://github.com/Alexhuszagh/rust-lexical/issues/24#issuecomment-578153783 const FORMAT: u128 = format::JSON; let options = Options::new(); // JSONTestSuite/test_parsing/y_number_0e1.json assert!(f64::from_lexical_with_options::(b"0e1", &options).is_ok()); // JSONTestSuite/test_parsing/y_number_int_with_exp.json assert!(f64::from_lexical_with_options::(b"20e1", &options).is_ok()); // JSONTestSuite/test_parsing/y_number_real_capital_e_pos_exp.json assert!(f64::from_lexical_with_options::(b"1E+2", &options).is_ok()); // JSONTestSuite/test_transform/number_1e-999.json assert!(f64::from_lexical_with_options::(b"1E-999", &options).is_ok()); // nativejson-benchmark/data/jsonchecker/pass01.json assert!(f64::from_lexical_with_options::(b"23456789012E66", &options).is_ok()); } #[test] #[cfg(feature = "format")] fn f64_json_exponent_requires_digit() { // Tests courtesy of @ijl: // https://github.com/Alexhuszagh/rust-lexical/issues/24#issuecomment-578153783 const FORMAT: u128 = format::JSON; let options = Options::new(); assert!(f64::from_lexical_with_options::(b"1e", &options).is_err()); // JSONTestSuite/test_parsing/n_number_9.e+.json assert!(f64::from_lexical_with_options::(b"9.e+", &options).is_err()); // JSONTestSuite/test_parsing/n_number_2.e-3.json assert!(f64::from_lexical_with_options::(b"2.e-3", &options).is_err()); // JSONTestSuite/test_parsing/n_number_real_without_fractional_part.json assert!(f64::from_lexical_with_options::(b"1.", &options).is_err()); } #[test] #[cfg(feature = "format")] fn f64_json_no_leading_zero() { const FORMAT: u128 = format::JSON; let options = Options::new(); assert!(f64::from_lexical_with_options::(b"12.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"-12.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"012.0", &options).is_err()); assert!(f64::from_lexical_with_options::(b"-012.0", &options).is_err()); } #[test] #[cfg(all(feature = "power-of-two", feature = "format"))] fn base_prefix_test() { const FORMAT: u128 = NumberFormatBuilder::new().base_prefix(num::NonZeroU8::new(b'x')).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+0x", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+0x ", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+0x3", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3.0e+300", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3.0e+300", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3.0e+300 ", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+0x", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+0x ", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+0x3", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+0x3.0e+300", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+0x3.0e+300", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+0x3.0e+300 ", &options).is_ok()); } #[test] #[cfg(all(feature = "power-of-two", feature = "format"))] fn base_suffix_test() { const FORMAT: u128 = NumberFormatBuilder::new().base_suffix(num::NonZeroU8::new(b'h')).build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"h", &options).is_err()); assert!(f64::from_lexical_with_options::(b"-h ", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+h ", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+3h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e+300h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e+300h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+3.0e+300h ", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+h", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+h ", &options).is_err()); assert!(f64::from_lexical_partial_with_options::(b"+3h", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0h", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0e+300h", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0e+300h", &options).is_ok()); assert!(f64::from_lexical_partial_with_options::(b"+3.0e+300h ", &options).is_ok()); } #[test] #[cfg(all(feature = "power-of-two", feature = "format"))] fn base_prefix_and_suffix_test() { const FORMAT: u128 = NumberFormatBuilder::new() .base_prefix(num::NonZeroU8::new(b'x')) .base_suffix(num::NonZeroU8::new(b'h')) .build(); let options = Options::new(); assert!(f64::from_lexical_with_options::(b"+3h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0xh", &options).is_err()); assert!(f64::from_lexical_with_options::(b"+0x3.0e+300h", &options).is_ok()); assert!(f64::from_lexical_with_options::(b"+0x3.0e+300h ", &options).is_err()); } #[test] #[cfg(feature = "format")] fn issue66_test() { const RUST: u128 = format::RUST_LITERAL; const JSON: u128 = format::JSON; const CXX: u128 = format::CXX17_LITERAL; let options = Options::new(); assert_eq!(f64::from_lexical_with_options::(b"42.0", &options), Ok(42.0)); assert_eq!(f64::from_lexical_with_options::(b"42.0", &options), Ok(42.0)); assert_eq!(f64::from_lexical_with_options::(b"4_2.0", &options), Ok(42.0)); assert_eq!(f64::from_lexical_with_options::(b"42.0", &options), Ok(42.0)); assert_eq!(f64::from_lexical_with_options::(b"4'2.0", &options), Ok(42.0)); } #[test] #[cfg(feature = "power-of-two")] fn issue68_test() { const FORMAT: u128 = NumberFormatBuilder::from_radix(16); let options = Options::builder().exponent(b'^').build().unwrap(); // Roughly 2^1375, 15 1s. let hex = b"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; assert_eq!(f32::INFINITY, f32::from_lexical_with_options::(hex, &options).unwrap()); assert_eq!(f64::INFINITY, f64::from_lexical_with_options::(hex, &options).unwrap()); } fn float_equal(x: F, y: F) -> bool { if x.is_nan() { y.is_nan() } else { y == x } } quickcheck! { #[cfg_attr(miri, ignore)] fn f32_roundtrip_quickcheck(x: f32) -> bool { let string = x.to_string(); let result = f32::from_lexical(string.as_bytes()); result.map_or(false, |y| float_equal(x, y)) } #[cfg_attr(miri, ignore)] fn f32_short_decimal_quickcheck(x: f32) -> bool { let string = format!("{:.4}", x); let actual = f32::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } #[cfg_attr(miri, ignore)] fn f32_long_decimal_quickcheck(x: f32) -> bool { let string = format!("{:.100}", x); let actual = f32::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } #[cfg_attr(miri, ignore)] fn f32_short_exponent_quickcheck(x: f32) -> bool { let string = format!("{:.4e}", x); let actual = f32::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } #[cfg_attr(miri, ignore)] fn f32_long_exponent_quickcheck(x: f32) -> bool { let string = format!("{:.100e}", x); let actual = f32::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } #[cfg_attr(miri, ignore)] fn f64_roundtrip_quickcheck(x: f64) -> bool { let string = x.to_string(); let result = f64::from_lexical(string.as_bytes()); result.map_or(false, |y| float_equal(x, y)) } #[cfg_attr(miri, ignore)] fn f64_short_decimal_quickcheck(x: f64) -> bool { let string = format!("{:.4}", x); let actual = f64::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } #[cfg_attr(miri, ignore)] fn f64_long_decimal_quickcheck(x: f64) -> bool { let string = format!("{:.100}", x); let actual = f64::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } #[cfg_attr(miri, ignore)] fn f64_short_exponent_quickcheck(x: f64) -> bool { let string = format!("{:.4e}", x); let actual = f64::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } #[cfg_attr(miri, ignore)] fn f64_long_exponent_quickcheck(x: f64) -> bool { let string = format!("{:.100e}", x); let actual = f64::from_lexical(string.as_bytes()); let expected = string.parse::(); actual.map_or(false, |y| expected.map_or(false, |x| float_equal(x, y))) } #[cfg(feature = "f16")] #[cfg_attr(miri, ignore)] fn f16_roundtrip_quickcheck(bits: u16) -> bool { let x = f16::from_bits(bits); let string = x.as_f32().to_string(); let result = f16::from_lexical(string.as_bytes()); result.map_or(false, |y| float_equal(x, y)) } #[cfg(feature = "f16")] #[cfg_attr(miri, ignore)] fn bf16_roundtrip_quickcheck(bits: u16) -> bool { let x = bf16::from_bits(bits); let string = x.as_f32().to_string(); let result = bf16::from_lexical(string.as_bytes()); result.map_or(false, |y| float_equal(x, y)) } } proptest! { #[test] #[cfg_attr(miri, ignore)] fn f32_invalid_proptest(i in r"[+-]?[0-9]{2}[^\deE]?\.[^\deE]?[0-9]{2}[^\deE]?e[+-]?[0-9]+[^\deE]") { let res = f32::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_invalid_digit()); } #[test] #[cfg_attr(miri, ignore)] fn f32_double_sign_proptest(i in r"[+-]{2}[0-9]{2}\.[0-9]{2}e[+-]?[0-9]+") { let res = f32::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!( res.err().unwrap().is_invalid_digit() || res.err().unwrap().is_empty_mantissa() ); } #[test] #[cfg_attr(miri, ignore)] fn f32_sign_or_dot_only_proptest(i in r"[+-]?\.?") { let res = f32::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!( res.err().unwrap().is_empty() || res.err().unwrap().is_empty_mantissa() ); } #[test] #[cfg_attr(miri, ignore)] fn f32_double_exponent_sign_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]{2}[0-9]+") { let res = f32::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_empty_exponent()); } #[test] #[cfg_attr(miri, ignore)] fn f32_missing_exponent_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]?") { let res = f32::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_empty_exponent()); } #[test] #[cfg_attr(miri, ignore)] fn f32_roundtrip_display_proptest(i in f32::MIN..f32::MAX) { let input: String = format!("{}", i); prop_assert_eq!(i, f32::from_lexical(input.as_bytes()).unwrap()); } #[test] #[cfg_attr(miri, ignore)] fn f32_roundtrip_debug_proptest(i in f32::MIN..f32::MAX) { let input: String = format!("{:?}", i); prop_assert_eq!(i, f32::from_lexical(input.as_bytes()).unwrap()); } #[test] #[cfg_attr(miri, ignore)] fn f32_roundtrip_scientific_proptest(i in f32::MIN..f32::MAX) { let input: String = format!("{:e}", i); prop_assert_eq!(i, f32::from_lexical(input.as_bytes()).unwrap()); } #[test] #[cfg_attr(miri, ignore)] fn f64_invalid_proptest(i in r"[+-]?[0-9]{2}[^\deE]?\.[^\deE]?[0-9]{2}[^\deE]?e[+-]?[0-9]+[^\deE]") { let res = f64::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_invalid_digit()); } #[test] #[cfg_attr(miri, ignore)] fn f64_double_sign_proptest(i in r"[+-]{2}[0-9]{2}\.[0-9]{2}e[+-]?[0-9]+") { let res = f64::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!( res.err().unwrap().is_invalid_digit() || res.err().unwrap().is_empty_mantissa() ); } #[test] #[cfg_attr(miri, ignore)] fn f64_sign_or_dot_only_proptest(i in r"[+-]?\.?") { let res = f64::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!( res.err().unwrap().is_empty() || res.err().unwrap().is_empty_mantissa() ); } #[test] #[cfg_attr(miri, ignore)] fn f64_double_exponent_sign_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]{2}[0-9]+") { let res = f64::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_empty_exponent()); } #[test] #[cfg_attr(miri, ignore)] fn f64_missing_exponent_proptest(i in r"[+-]?[0-9]{2}\.[0-9]{2}e[+-]?") { let res = f64::from_lexical(i.as_bytes()); prop_assert!(res.is_err()); prop_assert!(res.err().unwrap().is_empty_exponent()); } #[test] #[cfg_attr(miri, ignore)] fn f64_roundtrip_display_proptest(i in f64::MIN..f64::MAX) { let input: String = format!("{}", i); prop_assert_eq!(i, f64::from_lexical(input.as_bytes()).unwrap()); } #[test] #[cfg_attr(miri, ignore)] fn f64_roundtrip_debug_proptest(i in f64::MIN..f64::MAX) { let input: String = format!("{:?}", i); prop_assert_eq!(i, f64::from_lexical(input.as_bytes()).unwrap()); } #[test] #[cfg_attr(miri, ignore)] fn f64_roundtrip_scientific_proptest(i in f64::MIN..f64::MAX) { let input: String = format!("{:e}", i); prop_assert_eq!(i, f64::from_lexical(input.as_bytes()).unwrap()); } } lexical-parse-float-0.8.5/tests/bellerophon.rs000064400000000000000000000033250072674642500175460ustar 00000000000000#![cfg(any(feature = "compact", feature = "radix"))] #![allow(dead_code)] use lexical_parse_float::bellerophon::bellerophon; use lexical_parse_float::float::{extended_to_float, ExtendedFloat80, RawFloat}; use lexical_parse_float::number::Number; use lexical_util::format::STANDARD; pub fn bellerophon_test( xmant: u64, xexp: i32, many_digits: bool, ymant: u64, yexp: i32, ) { let num = Number { exponent: xexp as i64, mantissa: xmant, is_negative: false, many_digits, integer: &[], fraction: None, }; let xfp = bellerophon::(&num, false); let yfp = ExtendedFloat80 { mant: ymant, exp: yexp, }; // Given us useful error messages if the floats are valid. if xfp.exp >= 0 && yfp.exp >= 0 { assert!( xfp == yfp, "x != y, xfp={:?}, yfp={:?}, x={:?}, y={:?}", xfp, yfp, extended_to_float::(xfp), extended_to_float::(yfp) ); } else { assert_eq!(xfp, yfp); } } pub fn compute_float32(q: i64, w: u64) -> (i32, u64) { let num = Number { exponent: q, mantissa: w, is_negative: false, many_digits: false, integer: &[], fraction: None, }; let fp = bellerophon::(&num, false); (fp.exp, fp.mant) } pub fn compute_float64(q: i64, w: u64) -> (i32, u64) { let num = Number { exponent: q, mantissa: w, is_negative: false, many_digits: false, integer: &[], fraction: None, }; let fp = bellerophon::(&num, false); (fp.exp, fp.mant) } lexical-parse-float-0.8.5/tests/bellerophon_radix_tests.rs000064400000000000000000000021460072674642500221570ustar 00000000000000#![cfg(feature = "radix")] mod bellerophon; use bellerophon::bellerophon_test; use lexical_util::format::NumberFormatBuilder; const BASE3: u128 = NumberFormatBuilder::from_radix(3); #[test] fn bellerophon_radix_test() { // Checking the exact rounding of the digits close to 5e-324. bellerophon_test::(5, -640, false, 4172256988254845, 10); bellerophon_test::(2, -679, false, 0, 0); bellerophon_test::(3, -679, false, 1, 0); bellerophon_test::(6, -680, false, 0, 0); bellerophon_test::(7, -680, false, 1, 0); bellerophon_test::(20, -681, false, 0, 0); bellerophon_test::(21, -681, false, 1, 0); bellerophon_test::(61, -682, false, 0, 0); bellerophon_test::(62, -682, false, 1, 0); bellerophon_test::(184, -683, false, 0, 0); bellerophon_test::(185, -683, false, 1, 0); bellerophon_test::(554, -684, false, 0, 0); bellerophon_test::(555, -684, false, 1, 0); } lexical-parse-float-0.8.5/tests/bellerophon_tests.rs000064400000000000000000000237750072674642500210030ustar 00000000000000#![cfg(feature = "compact")] mod bellerophon; use bellerophon::{bellerophon_test, compute_float32, compute_float64}; use lexical_parse_float::shared::INVALID_FP; use lexical_util::format::STANDARD; #[test] fn halfway_round_down_test() { // Halfway, round-down tests bellerophon_test::(9007199254740992, 0, false, 0, 1076); bellerophon_test::( 9007199254740993, 0, false, 9223372036854776832, 1065 + INVALID_FP, ); bellerophon_test::(9007199254740994, 0, false, 1, 1076); bellerophon_test::(18014398509481984, 0, false, 0, 1077); bellerophon_test::( 18014398509481986, 0, false, 9223372036854776832, 1066 + INVALID_FP, ); bellerophon_test::(18014398509481988, 0, false, 1, 1077); bellerophon_test::(9223372036854775808, 0, false, 0, 1086); bellerophon_test::( 9223372036854776832, 0, false, 9223372036854776832, 1075 + INVALID_FP, ); bellerophon_test::(9223372036854777856, 0, false, 1, 1086); // Add a 0 but say we're truncated. bellerophon_test::(9007199254740992000, -3, true, 0, 1076); bellerophon_test::( 9007199254740993000, -3, true, 9223372036854776832, 1065 + INVALID_FP, ); bellerophon_test::(9007199254740994000, -3, true, 1, 1076); } #[test] fn halfway_round_up_test() { // Halfway, round-up tests bellerophon_test::(9007199254740994, 0, false, 1, 1076); bellerophon_test::( 9007199254740995, 0, false, 9223372036854778880, 1065 + INVALID_FP, ); bellerophon_test::(9007199254740996, 0, false, 2, 1076); bellerophon_test::(18014398509481988, 0, false, 1, 1077); bellerophon_test::( 18014398509481990, 0, false, 9223372036854778880, 1066 + INVALID_FP, ); bellerophon_test::(18014398509481992, 0, false, 2, 1077); bellerophon_test::(9223372036854777856, 0, false, 1, 1086); bellerophon_test::( 9223372036854778880, 0, false, 9223372036854778880, 1075 + INVALID_FP, ); bellerophon_test::(9223372036854779904, 0, false, 2, 1086); // Add a 0 but say we're truncated. bellerophon_test::(9007199254740994000, -3, true, 1, 1076); bellerophon_test::( 9007199254740994990, -3, true, 9223372036854778869, 1065 + INVALID_FP, ); bellerophon_test::( 9007199254740995000, -3, true, 9223372036854778879, 1065 + INVALID_FP, ); bellerophon_test::( 9007199254740995010, -3, true, 9223372036854778890, 1065 + INVALID_FP, ); bellerophon_test::(9007199254740995050, -3, true, 2, 1076); bellerophon_test::(9007199254740996000, -3, true, 2, 1076); } #[test] fn extremes_test() { // Need to check we get proper results with rounding for near-infinity // and near-zero and/or denormal floats. bellerophon_test::(5, -324, false, 1, 0); bellerophon_test::(10, -324, false, 2, 0); // This is very close to 2.4703282292062327206e-342. bellerophon_test::( 2470328229206232720, -342, false, 18446744073709551608, -64 + INVALID_FP, ); bellerophon_test::( 2470328229206232721, -342, false, 9223372036854775808, -32831, ); bellerophon_test::( 2470328229206232725, -342, false, 9223372036854775824, -32831, ); bellerophon_test::(2470328229206232726, -342, false, 1, 0); bellerophon_test::(2470328229206232730, -342, false, 1, 0); // Check very close to literal infinity. // 17.976931348623155 // 1.797693134862315508561243283845062402343434371574593359244049e+308 // 1.797693134862315708145274237317043567980705675258449965989175e+308 bellerophon_test::(17976931348623155, 292, false, 4503599627370494, 2046); bellerophon_test::(17976931348623156, 292, false, 4503599627370494, 2046); bellerophon_test::(1797693134862315605, 290, false, 4503599627370494, 2046); bellerophon_test::(1797693134862315607, 290, false, 4503599627370494, 2046); bellerophon_test::( 1797693134862315608, 290, false, 18446744073709548540, -30733, ); bellerophon_test::( 1797693134862315609, 290, false, 18446744073709548550, -30733, ); bellerophon_test::(179769313486231561, 291, false, 4503599627370495, 2046); bellerophon_test::(17976931348623157, 292, false, 4503599627370495, 2046); // Check existing issues and underflow. bellerophon_test::(2470328229206232726, -343, false, 0, 0); bellerophon_test::(2470328229206232726, -342, false, 1, 0); bellerophon_test::(1, -250, false, 1945308223406668, 192); bellerophon_test::(1, -150, false, 2867420733609077, 524); bellerophon_test::(1, -45, false, 1924152549665465, 873); bellerophon_test::(1, -40, false, 400386103400348, 890); bellerophon_test::(1, -20, false, 2142540351554083, 956); bellerophon_test::(1, 0, false, 0, 1023); bellerophon_test::(1, 20, false, 1599915997629504, 1089); bellerophon_test::(1, 40, false, 3768206498159781, 1155); bellerophon_test::(1, 150, false, 999684479948463, 1521); bellerophon_test::(1, 250, false, 1786584717939204, 1853); // Minimum positive normal float. bellerophon_test::(22250738585072014, -324, false, 0, 1); // Maximum positive subnormal float. bellerophon_test::(2225073858507201, -323, false, 4503599627370495, 0); // Next highest subnormal float. bellerophon_test::(22250738585072004, -324, false, 4503599627370494, 0); bellerophon_test::(22250738585072006, -324, false, 4503599627370494, 0); bellerophon_test::(22250738585072007, -324, false, 4503599627370495, 0); bellerophon_test::(222507385850720062, -325, false, 4503599627370494, 0); bellerophon_test::(222507385850720063, -325, false, 4503599627370494, 0); bellerophon_test::(222507385850720064, -325, false, 4503599627370494, 0); bellerophon_test::( 2225073858507200641, -326, false, 18446744073709545462, -32779, ); bellerophon_test::( 2225073858507200642, -326, false, 18446744073709545472, -32779, ); bellerophon_test::(222507385850720065, -325, false, 4503599627370495, 0); } #[test] fn compute_float_f32_test() { // These test near-halfway cases for single-precision floats. assert_eq!(compute_float32(0, 16777216), (151, 0)); assert_eq!(compute_float32(0, 16777217), (111 + INVALID_FP, 9223372586610589696)); assert_eq!(compute_float32(0, 16777218), (151, 1)); assert_eq!(compute_float32(0, 16777219), (111 + INVALID_FP, 9223373686122217472)); assert_eq!(compute_float32(0, 16777220), (151, 2)); // These are examples of the above tests, with // digits from the exponent shifted to the mantissa. assert_eq!(compute_float32(-10, 167772160000000000), (151, 0)); assert_eq!(compute_float32(-10, 167772170000000000), (111 + INVALID_FP, 9223372586610589696)); assert_eq!(compute_float32(-10, 167772180000000000), (151, 1)); // Let's check the lines to see if anything is different in table... assert_eq!(compute_float32(-10, 167772190000000000), (111 + INVALID_FP, 9223373686122217472)); assert_eq!(compute_float32(-10, 167772200000000000), (151, 2)); } #[test] fn compute_float_f64_test() { // These test near-halfway cases for double-precision floats. assert_eq!(compute_float64(0, 9007199254740992), (1076, 0)); assert_eq!(compute_float64(0, 9007199254740993), (1065 + INVALID_FP, 9223372036854776832)); assert_eq!(compute_float64(0, 9007199254740994), (1076, 1)); assert_eq!(compute_float64(0, 9007199254740995), (1065 + INVALID_FP, 9223372036854778880)); assert_eq!(compute_float64(0, 9007199254740996), (1076, 2)); assert_eq!(compute_float64(0, 18014398509481984), (1077, 0)); assert_eq!(compute_float64(0, 18014398509481986), (1066 + INVALID_FP, 9223372036854776832)); assert_eq!(compute_float64(0, 18014398509481988), (1077, 1)); assert_eq!(compute_float64(0, 18014398509481990), (1066 + INVALID_FP, 9223372036854778880)); assert_eq!(compute_float64(0, 18014398509481992), (1077, 2)); // These are examples of the above tests, with // digits from the exponent shifted to the mantissa. assert_eq!(compute_float64(-3, 9007199254740992000), (1076, 0)); assert_eq!(compute_float64(-3, 9007199254740993000), (1065 + INVALID_FP, 9223372036854776832)); assert_eq!(compute_float64(-3, 9007199254740994000), (1076, 1)); assert_eq!(compute_float64(-3, 9007199254740995000), (1065 + INVALID_FP, 9223372036854778879)); assert_eq!(compute_float64(-3, 9007199254740996000), (1076, 2)); } lexical-parse-float-0.8.5/tests/bigfloat_tests.rs000064400000000000000000000032210072674642500202410ustar 00000000000000#![cfg(feature = "radix")] mod stackvec; use lexical_parse_float::bigint::{Bigfloat, LIMB_BITS}; use lexical_parse_float::float::ExtendedFloat80; use stackvec::vec_from_u32; #[test] fn simple_test() { let x = Bigfloat::new(); assert_eq!(x.exp, 0); let y = Bigfloat::from_float(ExtendedFloat80 { mant: 1 << 63, exp: -63, }); assert_eq!(y.exp, -63); let x = Bigfloat::from_u32(1); assert_eq!(&*x.data, &[1]); let mut x = Bigfloat::from_u64(1); assert_eq!(&*x.data, &[1]); x.pow(10, 10); assert_eq!(&*x.data, &[9765625]); assert_eq!(x.exp, 10); x.shl_bits(1); assert_eq!(&*x.data, &[19531250]); assert_eq!(x.exp, 10); x.shl_limbs(1); assert_eq!(&*x.data, &[0, 19531250]); assert_eq!(x.exp, 10); assert_eq!(x.leading_zeros(), LIMB_BITS as u32 - 25); // y has a 0 for 32-bit limbs, no 0s for 64-bit limbs. x *= &y; let expected = if LIMB_BITS == 32 { vec_from_u32(&[0, 0, 0, 9765625]) } else { vec_from_u32(&[0, 0, 0, 0, 9765625]) }; assert!(x.data == expected, "failed"); assert_eq!(x.exp, -53); } #[test] fn leading_zeros_test() { assert_eq!(Bigfloat::new().leading_zeros(), 0); assert_eq!(Bigfloat::from_u32(0xFF).leading_zeros(), LIMB_BITS as u32 - 8); assert_eq!(Bigfloat::from_u64(0xFF00000000).leading_zeros(), 24); assert_eq!(Bigfloat::from_u32(0xF).leading_zeros(), LIMB_BITS as u32 - 4); assert_eq!(Bigfloat::from_u64(0xF00000000).leading_zeros(), 28); assert_eq!(Bigfloat::from_u32(0xF0).leading_zeros(), LIMB_BITS as u32 - 8); assert_eq!(Bigfloat::from_u64(0xF000000000).leading_zeros(), 24); } lexical-parse-float-0.8.5/tests/bigint_tests.rs000064400000000000000000000011370072674642500177320ustar 00000000000000mod stackvec; use lexical_parse_float::bigint::Bigint; use stackvec::vec_from_u32; #[test] fn simple_test() { let x = Bigint::new(); assert_eq!(x.hi64(), (0, false)); let x = Bigint::from_u32(1); assert_eq!(&*x.data, &[1]); let mut x = Bigint::from_u64(1); assert_eq!(&*x.data, &[1]); x.pow(10, 10); let expected = vec_from_u32(&[1410065408, 2]); assert!(x.data == expected, "failed"); assert_eq!(x.bit_length(), 34); let y = Bigint::from_u64(5); x *= &y; let expected = vec_from_u32(&[2755359744, 11]); assert!(x.data == expected, "failed"); } lexical-parse-float-0.8.5/tests/binary_tests.rs000064400000000000000000000155470072674642500177540ustar 00000000000000#![cfg(feature = "power-of-two")] use lexical_parse_float::binary::{binary, slow_binary}; use lexical_parse_float::number::Number; use lexical_util::format::NumberFormatBuilder; const BINARY: u128 = NumberFormatBuilder::from_radix(2); const BASE4: u128 = NumberFormatBuilder::from_radix(4); const OCTAL: u128 = NumberFormatBuilder::from_radix(8); const HEX: u128 = NumberFormatBuilder::from_radix(16); const BASE32: u128 = NumberFormatBuilder::from_radix(32); fn compute_float32(q: i64, w: u64, many_digits: bool) -> (i32, u64) { let num = Number { exponent: q, mantissa: w, is_negative: false, many_digits, integer: &[], fraction: None, }; let fp = binary::(&num, false); (fp.exp, fp.mant) } fn compute_float64(q: i64, w: u64, many_digits: bool) -> (i32, u64) { let num = Number { exponent: q, mantissa: w, is_negative: false, many_digits, integer: &[], fraction: None, }; let fp = binary::(&num, false); (fp.exp, fp.mant) } #[test] fn computef32_test() { // Halfway, round-down tests assert_eq!(compute_float32::(0, 16777216, false), (151, 0)); assert_eq!(compute_float32::(0, 16777217, false), (151, 0)); assert_eq!(compute_float32::(0, 16777218, false), (151, 1)); assert_eq!(compute_float32::(0, 33554432, false), (152, 0)); assert_eq!(compute_float32::(0, 33554434, false), (152, 0)); assert_eq!(compute_float32::(0, 33554436, false), (152, 1)); } #[test] fn halfway_round_down_test() { // Halfway, round-down tests assert_eq!(compute_float64::(0, 9007199254740992, false), (1076, 0)); assert_eq!(compute_float64::(0, 9007199254740993, false), (1076, 0)); assert_eq!(compute_float64::(0, 9007199254740994, false), (1076, 1)); assert_eq!(compute_float64::(0, 18014398509481984, false), (1077, 0)); assert_eq!(compute_float64::(0, 18014398509481986, false), (1077, 0)); assert_eq!(compute_float64::(0, 18014398509481988, false), (1077, 1)); assert_eq!(compute_float64::(0, 9223372036854775808, false), (1086, 0)); assert_eq!(compute_float64::(0, 9223372036854776832, false), (1086, 0)); assert_eq!(compute_float64::(0, 9223372036854777856, false), (1086, 1)); // Add a 0 but say we're truncated. assert_eq!(compute_float64::(-10, 9223372036854775808, true), (1076, 0)); assert_eq!( compute_float64::(-10, 9223372036854776832, true), (-31703, 9223372036854776832) ); assert_eq!(compute_float64::(-10, 9223372036854777856, true), (1076, 1)); // Check other bases. assert_eq!(compute_float64::(-2, 144115188075855872, false), (1076, 0)); assert_eq!(compute_float64::(-2, 144115188075855888, false), (1076, 0)); assert_eq!(compute_float64::(-2, 144115188075855904, false), (1076, 1)); assert_eq!(compute_float64::(-2, 576460752303423488, false), (1076, 0)); assert_eq!(compute_float64::(-2, 576460752303423552, false), (1076, 0)); assert_eq!(compute_float64::(-2, 576460752303423616, false), (1076, 1)); assert_eq!(compute_float64::(-1, 144115188075855872, false), (1076, 0)); assert_eq!(compute_float64::(-1, 144115188075855888, false), (1076, 0)); assert_eq!(compute_float64::(-1, 144115188075855904, false), (1076, 1)); assert_eq!(compute_float64::(-1, 288230376151711744, false), (1076, 0)); assert_eq!(compute_float64::(-1, 288230376151711776, false), (1076, 0)); assert_eq!(compute_float64::(-1, 288230376151711808, false), (1076, 1)); } #[test] fn test_halfway_round_up() { // Halfway, round-up tests assert_eq!(compute_float64::(0, 9007199254740994, false), (1076, 1)); assert_eq!(compute_float64::(0, 9007199254740995, false), (1076, 2)); assert_eq!(compute_float64::(0, 9007199254740996, false), (1076, 2)); assert_eq!(compute_float64::(0, 18014398509481988, false), (1077, 1)); assert_eq!(compute_float64::(0, 18014398509481990, false), (1077, 2)); assert_eq!(compute_float64::(0, 18014398509481992, false), (1077, 2)); assert_eq!(compute_float64::(0, 9223372036854777856, false), (1086, 1)); assert_eq!(compute_float64::(0, 9223372036854778880, false), (1086, 2)); assert_eq!(compute_float64::(0, 9223372036854779904, false), (1086, 2)); // Add a 0 but say we're truncated. assert_eq!(compute_float64::(-10, 9223372036854777856, true), (1076, 1)); assert_eq!(compute_float64::(-10, 9223372036854778879, true), (1076, 1)); assert_eq!(compute_float64::(-10, 9223372036854778880, true), (1076, 2)); assert_eq!(compute_float64::(-10, 9223372036854779904, true), (1076, 2)); // Check other bases. assert_eq!(compute_float64::(-2, 144115188075855904, false), (1076, 1)); assert_eq!(compute_float64::(-2, 144115188075855920, false), (1076, 2)); assert_eq!(compute_float64::(-2, 144115188075855936, false), (1076, 2)); assert_eq!(compute_float64::(-2, 576460752303423616, false), (1076, 1)); assert_eq!(compute_float64::(-2, 576460752303423680, false), (1076, 2)); assert_eq!(compute_float64::(-2, 576460752303423744, false), (1076, 2)); assert_eq!(compute_float64::(-1, 144115188075855904, false), (1076, 1)); assert_eq!(compute_float64::(-1, 144115188075855920, false), (1076, 2)); assert_eq!(compute_float64::(-1, 144115188075855936, false), (1076, 2)); assert_eq!(compute_float64::(-1, 288230376151711808, false), (1076, 1)); assert_eq!(compute_float64::(-1, 288230376151711840, false), (1076, 2)); assert_eq!(compute_float64::(-1, 288230376151711872, false), (1076, 2)); } fn compute_float64_slow( integer: &[u8], fraction: Option<&[u8]>, exponent: i64, ) -> (i32, u64) { let num = Number { exponent, mantissa: 0, is_negative: false, many_digits: false, integer, fraction, }; let fp = slow_binary::(num); (fp.exp, fp.mant) } #[test] fn test_slow() { let i = b"100000000000000000000000000000000000000000000000000001"; let f = b"0000000000000"; assert_eq!(compute_float64_slow::(i, Some(f), -10), (1076, 0)); let i = b"100000000000000000000000000000000000000000000000000001"; let f = b"000000000000000000001"; assert_eq!(compute_float64_slow::(i, Some(f), -10), (1076, 1)); let i = b"100000000000000000000000000000000000000000000000000001"; let f = b"000000000000010000000"; assert_eq!(compute_float64_slow::(i, Some(f), -10), (1076, 1)); } lexical-parse-float-0.8.5/tests/float_tests.rs000064400000000000000000000111140072674642500175570ustar 00000000000000use lexical_parse_float::float::{self, RawFloat}; use lexical_parse_float::limits::ExactFloat; use lexical_util::num::Float; #[test] fn exponent_fast_path_test() { assert_eq!(f32::min_exponent_fast_path(10), -10); assert_eq!(f32::max_exponent_fast_path(10), 10); assert_eq!(f32::max_exponent_disguised_fast_path(10), 17); assert_eq!(f64::min_exponent_fast_path(10), -22); assert_eq!(f64::max_exponent_fast_path(10), 22); assert_eq!(f64::max_exponent_disguised_fast_path(10), 37); } fn slow_f32_power(exponent: usize, radix: u32) -> f32 { let mut value: f32 = 1.0; for _ in 0..exponent { value *= radix as f32; } value } fn slow_f64_power(exponent: usize, radix: u32) -> f64 { let mut value: f64 = 1.0; for _ in 0..exponent { value *= radix as f64; } value } fn pow_fast_path(radix: u32) { for exponent in 0..f32::exponent_limit(radix).1 + 1 { let exponent = exponent as usize; let actual = unsafe { f32::pow_fast_path(exponent, radix) }; assert_eq!(actual, slow_f32_power(exponent, radix)); } for exponent in 0..f64::exponent_limit(radix).1 + 1 { let exponent = exponent as usize; let actual = unsafe { f64::pow_fast_path(exponent, radix) }; assert_eq!(actual, slow_f64_power(exponent, radix)); } } #[test] #[cfg_attr(miri, ignore)] fn pow_fast_path_test() { pow_fast_path(10); if cfg!(feature = "power-of-two") { pow_fast_path(2); pow_fast_path(4); pow_fast_path(8); pow_fast_path(16); pow_fast_path(32); } if cfg!(feature = "radix") { pow_fast_path(3); pow_fast_path(5); pow_fast_path(6); pow_fast_path(7); pow_fast_path(9); pow_fast_path(11); pow_fast_path(12); pow_fast_path(13); pow_fast_path(14); pow_fast_path(15); pow_fast_path(17); pow_fast_path(18); pow_fast_path(19); pow_fast_path(20); pow_fast_path(21); pow_fast_path(22); pow_fast_path(23); pow_fast_path(24); pow_fast_path(25); pow_fast_path(26); pow_fast_path(27); pow_fast_path(28); pow_fast_path(29); pow_fast_path(30); pow_fast_path(31); pow_fast_path(33); pow_fast_path(34); pow_fast_path(35); pow_fast_path(36); } } fn slow_int_power(exponent: usize, radix: u32) -> u64 { let mut value: u64 = 1; for _ in 0..exponent { value *= radix as u64; } value } fn int_pow_fast_path(radix: u32) { for exponent in 0..f64::mantissa_limit(radix) { let exponent = exponent as usize; let actual = unsafe { f64::int_pow_fast_path(exponent, radix) }; assert_eq!(actual, slow_int_power(exponent, radix)); } } #[test] fn int_pow_fast_path_test() { int_pow_fast_path(10); if cfg!(feature = "power-of-two") { int_pow_fast_path(2); int_pow_fast_path(4); int_pow_fast_path(8); int_pow_fast_path(16); int_pow_fast_path(32); } if cfg!(feature = "radix") { int_pow_fast_path(3); int_pow_fast_path(5); int_pow_fast_path(6); int_pow_fast_path(7); int_pow_fast_path(9); int_pow_fast_path(11); int_pow_fast_path(12); int_pow_fast_path(13); int_pow_fast_path(14); int_pow_fast_path(15); int_pow_fast_path(17); int_pow_fast_path(18); int_pow_fast_path(19); int_pow_fast_path(20); int_pow_fast_path(21); int_pow_fast_path(22); int_pow_fast_path(23); int_pow_fast_path(24); int_pow_fast_path(25); int_pow_fast_path(26); int_pow_fast_path(27); int_pow_fast_path(28); int_pow_fast_path(29); int_pow_fast_path(30); int_pow_fast_path(31); int_pow_fast_path(33); int_pow_fast_path(34); int_pow_fast_path(35); int_pow_fast_path(36); } } fn extended_to_float(mantissa: u64, exponent: i32, expected: F) { let fp = float::ExtendedFloat80 { mant: mantissa, exp: exponent, }; assert_eq!(float::extended_to_float::(fp), expected); } #[test] fn extended_to_float_test() { let max_mant = (1 << f64::MANTISSA_SIZE) - 1; let max_exp = f64::INFINITE_POWER - 1; extended_to_float::(0, 0, 0.0); extended_to_float::(1, 0, 5e-324); extended_to_float::(max_mant, max_exp, f64::MAX); extended_to_float::(0, 1076, 9007199254740992.0); extended_to_float::(1, 1076, 9007199254740994.0); } lexical-parse-float-0.8.5/tests/lemire_tests.rs000064400000000000000000000310240072674642500177310ustar 00000000000000//! These tests are adapted from the Rust core library's unittests. #![cfg(not(feature = "compact"))] use lexical_parse_float::lemire; use lexical_parse_float::shared::INVALID_FP; fn compute_error32(q: i64, w: u64) -> (i32, u64) { let fp = lemire::compute_error::(q, w); (fp.exp, fp.mant) } fn compute_error64(q: i64, w: u64) -> (i32, u64) { let fp = lemire::compute_error::(q, w); (fp.exp, fp.mant) } fn compute_error_scaled32(q: i64, w: u64, lz: i32) -> (i32, u64) { let fp = lemire::compute_error_scaled::(q, w, lz); (fp.exp, fp.mant) } fn compute_error_scaled64(q: i64, w: u64, lz: i32) -> (i32, u64) { let fp = lemire::compute_error_scaled::(q, w, lz); (fp.exp, fp.mant) } fn compute_float32(q: i64, w: u64) -> (i32, u64) { let fp = lemire::compute_float::(q, w, false); (fp.exp, fp.mant) } fn compute_float64(q: i64, w: u64) -> (i32, u64) { let fp = lemire::compute_float::(q, w, false); (fp.exp, fp.mant) } #[test] fn compute_error32_test() { // These test near-halfway cases for single-precision floats. assert_eq!(compute_error32(0, 16777216), (111 + INVALID_FP, 9223372036854775808)); assert_eq!(compute_error32(0, 16777217), (111 + INVALID_FP, 9223372586610589696)); assert_eq!(compute_error32(0, 16777218), (111 + INVALID_FP, 9223373136366403584)); assert_eq!(compute_error32(0, 16777219), (111 + INVALID_FP, 9223373686122217472)); assert_eq!(compute_error32(0, 16777220), (111 + INVALID_FP, 9223374235878031360)); // These are examples of the above tests, with // digits from the exponent shifted to the mantissa. assert_eq!(compute_error32(-10, 167772160000000000), (111 + INVALID_FP, 9223372036854775808)); assert_eq!(compute_error32(-10, 167772170000000000), (111 + INVALID_FP, 9223372586610589696)); assert_eq!(compute_error32(-10, 167772180000000000), (111 + INVALID_FP, 9223373136366403584)); // Let's check the lines to see if anything is different in table... assert_eq!(compute_error32(-10, 167772190000000000), (111 + INVALID_FP, 9223373686122217472)); assert_eq!(compute_error32(-10, 167772200000000000), (111 + INVALID_FP, 9223374235878031360)); } #[test] fn compute_error64_test() { // These test near-halfway cases for double-precision floats. assert_eq!(compute_error64(0, 9007199254740992), (1065 + INVALID_FP, 9223372036854775808)); assert_eq!(compute_error64(0, 9007199254740993), (1065 + INVALID_FP, 9223372036854776832)); assert_eq!(compute_error64(0, 9007199254740994), (1065 + INVALID_FP, 9223372036854777856)); assert_eq!(compute_error64(0, 9007199254740995), (1065 + INVALID_FP, 9223372036854778880)); assert_eq!(compute_error64(0, 9007199254740996), (1065 + INVALID_FP, 9223372036854779904)); assert_eq!(compute_error64(0, 18014398509481984), (1066 + INVALID_FP, 9223372036854775808)); assert_eq!(compute_error64(0, 18014398509481986), (1066 + INVALID_FP, 9223372036854776832)); assert_eq!(compute_error64(0, 18014398509481988), (1066 + INVALID_FP, 9223372036854777856)); assert_eq!(compute_error64(0, 18014398509481990), (1066 + INVALID_FP, 9223372036854778880)); assert_eq!(compute_error64(0, 18014398509481992), (1066 + INVALID_FP, 9223372036854779904)); // Test a much closer set of examples. assert_eq!(compute_error64(0, 9007199254740991), (1064 + INVALID_FP, 18446744073709549568)); assert_eq!(compute_error64(0, 9223372036854776831), (1075 + INVALID_FP, 9223372036854776830)); assert_eq!(compute_error64(0, 9223372036854776832), (1075 + INVALID_FP, 9223372036854776832)); assert_eq!(compute_error64(0, 9223372036854776833), (1075 + INVALID_FP, 9223372036854776832)); assert_eq!(compute_error64(-42, 9123456727292927), (925 + INVALID_FP, 13021432563531497894)); assert_eq!(compute_error64(-43, 91234567272929275), (925 + INVALID_FP, 13021432563531498606)); assert_eq!(compute_error64(-42, 9123456727292928), (925 + INVALID_FP, 13021432563531499320)); // These are examples of the above tests, with // digits from the exponent shifted to the mantissa. assert_eq!(compute_error64(-3, 9007199254740992000), (1065 + INVALID_FP, 9223372036854775808)); assert_eq!(compute_error64(-3, 9007199254740993000), (1065 + INVALID_FP, 9223372036854776832)); assert_eq!(compute_error64(-3, 9007199254740994000), (1065 + INVALID_FP, 9223372036854777856)); assert_eq!(compute_error64(-3, 9007199254740995000), (1065 + INVALID_FP, 9223372036854778880)); assert_eq!(compute_error64(-3, 9007199254740996000), (1065 + INVALID_FP, 9223372036854779904)); // Test from errors in atof. assert_eq!(compute_error64(-18, 1000000178813934326), (1012 + INVALID_FP, 9223373686122217470)); // Check edge-cases from previous errors. assert_eq!( compute_error64(-342, 2470328229206232720), (-64 + INVALID_FP, 18446744073709551608) ); } #[test] fn compute_error_scaled32_test() { // These are the same examples above, just using pre-computed scaled values. // These test near-halfway cases for single-precision floats. assert_eq!( compute_error_scaled32(0, 4611686018427387904, 39), (111 + INVALID_FP, 9223372036854775808) ); assert_eq!( compute_error_scaled32(0, 4611686293305294848, 39), (111 + INVALID_FP, 9223372586610589696) ); assert_eq!( compute_error_scaled32(0, 4611686568183201792, 39), (111 + INVALID_FP, 9223373136366403584) ); assert_eq!( compute_error_scaled32(0, 4611686843061108736, 39), (111 + INVALID_FP, 9223373686122217472) ); assert_eq!( compute_error_scaled32(0, 4611687117939015680, 39), (111 + INVALID_FP, 9223374235878031360) ); assert_eq!( compute_error_scaled32(-10, 9223372036854775808, 6), (111 + INVALID_FP, 9223372036854775808) ); assert_eq!( compute_error_scaled32(-10, 9223372586610589696, 6), (111 + INVALID_FP, 9223372586610589696) ); assert_eq!( compute_error_scaled32(-10, 9223373136366403584, 6), (111 + INVALID_FP, 9223373136366403584) ); assert_eq!( compute_error_scaled32(-10, 9223373686122217472, 6), (111 + INVALID_FP, 9223373686122217472) ); assert_eq!( compute_error_scaled32(-10, 9223374235878031360, 6), (111 + INVALID_FP, 9223374235878031360) ); } #[test] fn compute_error_scaled64_test() { // These are the same examples above, just using pre-computed scaled values. // These test near-halfway cases for double-precision floats. assert_eq!( compute_error_scaled64(0, 4611686018427387904, 10), (1065 + INVALID_FP, 9223372036854775808) ); assert_eq!( compute_error_scaled64(0, 4611686018427388416, 10), (1065 + INVALID_FP, 9223372036854776832) ); assert_eq!( compute_error_scaled64(0, 4611686018427388928, 10), (1065 + INVALID_FP, 9223372036854777856) ); assert_eq!( compute_error_scaled64(0, 4611686018427389440, 10), (1065 + INVALID_FP, 9223372036854778880) ); assert_eq!( compute_error_scaled64(0, 4611686018427389952, 10), (1065 + INVALID_FP, 9223372036854779904) ); assert_eq!( compute_error_scaled64(0, 4611686018427387904, 9), (1066 + INVALID_FP, 9223372036854775808) ); assert_eq!( compute_error_scaled64(0, 4611686018427388416, 9), (1066 + INVALID_FP, 9223372036854776832) ); assert_eq!( compute_error_scaled64(0, 4611686018427388928, 9), (1066 + INVALID_FP, 9223372036854777856) ); assert_eq!( compute_error_scaled64(0, 4611686018427389440, 9), (1066 + INVALID_FP, 9223372036854778880) ); assert_eq!( compute_error_scaled64(0, 4611686018427389952, 9), (1066 + INVALID_FP, 9223372036854779904) ); // Test a much closer set of examples. assert_eq!( compute_error_scaled64(0, 9223372036854774784, 11), (1064 + INVALID_FP, 18446744073709549568) ); assert_eq!( compute_error_scaled64(0, 4611686018427388415, 0), (1075 + INVALID_FP, 9223372036854776830) ); assert_eq!( compute_error_scaled64(0, 4611686018427388416, 0), (1075 + INVALID_FP, 9223372036854776832) ); assert_eq!( compute_error_scaled64(0, 4611686018427388416, 0), (1075 + INVALID_FP, 9223372036854776832) ); assert_eq!( compute_error_scaled64(-42, 6510716281765748947, 10), (925 + INVALID_FP, 13021432563531497894) ); assert_eq!( compute_error_scaled64(-43, 6510716281765749303, 7), (925 + INVALID_FP, 13021432563531498606) ); assert_eq!( compute_error_scaled64(-42, 6510716281765749660, 10), (925 + INVALID_FP, 13021432563531499320) ); // These are examples of the above tests, with // digits from the exponent shifted to the mantissa. assert_eq!( compute_error_scaled64(-3, 9223372036854775808, 1), (1065 + INVALID_FP, 9223372036854775808) ); assert_eq!( compute_error_scaled64(-3, 9223372036854776832, 1), (1065 + INVALID_FP, 9223372036854776832) ); assert_eq!( compute_error_scaled64(-3, 9223372036854777856, 1), (1065 + INVALID_FP, 9223372036854777856) ); assert_eq!( compute_error_scaled64(-3, 9223372036854778880, 1), (1065 + INVALID_FP, 9223372036854778880) ); assert_eq!( compute_error_scaled64(-3, 9223372036854779904, 1), (1065 + INVALID_FP, 9223372036854779904) ); // Test from errors in atof. assert_eq!( compute_error_scaled64(-18, 9223373686122217470, 4), (1012 + INVALID_FP, 9223373686122217470) ); // Check edge-cases from previous errors. assert_eq!( compute_error_scaled64(-342, 9223372036854775804, 2), (-64 + INVALID_FP, 18446744073709551608) ); } #[test] fn compute_float_f32_rounding() { // These test near-halfway cases for single-precision floats. assert_eq!(compute_float32(0, 16777216), (151, 0)); assert_eq!(compute_float32(0, 16777217), (151, 0)); assert_eq!(compute_float32(0, 16777218), (151, 1)); assert_eq!(compute_float32(0, 16777219), (151, 2)); assert_eq!(compute_float32(0, 16777220), (151, 2)); // These are examples of the above tests, with // digits from the exponent shifted to the mantissa. assert_eq!(compute_float32(-10, 167772160000000000), (151, 0)); assert_eq!(compute_float32(-10, 167772170000000000), (151, 0)); assert_eq!(compute_float32(-10, 167772180000000000), (151, 1)); // Let's check the lines to see if anything is different in table... assert_eq!(compute_float32(-10, 167772190000000000), (151, 2)); assert_eq!(compute_float32(-10, 167772200000000000), (151, 2)); } #[test] fn compute_float_f64_rounding() { // Also need to check halfway cases **inside** that exponent range. // These test near-halfway cases for double-precision floats. assert_eq!(compute_float64(0, 9007199254740992), (1076, 0)); assert_eq!(compute_float64(0, 9007199254740993), (1076, 0)); assert_eq!(compute_float64(0, 9007199254740994), (1076, 1)); assert_eq!(compute_float64(0, 9007199254740995), (1076, 2)); assert_eq!(compute_float64(0, 9007199254740996), (1076, 2)); assert_eq!(compute_float64(0, 18014398509481984), (1077, 0)); assert_eq!(compute_float64(0, 18014398509481986), (1077, 0)); assert_eq!(compute_float64(0, 18014398509481988), (1077, 1)); assert_eq!(compute_float64(0, 18014398509481990), (1077, 2)); assert_eq!(compute_float64(0, 18014398509481992), (1077, 2)); // Test a much closer set of examples. assert_eq!(compute_float64(0, 9007199254740991), (1075, 4503599627370495)); assert_eq!(compute_float64(0, 9223372036854776831), (1086, 0)); assert_eq!(compute_float64(0, 9223372036854776832), (1086, 0)); assert_eq!(compute_float64(0, 9223372036854776833), (1086, 1)); assert_eq!(compute_float64(-42, 9123456727292927), (936, 1854521741541368)); assert_eq!(compute_float64(-43, 91234567272929275), (936, 1854521741541369)); assert_eq!(compute_float64(-42, 9123456727292928), (936, 1854521741541369)); // These are examples of the above tests, with // digits from the exponent shifted to the mantissa. assert_eq!(compute_float64(-3, 9007199254740992000), (1076, 0)); assert_eq!(compute_float64(-3, 9007199254740993000), (1076, 0)); assert_eq!(compute_float64(-3, 9007199254740994000), (1076, 1)); assert_eq!(compute_float64(-3, 9007199254740995000), (1076, 2)); assert_eq!(compute_float64(-3, 9007199254740996000), (1076, 2)); } lexical-parse-float-0.8.5/tests/libm_tests.rs000064400000000000000000000222700072674642500174020ustar 00000000000000#![cfg(all(not(feature = "std"), feature = "compact"))] // These are adapted from libm, a port of musl libc's libm to Rust. // libm can be found online [here](https://github.com/rust-lang/libm), // and is similarly licensed under an Apache2.0/MIT license use core::f64; use lexical_parse_float::libm; #[test] fn fabsf_sanity_test() { assert_eq!(libm::fabsf(-1.0), 1.0); assert_eq!(libm::fabsf(2.8), 2.8); } /// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs #[test] fn fabsf_spec_test() { assert!(libm::fabsf(f32::NAN).is_nan()); for f in [0.0, -0.0].iter().copied() { assert_eq!(libm::fabsf(f), 0.0); } for f in [f32::INFINITY, f32::NEG_INFINITY].iter().copied() { assert_eq!(libm::fabsf(f), f32::INFINITY); } } #[test] fn sqrtf_sanity_test() { assert_eq!(libm::sqrtf(100.0), 10.0); assert_eq!(libm::sqrtf(4.0), 2.0); } /// The spec: https://en.cppreference.com/w/cpp/numeric/math/sqrt #[test] fn sqrtf_spec_test() { // Not Asserted: FE_INVALID exception is raised if argument is negative. assert!(libm::sqrtf(-1.0).is_nan()); assert!(libm::sqrtf(f32::NAN).is_nan()); for f in [0.0, -0.0, f32::INFINITY].iter().copied() { assert_eq!(libm::sqrtf(f), f); } } const POS_ZERO: &[f64] = &[0.0]; const NEG_ZERO: &[f64] = &[-0.0]; const POS_ONE: &[f64] = &[1.0]; const NEG_ONE: &[f64] = &[-1.0]; const POS_FLOATS: &[f64] = &[99.0 / 70.0, f64::consts::E, f64::consts::PI]; const NEG_FLOATS: &[f64] = &[-99.0 / 70.0, -f64::consts::E, -f64::consts::PI]; const POS_SMALL_FLOATS: &[f64] = &[(1.0 / 2.0), f64::MIN_POSITIVE, f64::EPSILON]; const NEG_SMALL_FLOATS: &[f64] = &[-(1.0 / 2.0), -f64::MIN_POSITIVE, -f64::EPSILON]; const POS_EVENS: &[f64] = &[2.0, 6.0, 8.0, 10.0, 22.0, 100.0, f64::MAX]; const NEG_EVENS: &[f64] = &[f64::MIN, -100.0, -22.0, -10.0, -8.0, -6.0, -2.0]; const POS_ODDS: &[f64] = &[3.0, 7.0]; const NEG_ODDS: &[f64] = &[-7.0, -3.0]; const NANS: &[f64] = &[f64::NAN]; const POS_INF: &[f64] = &[f64::INFINITY]; const NEG_INF: &[f64] = &[f64::NEG_INFINITY]; const ALL: &[&[f64]] = &[ POS_ZERO, NEG_ZERO, NANS, NEG_SMALL_FLOATS, POS_SMALL_FLOATS, NEG_FLOATS, POS_FLOATS, NEG_EVENS, POS_EVENS, NEG_ODDS, POS_ODDS, NEG_INF, POS_INF, NEG_ONE, POS_ONE, ]; const POS: &[&[f64]] = &[POS_ZERO, POS_ODDS, POS_ONE, POS_FLOATS, POS_EVENS, POS_INF]; const NEG: &[&[f64]] = &[NEG_ZERO, NEG_ODDS, NEG_ONE, NEG_FLOATS, NEG_EVENS, NEG_INF]; fn powd(base: f64, exponent: f64, expected: f64) { let res = libm::powd(base, exponent); assert!( if expected.is_nan() { res.is_nan() } else { libm::powd(base, exponent) == expected }, "{} ** {} was {} instead of {}", base, exponent, res, expected ); } fn powd_test_sets_as_base(sets: &[&[f64]], exponent: f64, expected: f64) { sets.iter().for_each(|s| s.iter().for_each(|val| powd(*val, exponent, expected))); } fn powd_test_sets_as_exponent(base: f64, sets: &[&[f64]], expected: f64) { sets.iter().for_each(|s| s.iter().for_each(|val| powd(base, *val, expected))); } fn powd_test_sets(sets: &[&[f64]], computed: &dyn Fn(f64) -> f64, expected: &dyn Fn(f64) -> f64) { sets.iter().for_each(|s| { s.iter().for_each(|val| { let exp = expected(*val); let res = computed(*val); assert!( if exp.is_nan() { res.is_nan() } else { exp == res }, "test for {} was {} instead of {}", val, res, exp ); }) }); } #[test] fn powd_zero_as_exponent() { powd_test_sets_as_base(ALL, 0.0, 1.0); powd_test_sets_as_base(ALL, -0.0, 1.0); } #[test] fn powd_one_as_base() { powd_test_sets_as_exponent(1.0, ALL, 1.0); } #[test] fn powd_nan_inputs() { // NAN as the base: // (NAN ^ anything *but 0* should be NAN) powd_test_sets_as_exponent(f64::NAN, &ALL[2..], f64::NAN); // NAN as the exponent: // (anything *but 1* ^ NAN should be NAN) powd_test_sets_as_base(&ALL[..(ALL.len() - 2)], f64::NAN, f64::NAN); } #[test] fn powd_infinity_as_base() { // Positive Infinity as the base: // (+Infinity ^ positive anything but 0 and NAN should be +Infinity) powd_test_sets_as_exponent(f64::INFINITY, &POS[1..], f64::INFINITY); // (+Infinity ^ negative anything except 0 and NAN should be 0.0) powd_test_sets_as_exponent(f64::INFINITY, &NEG[1..], 0.0); // Negative Infinity as the base: // (-Infinity ^ positive odd ints should be -Infinity) powd_test_sets_as_exponent(f64::NEG_INFINITY, &[POS_ODDS], f64::NEG_INFINITY); // (-Infinity ^ anything but odd ints should be == -0 ^ (-anything)) // We can lump in pos/neg odd ints here because they don't seem to // cause panics (div by zero) in release mode (I think). powd_test_sets(ALL, &|v: f64| libm::powd(f64::NEG_INFINITY, v), &|v: f64| libm::powd(-0.0, -v)); } #[test] fn infinity_as_exponent() { // Positive/Negative base greater than 1: // (pos/neg > 1 ^ Infinity should be Infinity - note this excludes NAN as the base) powd_test_sets_as_base(&ALL[5..(ALL.len() - 2)], f64::INFINITY, f64::INFINITY); // (pos/neg > 1 ^ -Infinity should be 0.0) powd_test_sets_as_base(&ALL[5..ALL.len() - 2], f64::NEG_INFINITY, 0.0); // Positive/Negative base less than 1: let base_below_one = &[POS_ZERO, NEG_ZERO, NEG_SMALL_FLOATS, POS_SMALL_FLOATS]; // (pos/neg < 1 ^ Infinity should be 0.0 - this also excludes NAN as the base) powd_test_sets_as_base(base_below_one, f64::INFINITY, 0.0); // (pos/neg < 1 ^ -Infinity should be Infinity) powd_test_sets_as_base(base_below_one, f64::NEG_INFINITY, f64::INFINITY); // Positive/Negative 1 as the base: // (pos/neg 1 ^ Infinity should be 1) powd_test_sets_as_base(&[NEG_ONE, POS_ONE], f64::INFINITY, 1.0); // (pos/neg 1 ^ -Infinity should be 1) powd_test_sets_as_base(&[NEG_ONE, POS_ONE], f64::NEG_INFINITY, 1.0); } #[test] fn powd_zero_as_base() { // Positive Zero as the base: // (+0 ^ anything positive but 0 and NAN should be +0) powd_test_sets_as_exponent(0.0, &POS[1..], 0.0); // (+0 ^ anything negative but 0 and NAN should be Infinity) // (this should panic because we're dividing by zero) powd_test_sets_as_exponent(0.0, &NEG[1..], f64::INFINITY); // Negative Zero as the base: // (-0 ^ anything positive but 0, NAN, and odd ints should be +0) powd_test_sets_as_exponent(-0.0, &POS[3..], 0.0); // (-0 ^ anything negative but 0, NAN, and odd ints should be Infinity) // (should panic because of divide by zero) powd_test_sets_as_exponent(-0.0, &NEG[3..], f64::INFINITY); // (-0 ^ positive odd ints should be -0) powd_test_sets_as_exponent(-0.0, &[POS_ODDS], -0.0); // (-0 ^ negative odd ints should be -Infinity) // (should panic because of divide by zero) powd_test_sets_as_exponent(-0.0, &[NEG_ODDS], f64::NEG_INFINITY); } #[test] fn special_cases() { // One as the exponent: // (anything ^ 1 should be anything - i.e. the base) powd_test_sets(ALL, &|v: f64| libm::powd(v, 1.0), &|v: f64| v); // Negative One as the exponent: // (anything ^ -1 should be 1/anything) powd_test_sets(ALL, &|v: f64| libm::powd(v, -1.0), &|v: f64| 1.0 / v); // Factoring -1 out: // (negative anything ^ integer should be (-1 ^ integer) * (positive anything ^ integer)) [POS_ZERO, NEG_ZERO, POS_ONE, NEG_ONE, POS_EVENS, NEG_EVENS].iter().for_each(|int_set| { int_set.iter().for_each(|int| { powd_test_sets(ALL, &|v: f64| libm::powd(-v, *int), &|v: f64| { libm::powd(-1.0, *int) * libm::powd(v, *int) }); }) }); // Negative base (imaginary results): // (-anything except 0 and Infinity ^ non-integer should be NAN) NEG[1..(NEG.len() - 1)].iter().for_each(|set| { set.iter().for_each(|val| { powd_test_sets(&ALL[3..7], &|v: f64| libm::powd(*val, v), &|_| f64::NAN); }) }); } #[test] fn normal_cases() { assert_eq!(libm::powd(2.0, 20.0), (1 << 20) as f64); assert_eq!(libm::powd(-1.0, 9.0), -1.0); assert!(libm::powd(-1.0, 2.2).is_nan()); assert!(libm::powd(-1.0, -1.14).is_nan()); } #[test] fn fabsd_sanity_test() { assert_eq!(libm::fabsd(-1.0), 1.0); assert_eq!(libm::fabsd(2.8), 2.8); } /// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs #[test] fn fabsd_spec_test() { assert!(libm::fabsd(f64::NAN).is_nan()); for f in [0.0, -0.0].iter().copied() { assert_eq!(libm::fabsd(f), 0.0); } for f in [f64::INFINITY, f64::NEG_INFINITY].iter().copied() { assert_eq!(libm::fabsd(f), f64::INFINITY); } } #[test] fn sqrtd_sanity_test() { assert_eq!(libm::sqrtd(100.0), 10.0); assert_eq!(libm::sqrtd(4.0), 2.0); } /// The spec: https://en.cppreference.com/w/cpp/numeric/math/sqrt #[test] fn sqrtd_spec_test() { // Not Asserted: FE_INVALID exception is raised if argument is negative. assert!(libm::sqrtd(-1.0).is_nan()); assert!(libm::sqrtd(f64::NAN).is_nan()); for f in [0.0, -0.0, f64::INFINITY].iter().copied() { assert_eq!(libm::sqrtd(f), f); } } lexical-parse-float-0.8.5/tests/limits_tests.rs000064400000000000000000000012620072674642500177560ustar 00000000000000use lexical_parse_float::limits::{self, ExactFloat, MaxDigits}; #[test] fn mantissa_limit_test() { assert_eq!(f32::mantissa_limit(10), 7); assert_eq!(f64::mantissa_limit(10), 15); } #[test] fn exponent_limit_test() { assert_eq!(f32::exponent_limit(10), (-10, 10)); assert_eq!(f64::exponent_limit(10), (-22, 22)); } #[test] fn power_limit_test() { assert_eq!(limits::u32_power_limit(5), 13); assert_eq!(limits::u32_power_limit(10), 9); assert_eq!(limits::u64_power_limit(5), 27); assert_eq!(limits::u64_power_limit(10), 19); } #[test] fn max_digit_test() { assert_eq!(f32::max_digits(10), Some(114)); assert_eq!(f64::max_digits(10), Some(769)); } lexical-parse-float-0.8.5/tests/mask_tests.rs000064400000000000000000000004170072674642500174110ustar 00000000000000use lexical_parse_float::mask; #[test] fn lower_n_mask_test() { assert_eq!(mask::lower_n_mask(2), 0b11); } #[test] fn lower_n_halfway_test() { assert_eq!(mask::lower_n_halfway(2), 0b10); } #[test] fn nth_bit_test() { assert_eq!(mask::nth_bit(2), 0b100); } lexical-parse-float-0.8.5/tests/number_tests.rs000064400000000000000000000066570072674642500177620ustar 00000000000000use lexical_parse_float::number::Number; use lexical_util::format::STANDARD; #[test] fn is_fast_path_test() { let mut number = Number { exponent: -4, mantissa: 12345, is_negative: false, many_digits: false, integer: &[], fraction: None, }; assert_eq!(number.is_fast_path::(), true); assert_eq!(number.is_fast_path::(), true); number.exponent = -15; assert_eq!(number.is_fast_path::(), false); assert_eq!(number.is_fast_path::(), true); number.exponent = -25; assert_eq!(number.is_fast_path::(), false); assert_eq!(number.is_fast_path::(), false); number.exponent = 25; assert_eq!(number.is_fast_path::(), false); assert_eq!(number.is_fast_path::(), true); number.exponent = 36; assert_eq!(number.is_fast_path::(), false); assert_eq!(number.is_fast_path::(), true); number.exponent = 38; assert_eq!(number.is_fast_path::(), false); assert_eq!(number.is_fast_path::(), false); number.mantissa = 1 << 25; number.exponent = 0; assert_eq!(number.is_fast_path::(), false); assert_eq!(number.is_fast_path::(), true); number.mantissa = 1 << 54; assert_eq!(number.is_fast_path::(), false); assert_eq!(number.is_fast_path::(), false); number.mantissa = 1 << 52; assert_eq!(number.is_fast_path::(), false); assert_eq!(number.is_fast_path::(), true); number.many_digits = true; assert_eq!(number.is_fast_path::(), false); assert_eq!(number.is_fast_path::(), false); } #[test] fn try_fast_path_test() { let mut number = Number { exponent: -4, mantissa: 12345, is_negative: false, many_digits: false, integer: &[], fraction: None, }; assert_eq!(number.try_fast_path::(), Some(1.2345)); assert_eq!(number.try_fast_path::(), Some(1.2345)); number.exponent = -10; assert_eq!(number.try_fast_path::(), Some(1.2345e-6)); assert_eq!(number.try_fast_path::(), Some(1.2345e-6)); number.exponent = -20; assert_eq!(number.try_fast_path::(), None); assert_eq!(number.try_fast_path::(), Some(1.2345e-16)); number.exponent = -25; assert_eq!(number.try_fast_path::(), None); assert_eq!(number.try_fast_path::(), None); number.exponent = 12; assert_eq!(number.try_fast_path::(), Some(1.2345e16)); assert_eq!(number.try_fast_path::(), Some(1.2345e16)); number.exponent = 25; assert_eq!(number.try_fast_path::(), None); assert_eq!(number.try_fast_path::(), Some(1.2345e29)); number.exponent = 32; assert_eq!(number.try_fast_path::(), None); assert_eq!(number.try_fast_path::(), Some(1.2345e36)); number.exponent = 36; assert_eq!(number.try_fast_path::(), None); assert_eq!(number.try_fast_path::(), None); } lexical-parse-float-0.8.5/tests/options_tests.rs000064400000000000000000000112200072674642500201430ustar 00000000000000use lexical_parse_float::options::{Options, OptionsBuilder}; #[test] fn invalid_exponent_test() { let mut builder = OptionsBuilder::default(); builder = builder.exponent(b'\x00'); assert!(!builder.is_valid()); builder = builder.exponent(b'\x7f'); assert!(!builder.is_valid()); assert!(builder.build().is_err()); builder = builder.exponent(b'^'); assert!(builder.is_valid()); assert!(builder.build().is_ok()); } #[test] fn invalid_decimal_point_test() { let mut builder = OptionsBuilder::default(); builder = builder.decimal_point(b'\x00'); assert!(!builder.is_valid()); builder = builder.decimal_point(b'\x7f'); assert!(!builder.is_valid()); assert!(builder.build().is_err()); builder = builder.decimal_point(b','); assert!(builder.is_valid()); assert!(builder.build().is_ok()); } #[test] fn invalid_nan_test() { let mut builder = OptionsBuilder::default(); builder = builder.nan_string(Some(b"naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaan")); assert!(!builder.is_valid()); builder = builder.nan_string(Some(b"inf")); assert!(!builder.is_valid()); builder = builder.nan_string(Some(b"na00n")); assert!(!builder.is_valid()); assert!(builder.build().is_err()); builder = builder.nan_string(Some(b"nan")); assert!(builder.is_valid()); assert!(builder.build().is_ok()); builder = builder.nan_string(None); assert!(builder.is_valid()); } #[test] fn invalid_inf_test() { let mut builder = OptionsBuilder::default(); builder = builder.inf_string(Some(b"innnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnf")); assert!(!builder.is_valid()); builder = builder.inf_string(Some(b"nan")); assert!(!builder.is_valid()); builder = builder.inf_string(Some(b"in00f")); assert!(!builder.is_valid()); assert!(builder.build().is_err()); builder = builder.inf_string(Some(b"i")); assert!(builder.is_valid()); builder = builder.inf_string(Some(b"inf")); assert!(builder.is_valid()); assert!(builder.build().is_ok()); builder = builder.inf_string(None); assert!(builder.is_valid()); builder = builder.infinity_string(None); assert!(builder.is_valid()); } #[test] fn invalid_infinity_test() { let mut builder = OptionsBuilder::default(); builder = builder.infinity_string(Some(b"innnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnf")); assert!(!builder.is_valid()); builder = builder.infinity_string(Some(b"nan")); assert!(!builder.is_valid()); builder = builder.infinity_string(Some(b"i")); assert!(!builder.is_valid()); builder = builder.inf_string(Some(b"infi000nity")); assert!(!builder.is_valid()); assert!(builder.build().is_err()); builder = builder.inf_string(Some(b"i")); assert!(builder.is_valid()); builder = builder.infinity_string(Some(b"infinity")); assert!(builder.is_valid()); assert!(builder.build().is_ok()); builder = builder.infinity_string(None); assert!(!builder.is_valid()); builder = builder.inf_string(None); assert!(builder.is_valid()); } #[test] fn builder_test() { let mut builder = OptionsBuilder::default(); builder = builder.lossy(true); builder = builder.exponent(b'^'); builder = builder.decimal_point(b','); builder = builder.nan_string(Some(b"nan")); builder = builder.inf_string(Some(b"Infinity")); builder = builder.infinity_string(Some(b"Infiniiiiiity")); assert_eq!(builder.get_lossy(), true); assert_eq!(builder.get_exponent(), b'^'); assert_eq!(builder.get_decimal_point(), b','); assert_eq!(builder.get_nan_string(), Some("nan".as_bytes())); assert_eq!(builder.get_inf_string(), Some("Infinity".as_bytes())); assert_eq!(builder.get_infinity_string(), Some("Infiniiiiiity".as_bytes())); assert!(builder.is_valid()); assert_eq!(builder.build(), Ok(unsafe { builder.build_unchecked() })); } #[test] fn options_test() { let mut opts = Options::new(); unsafe { opts.set_lossy(true); opts.set_exponent(b'^'); opts.set_decimal_point(b','); opts.set_nan_string(Some(b"nan")); opts.set_inf_string(Some(b"Infinity")); opts.set_infinity_string(Some(b"Infiniiiiiity")); } assert_eq!(opts.lossy(), true); assert_eq!(opts.exponent(), b'^'); assert_eq!(opts.decimal_point(), b','); assert_eq!(opts.nan_string(), Some("nan".as_bytes())); assert_eq!(opts.inf_string(), Some("Infinity".as_bytes())); assert_eq!(opts.infinity_string(), Some("Infiniiiiiity".as_bytes())); assert!(opts.is_valid()); assert_eq!(Options::builder(), OptionsBuilder::new()); assert_eq!(opts.rebuild().build(), Ok(opts)); } lexical-parse-float-0.8.5/tests/parse_tests.rs000064400000000000000000000207230072674642500175720ustar 00000000000000use lexical_parse_float::options::Options; use lexical_parse_float::parse; use lexical_util::format::STANDARD; use lexical_util::iterator::AsBytes; use lexical_util::step::u64_step; #[test] fn parse_complete_test() { const FORMAT: u128 = STANDARD; let options = Options::new(); let string = b"1.2345e10"; let result = parse::parse_complete::(string, &options); assert_eq!(result, Ok(1.2345e10)); let string = b"1.2345e"; let result = parse::parse_complete::(string, &options); assert!(result.is_err()); let string = b"1.2345 "; let result = parse::parse_complete::(string, &options); assert!(result.is_err()); } #[test] fn fast_path_complete_test() { const FORMAT: u128 = STANDARD; let options = Options::new(); let string = b"1.2345e10"; let result = parse::fast_path_complete::(string, &options); assert_eq!(result, Ok(1.2345e10)); let string = b"1.2345e"; let result = parse::fast_path_complete::(string, &options); assert!(result.is_err()); let string = b"1.2345 "; let result = parse::fast_path_complete::(string, &options); assert!(result.is_err()); } #[test] fn parse_partial_test() { const FORMAT: u128 = STANDARD; let options = Options::new(); let string = b"1.2345e10"; let result = parse::parse_partial::(string, &options); assert_eq!(result, Ok((1.2345e10, 9))); let string = b"1.2345e"; let result = parse::parse_partial::(string, &options); assert!(result.is_err()); let string = b"1.2345 "; let result = parse::parse_partial::(string, &options); assert_eq!(result, Ok((1.2345, 6))); } #[test] fn fast_path_partial_test() { const FORMAT: u128 = STANDARD; let options = Options::new(); let string = b"1.2345e10"; let result = parse::fast_path_partial::(string, &options); assert_eq!(result, Ok((1.2345e10, 9))); let string = b"1.2345e"; let result = parse::fast_path_partial::(string, &options); assert!(result.is_err()); let string = b"1.2345 "; let result = parse::fast_path_partial::(string, &options); assert_eq!(result, Ok((1.2345, 6))); } #[test] fn parse_number_test() { const FORMAT: u128 = STANDARD; let options = Options::new(); let string = b"1.2345e10"; let byte = string.bytes::<{ FORMAT }>(); let result = parse::parse_number(byte, false, &options); assert!(result.is_ok()); let num = result.unwrap(); assert_eq!(num.mantissa, 12345); assert_eq!(num.exponent, 6); assert_eq!(num.many_digits, false); let string = b"1.2345e"; let byte = string.bytes::<{ FORMAT }>(); let result = parse::parse_number(byte, false, &options); assert!(result.is_err()); let string = b"1.2345 "; let byte = string.bytes::<{ FORMAT }>(); let result = parse::parse_number(byte, false, &options); assert!(result.is_err()); } #[test] fn parse_partial_number_test() { const FORMAT: u128 = STANDARD; let options = Options::new(); let string = b"1.2345e10"; let byte = string.bytes::<{ FORMAT }>(); let result = parse::parse_partial_number(byte, false, &options); assert!(result.is_ok()); let (num, count) = result.unwrap(); assert_eq!(num.mantissa, 12345); assert_eq!(num.exponent, 6); assert_eq!(num.many_digits, false); assert_eq!(count, 9); let string = b"1.2345e"; let byte = string.bytes::<{ FORMAT }>(); let result = parse::parse_partial_number(byte, false, &options); assert!(result.is_err()); let string = b"1.2345 "; let byte = string.bytes::<{ FORMAT }>(); let result = parse::parse_partial_number(byte, false, &options); assert!(result.is_ok()); let (num, count) = result.unwrap(); assert_eq!(num.mantissa, 12345); assert_eq!(num.exponent, -4); assert_eq!(num.many_digits, false); assert_eq!(count, 6); // Leading zeros let string = b"00000000000000000000001.2345 "; let byte = string.bytes::<{ FORMAT }>(); let result = parse::parse_partial_number(byte, false, &options); assert!(result.is_ok()); let (num, count) = result.unwrap(); assert_eq!(num.mantissa, 12345); assert_eq!(num.exponent, -4); assert_eq!(num.many_digits, false); assert_eq!(count, 28); // Leading zeros let string = b"0.00000000000000000000012345 "; let byte = string.bytes::<{ FORMAT }>(); let result = parse::parse_partial_number(byte, false, &options); assert!(result.is_ok()); let (num, count) = result.unwrap(); assert_eq!(num.mantissa, 12345); assert_eq!(num.exponent, -26); assert_eq!(num.many_digits, false); assert_eq!(count, 28); } #[test] fn parse_digits_test() { const FORMAT: u128 = STANDARD; let mut mantissa: u64 = 0; let digits = b"1234567890123456789012345"; let mut byte = digits.bytes::<{ FORMAT }>(); parse::parse_digits::<_, _, FORMAT>(byte.integer_iter(), |digit| { mantissa = mantissa.wrapping_mul(10).wrapping_add(digit as _); }); assert_eq!(mantissa, 1096246371337559929); } #[test] #[cfg(not(feature = "compact"))] fn parse_8digits_test() { const FORMAT: u128 = STANDARD; let mut mantissa: u64 = 0; let digits = b"1234567890123456789012345"; let mut byte = digits.bytes::<{ FORMAT }>(); parse::parse_8digits::<_, FORMAT>(byte.integer_iter(), &mut mantissa); // We don't check for overflow. assert_eq!(mantissa, 11177671081359486962); } #[test] fn parse_u64_digits_test() { const FORMAT: u128 = STANDARD; let mut mantissa: u64 = 0; let mut step = u64_step(10); let digits = b"1234567890123456789012345"; let mut byte = digits.bytes::<{ FORMAT }>(); parse::parse_u64_digits::<_, FORMAT>(byte.integer_iter(), &mut mantissa, &mut step); assert_eq!(mantissa, 1234567890123456789); assert_eq!(step, 0); let mut mantissa: u64 = 0; let mut step = u64_step(10); let digits = b"1234567890123456789"; let mut byte = digits.bytes::<{ FORMAT }>(); parse::parse_u64_digits::<_, FORMAT>(byte.integer_iter(), &mut mantissa, &mut step); assert_eq!(mantissa, 1234567890123456789); assert_eq!(step, 0); } #[test] fn is_special_eq_test() { const FORMAT: u128 = STANDARD; let digits = b"NaN"; let byte = digits.bytes::<{ FORMAT }>(); assert_eq!(parse::is_special_eq::(byte.clone(), b"nan"), 3); let byte = digits.bytes::<{ FORMAT }>(); assert_eq!(parse::is_special_eq::(byte.clone(), b"NaN"), 3); let byte = digits.bytes::<{ FORMAT }>(); assert_eq!(parse::is_special_eq::(byte.clone(), b"inf"), 0); } #[test] fn parse_positive_special_test() { const FORMAT: u128 = STANDARD; let options = Options::new(); let digits = b"NaN"; let byte = digits.bytes::<{ FORMAT }>(); let result = parse::parse_positive_special::(byte, &options).unwrap(); assert_eq!(result.1, 3); assert!(f64::is_nan(result.0)); let digits = b"NaN1"; let byte = digits.bytes::<{ FORMAT }>(); let result = parse::parse_positive_special::(byte, &options).unwrap(); assert_eq!(result.1, 3); assert!(f64::is_nan(result.0)); let digits = b"inf"; let byte = digits.bytes::<{ FORMAT }>(); let result = parse::parse_positive_special::(byte, &options).unwrap(); assert_eq!(result.1, 3); assert!(f64::is_infinite(result.0)); let digits = b"in"; let byte = digits.bytes::<{ FORMAT }>(); let result = parse::parse_positive_special::(byte, &options); assert_eq!(result, None); } #[test] fn parse_partial_special_test() { const FORMAT: u128 = STANDARD; let options = Options::new(); let digits = b"NaN"; let byte = digits.bytes::<{ FORMAT }>(); let result = parse::parse_partial_special::(byte, true, &options).unwrap(); assert_eq!(result.1, 3); assert!(f64::is_nan(result.0)); assert!(f64::is_sign_negative(result.0)); } #[test] fn parse_parse_special_test() { const FORMAT: u128 = STANDARD; let options = Options::new(); let digits = b"NaN"; let byte = digits.bytes::<{ FORMAT }>(); let result = parse::parse_special::(byte, true, &options).unwrap(); assert!(f64::is_nan(result)); assert!(f64::is_sign_negative(result)); let digits = b"NaN1"; let byte = digits.bytes::<{ FORMAT }>(); let result = parse::parse_special::(byte, true, &options); assert_eq!(result, None); } lexical-parse-float-0.8.5/tests/shared_tests.rs000064400000000000000000000065410072674642500177300ustar 00000000000000use lexical_parse_float::float::ExtendedFloat80; use lexical_parse_float::shared; #[cfg(feature = "power-of-two")] use lexical_util::format::NumberFormatBuilder; #[test] fn calculate_shift_test() { assert_eq!(shared::calculate_shift::(-63), 64); assert_eq!(shared::calculate_shift::(-15), 16); assert_eq!(shared::calculate_shift::(-8), 11); assert_eq!(shared::calculate_shift::(0), 11); assert_eq!(shared::calculate_shift::(50), 11); } #[test] #[cfg(feature = "power-of-two")] fn calculate_power2_test() { const BASE4: u128 = NumberFormatBuilder::from_radix(4); assert_eq!(shared::calculate_power2::(-63, 5), 944); assert_eq!(shared::calculate_power2::(-15, 5), 1040); assert_eq!(shared::calculate_power2::(-8, 0), 1059); assert_eq!(shared::calculate_power2::(-8, 5), 1054); assert_eq!(shared::calculate_power2::(0, 5), 1070); assert_eq!(shared::calculate_power2::(50, 5), 1170); } #[test] fn log2_test() { assert_eq!(shared::log2(2), 1); assert_eq!(shared::log2(4), 2); assert_eq!(shared::log2(10), 1); } #[test] fn starts_with_test() { assert_eq!(shared::starts_with(b"NaN".iter(), b"nAN".iter()), false); assert_eq!(shared::starts_with(b"nAN".iter(), b"nAN".iter()), true); assert_eq!(shared::starts_with(b"nAN1".iter(), b"nAN".iter()), true); assert_eq!(shared::starts_with(b"nAN1".iter(), b"nAN12".iter()), false); } #[test] fn case_insensitive_starts_with_test() { assert_eq!(shared::case_insensitive_starts_with(b"NaN".iter(), b"nAN".iter()), true); assert_eq!(shared::case_insensitive_starts_with(b"nAN".iter(), b"nAN".iter()), true); assert_eq!(shared::case_insensitive_starts_with(b"nAN1".iter(), b"nAN".iter()), true); assert_eq!(shared::case_insensitive_starts_with(b"nAN1".iter(), b"nAN12".iter()), false); } #[test] fn round_test() { let mut fp = ExtendedFloat80 { mant: 9223372036854776832, exp: -10, }; shared::round::(&mut fp, |f, s| { f.mant >>= s; f.exp += s; }); assert_eq!(fp.mant, 0); assert_eq!(fp.exp, 1); let mut fp = ExtendedFloat80 { mant: 9223372036854776832, exp: -10, }; shared::round::(&mut fp, |f, s| { f.mant >>= s; f.exp += s; // Round-up. f.mant += 1; }); assert_eq!(fp.mant, 1); assert_eq!(fp.exp, 1); // Round-down let mut fp = ExtendedFloat80 { mant: 9223372036854776832, exp: -10, }; shared::round::(&mut fp, |f, s| { shared::round_nearest_tie_even(f, s, |is_odd, is_halfway, is_above| { is_above || (is_odd && is_halfway) }); }); assert_eq!(fp.mant, 0); assert_eq!(fp.exp, 1); // Round up let mut fp = ExtendedFloat80 { mant: 9223372036854778880, exp: -10, }; shared::round::(&mut fp, |f, s| { shared::round_nearest_tie_even(f, s, |is_odd, is_halfway, is_above| { is_above || (is_odd && is_halfway) }); }); assert_eq!(fp.mant, 2); assert_eq!(fp.exp, 1); // Round down let mut fp = ExtendedFloat80 { mant: 9223372036854778880, exp: -10, }; shared::round::(&mut fp, shared::round_down); assert_eq!(fp.mant, 1); assert_eq!(fp.exp, 1); } lexical-parse-float-0.8.5/tests/slow_tests.rs000064400000000000000000001253720072674642500174520ustar 00000000000000mod stackvec; #[cfg(feature = "radix")] use core::cmp; #[cfg(feature = "radix")] use lexical_parse_float::bigint::Bigfloat; use lexical_parse_float::bigint::Bigint; use lexical_parse_float::float::{ExtendedFloat80, RawFloat}; use lexical_parse_float::limits::MaxDigits; use lexical_parse_float::number::Number; use lexical_parse_float::slow; use lexical_util::format::STANDARD; use stackvec::vec_from_u32; fn b(float: F) -> (u64, i32) { let fp = slow::b(float); (fp.mant, fp.exp) } fn bh(float: F) -> (u64, i32) { let fp = slow::bh(float); (fp.mant, fp.exp) } #[test] fn b_test() { assert_eq!(b(1e-45_f32), (1, -149)); assert_eq!(b(5e-324_f64), (1, -1074)); assert_eq!(b(1e-323_f64), (2, -1074)); assert_eq!(b(2e-323_f64), (4, -1074)); assert_eq!(b(3e-323_f64), (6, -1074)); assert_eq!(b(4e-323_f64), (8, -1074)); assert_eq!(b(5e-323_f64), (10, -1074)); assert_eq!(b(6e-323_f64), (12, -1074)); assert_eq!(b(7e-323_f64), (14, -1074)); assert_eq!(b(8e-323_f64), (16, -1074)); assert_eq!(b(9e-323_f64), (18, -1074)); assert_eq!(b(1_f32), (8388608, -23)); assert_eq!(b(1_f64), (4503599627370496, -52)); assert_eq!(b(1e38_f32), (9860761, 103)); assert_eq!(b(1e308_f64), (5010420900022432, 971)); } #[test] fn bh_test() { assert_eq!(bh(1e-45_f32), (3, -150)); assert_eq!(bh(5e-324_f64), (3, -1075)); assert_eq!(bh(1_f32), (16777217, -24)); assert_eq!(bh(1_f64), (9007199254740993, -53)); assert_eq!(bh(1e38_f32), (19721523, 102)); assert_eq!(bh(1e308_f64), (10020841800044865, 970)); } #[test] fn slow_radix_test() { const FORMAT: u128 = STANDARD; // 5e-324, round-down. let mut num = Number { mantissa: 2470328229206232720, exponent: -342, is_negative: false, many_digits: true, integer: b"2", fraction: Some(b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999"), }; let fp = ExtendedFloat80 { mant: 1 << 63, exp: -63, }; let result = slow::slow_radix::(num.clone(), fp); assert_eq!(result.mant, 0); assert_eq!(result.exp, 0); // 5e-324, round-up. num.fraction = Some(b"47032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281251"); let result = slow::slow_radix::(num.clone(), fp); assert_eq!(result.mant, 1); assert_eq!(result.exp, 0); // 8.98846567431158e+307 let mut num = Number { mantissa: 8988465674311580536, exponent: 289, is_negative: false, many_digits: true, integer: b"8", fraction: Some(b"9884656743115805365666807213050294962762414131308158973971342756154045415486693752413698006024096935349884403114202125541629105369684531108613657287705365884742938136589844238179474556051429647415148697857438797685859063890851407391008830874765563025951597582513936655578157348020066364210154316532161708032"), }; let fp = ExtendedFloat80 { mant: 9223372036854776832, exp: 2035, }; let result = slow::slow_radix::(num.clone(), fp); assert_eq!(result.mant, 0); assert_eq!(result.exp, 2046); // 8.988465674311582e+307 num.fraction = Some(b"98846567431158053656668072130502949627624141313081589739713427561540454154866937524136980060240969353498844031142021255416291053696845311086136572877053658847429381365898442381794745560514296474151486978574387976858590638908514073910088308747655630259515975825139366555781573480200663642101543165321617080321"); let result = slow::slow_radix::(num.clone(), fp); assert_eq!(result.mant, 1); assert_eq!(result.exp, 2046); } #[test] fn digit_comp_test() { const FORMAT: u128 = STANDARD; let max_digits = f64::max_digits(10).unwrap(); // 5e-324, round-down. let num = Number { mantissa: 2470328229206232720, exponent: -342, is_negative: false, many_digits: true, integer: b"2", fraction: Some(b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999"), }; let fp = ExtendedFloat80 { mant: 1 << 63, exp: -63, }; let result = slow::digit_comp::(num.clone(), fp, -324, max_digits); assert_eq!(result.mant, 0); assert_eq!(result.exp, 0); // 1e-323, round-up. let num = Number { mantissa: 7410984687618698162, exponent: -342, is_negative: false, many_digits: true, integer: b"7", fraction: Some(b"4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375"), }; let fp = ExtendedFloat80 { mant: 1 << 63, exp: -62, }; let result = slow::digit_comp::(num.clone(), fp, -324, max_digits); assert_eq!(result.mant, 2); assert_eq!(result.exp, 0); // 8.98846567431158e+307 let mut num = Number { mantissa: 8988465674311580536, exponent: 289, is_negative: false, many_digits: true, integer: b"8", fraction: Some(b"9884656743115805365666807213050294962762414131308158973971342756154045415486693752413698006024096935349884403114202125541629105369684531108613657287705365884742938136589844238179474556051429647415148697857438797685859063890851407391008830874765563025951597582513936655578157348020066364210154316532161708032"), }; let fp = ExtendedFloat80 { mant: 9223372036854776832, exp: 2035, }; let result = slow::digit_comp::(num.clone(), fp, 307, max_digits); assert_eq!(result.mant, 0); assert_eq!(result.exp, 2046); // 8.988465674311582e+307 num.fraction = Some(b"98846567431158053656668072130502949627624141313081589739713427561540454154866937524136980060240969353498844031142021255416291053696845311086136572877053658847429381365898442381794745560514296474151486978574387976858590638908514073910088308747655630259515975825139366555781573480200663642101543165321617080321"); let result = slow::digit_comp::(num.clone(), fp, 307, max_digits); assert_eq!(result.mant, 1); assert_eq!(result.exp, 2046); } #[test] fn positive_digit_comp_test() { const FORMAT: u128 = STANDARD; // 8.98846567431158e+307 let bigmant = Bigint { data: vec_from_u32(&[ 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, 1024, 2147483648, ]), }; let exponent = 307 + 1 - 308; let result = slow::positive_digit_comp::(bigmant, exponent); assert_eq!(result.mant, 0); assert_eq!(result.exp, 2046); // 8.988465674311582e+307 let bigmant = Bigint { data: vec_from_u32(&[ 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, 1024, 2147483648, ]), }; let exponent = 307 + 1 - 308; let result = slow::positive_digit_comp::(bigmant, exponent); assert_eq!(result.mant, 1); assert_eq!(result.exp, 2046); } #[test] fn negative_digit_comp_test() { const FORMAT: u128 = STANDARD; // 5e-324, below halfway, round-down to 0.0. let bigmant = Bigint { data: vec_from_u32(&[ 1727738439, 330069557, 3509095598, 686205316, 156923684, 750687444, 2688855918, 28211928, 1887482096, 3222998811, 913348873, 1652282845, 1600735541, 1664240266, 84454144, 1487769792, 1855966778, 2832488299, 507030148, 1410055467, 2513359584, 3453963205, 779237894, 3456088326, 3671009895, 3094451696, 1250165638, 2682979794, 357925323, 1713890438, 3271046672, 3485897285, 3934710962, 1813530592, 199705026, 976390839, 2805488572, 2194288220, 2094065006, 2592523639, 3798974617, 586957244, 1409218821, 3442050171, 3789534764, 1380190380, 2055222457, 3535299831, 429482276, 389342206, 133558576, 721875297, 3013586570, 540178306, 2389746866, 2313334501, 422440635, 1288499129, 864978311, 842263325, 3016323856, 2282442263, 1440906063, 3931458696, 3511314276, 1884879882, 946366824, 4260548261, 1073379659, 1732329252, 3828972211, 1915607049, 3665440937, 1844358779, 3735281178, 2646335050, 1457460927, 2940016422, 1051, ]), }; let fp = ExtendedFloat80 { mant: 1 << 63, exp: -63, }; let exponent = -324 + 1 - 755; let result = slow::negative_digit_comp::(bigmant, fp, exponent); assert_eq!(result.mant, 0); assert_eq!(result.exp, 0); // 5e-324, halfway, round-down to 0.0. let bigmant = Bigint { data: vec_from_u32(&[ 2084786877, 507136210, 2666388819, 3110242527, 3178432722, 541916566, 208847286, 3092404665, 83491860, 2893735989, 3973758097, 2600107496, 147629623, 1754010897, 4226332273, 2587058081, 942453804, 88731834, 1319061990, 173208747, 1982493283, 3808794987, 3874839738, 1854586992, 3508364323, 2021729080, 1899625710, 2420749567, 816401711, 3059730605, 1570934109, 3138812023, 1756281367, 3205859133, 2985201975, 1014588672, 3799556578, 577719905, 4052248225, 3649019757, 398935965, 56421532, 976366795, 1876047791, 3147705595, 4025764546, 1097271882, 1910500779, 2397021233, 1340419138, 2753207595, 3067328524, 2210626776, 1280440432, 3940874757, 4172726578, 1035509558, 1062145421, 1465448826, 2990139501, 1785427751, 2093931515, 4055890033, 3388365687, 2245484242, 3609657408, 3527114516, 1013577862, 2389075196, 426934091, 3237939346, 1071362463, 4070999470, 250952461, 2280067948, 1097862995, 2226250520, 221983348, 1, ]), }; let exponent = -324 + 1 - 752; let result = slow::negative_digit_comp::(bigmant, fp, exponent); assert_eq!(result.mant, 0); assert_eq!(result.exp, 0); // 5e-324, above halfway, round-up to 5e-324. let bigmant = Bigint { data: vec_from_u32(&[ 3667999587, 776394808, 894084415, 1037654204, 1719556155, 1124198371, 2088472861, 859275578, 834918607, 3167556114, 1082875312, 231271193, 1476296236, 360239786, 3608617070, 100777043, 834603454, 887318342, 305718012, 1732087473, 2645063646, 3728211506, 93691724, 1366000745, 723904866, 3037421624, 1816387920, 2732659194, 3869049819, 532534979, 2824439209, 1323349161, 382944493, 1993820262, 4082215981, 1555952134, 3635827414, 1482231762, 1867776587, 2130459211, 3989359658, 564215320, 1173733358, 1580608728, 1412284882, 1602939803, 2382784237, 1925138608, 2495375854, 519289497, 1762272177, 608514174, 631431287, 4214469733, 754041908, 3072560125, 1765160997, 2031519620, 1769586374, 4131591237, 674408332, 3759445970, 1904194670, 3818885807, 980005947, 1736835717, 911406800, 1545844036, 2415915482, 4269340915, 2314622388, 2123690045, 2055289038, 2509524619, 1325843000, 2388695363, 787668722, 2219833485, 10, ]), }; let exponent = -324 + 1 - 753; let result = slow::negative_digit_comp::(bigmant, fp, exponent); assert_eq!(result.mant, 1); assert_eq!(result.exp, 0); // 1e-323, below halfway, round-down to 5e-324. let bigmant = Bigint { data: vec_from_u32(&[ 888248023, 990208672, 1937352202, 2058615950, 470771052, 2252062332, 3771600458, 84635785, 1367478992, 1079061842, 2740046621, 661881239, 507239328, 697753503, 253362433, 168342080, 1272933039, 4202497602, 1521090445, 4230166401, 3245111456, 1771955024, 2337713684, 1778330386, 2423095095, 693420498, 3750496916, 3753972086, 1073775970, 846704018, 1223205425, 1867757265, 3214198296, 1145624482, 599115079, 2929172517, 4121498420, 2287897365, 1987227723, 3482603622, 2806989260, 1760871734, 4227656463, 1736215921, 2778669702, 4140571142, 1870700075, 2015964902, 1288446830, 1168026618, 400675728, 2165625891, 450825118, 1620534920, 2874273302, 2645036208, 1267321906, 3865497387, 2594934933, 2526789975, 459036976, 2552359495, 27750894, 3204441497, 1944008238, 1359672352, 2839100473, 4191710191, 3220138979, 902020460, 2896982042, 1451853853, 2406388220, 1238109043, 2615908943, 3644037856, 77415486, 230114675, 3155, ]), }; let fp = ExtendedFloat80 { mant: 1 << 63, exp: -62, }; let exponent = -324 + 1 - 755; let result = slow::negative_digit_comp::(bigmant, fp, exponent); assert_eq!(result.mant, 1); assert_eq!(result.exp, 0); // 1e-323, halfway, round-up to 1e-323. let bigmant = Bigint { data: vec_from_u32(&[ 1959393335, 1521408631, 3704199161, 740792990, 945363576, 1625749700, 626541858, 687279403, 250475582, 91273375, 3331339701, 3505355194, 442888870, 967065395, 4089062228, 3466206949, 2827361413, 266195502, 3957185970, 519626241, 1652512553, 2836450370, 3034584624, 1268793682, 1935158378, 1770219946, 1403909835, 2967281406, 2449205134, 589257223, 417835033, 826501478, 973876807, 1027642808, 365671335, 3043766018, 2808735142, 1733159717, 3566810083, 2357124681, 1196807897, 169264596, 2929100385, 1333176077, 853182194, 3487359048, 3291815648, 1436535041, 2896096404, 4021257415, 3964655489, 612050981, 2336913034, 3841321297, 3232689679, 3928245144, 3106528676, 3186436263, 101379182, 380483912, 1061315959, 1986827250, 3577735508, 1575162471, 2441485432, 2239037633, 1991408958, 3040733588, 2872258292, 1280802274, 1123883446, 3214087391, 3623063818, 752857385, 2545236548, 3293588986, 2383784264, 665950045, 3, ]), }; let exponent = -324 + 1 - 752; let result = slow::negative_digit_comp::(bigmant, fp, exponent); assert_eq!(result.mant, 2); assert_eq!(result.exp, 0); // 1e-323, above halfway, round-up to 1e-323. let bigmant = Bigint { data: vec_from_u32(&[ 2414064167, 2329184426, 2682253245, 3112962612, 863701169, 3372595114, 1970451287, 2577826735, 2504755821, 912733750, 3248625938, 693813579, 133921412, 1080719359, 2235916618, 302331131, 2503810362, 2661955026, 917154036, 901295123, 3640223643, 2594699927, 281075174, 4098002235, 2171714598, 522330280, 1154196466, 3903010287, 3017214866, 1597604939, 4178350331, 3970047484, 1148833479, 1686493490, 3656713352, 372889108, 2317547651, 151727992, 1308362466, 2096410338, 3378144383, 1692645962, 3521200074, 446858888, 4236854647, 513852113, 2853385416, 1480448529, 3191160267, 1557868492, 991849235, 1825542523, 1894293861, 4053474607, 2262125726, 627745783, 1000515697, 1799591565, 1013791827, 3804839120, 2023224998, 2688403318, 1417616716, 2866722830, 2940017843, 915539855, 2734220401, 342564812, 2952779151, 4218088154, 2648899870, 2076102840, 1870899819, 3233606562, 3977529001, 2871118793, 2363006167, 2364533159, 31, ]), }; let exponent = -324 + 1 - 753; let result = slow::negative_digit_comp::(bigmant, fp, exponent); assert_eq!(result.mant, 2); assert_eq!(result.exp, 0); } #[test] fn parse_mantissa_test() { const FORMAT: u128 = STANDARD; let max_digits = f64::max_digits(10).unwrap(); // Large number of digits. let mut num = Number { mantissa: 2470328229206232720, exponent: -342, is_negative: false, many_digits: true, integer: b"2", fraction: Some(b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999"), }; let (bigmant, count) = slow::parse_mantissa::(num.clone(), max_digits); let expected = vec_from_u32::<100>(&[ 1727738439, 330069557, 3509095598, 686205316, 156923684, 750687444, 2688855918, 28211928, 1887482096, 3222998811, 913348873, 1652282845, 1600735541, 1664240266, 84454144, 1487769792, 1855966778, 2832488299, 507030148, 1410055467, 2513359584, 3453963205, 779237894, 3456088326, 3671009895, 3094451696, 1250165638, 2682979794, 357925323, 1713890438, 3271046672, 3485897285, 3934710962, 1813530592, 199705026, 976390839, 2805488572, 2194288220, 2094065006, 2592523639, 3798974617, 586957244, 1409218821, 3442050171, 3789534764, 1380190380, 2055222457, 3535299831, 429482276, 389342206, 133558576, 721875297, 3013586570, 540178306, 2389746866, 2313334501, 422440635, 1288499129, 864978311, 842263325, 3016323856, 2282442263, 1440906063, 3931458696, 3511314276, 1884879882, 946366824, 4260548261, 1073379659, 1732329252, 3828972211, 1915607049, 3665440937, 1844358779, 3735281178, 2646335050, 1457460927, 2940016422, 1051, ]); assert_eq!(&*bigmant.data, &*expected); assert_eq!(count, 755); // Leading zeros num.integer = b"0000000002"; let (bigmant, count) = slow::parse_mantissa::(num.clone(), max_digits); assert_eq!(&*bigmant.data, &*expected); assert_eq!(count, 755); // Truncation. let mut num = Number { mantissa: 7410984687618698162, exponent: -342, is_negative: false, many_digits: true, integer: b"7", fraction: Some(b"4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375332669816033062329967789262837"), }; let (bigmant, count) = slow::parse_mantissa::(num.clone(), max_digits); let expected = vec_from_u32::<100>(&[ 983641521, 2202462645, 4170685875, 1591772364, 529830014, 803977727, 126733331, 1695971390, 4089590927, 1532849076, 2705586665, 4046282448, 4076195232, 3230469892, 3059053929, 79035789, 744229654, 2026438108, 3570486781, 2818088662, 3485839733, 3653138023, 2857937689, 602717004, 3689362390, 283607819, 1783392475, 2053068939, 1888214698, 550023429, 296880187, 1046779059, 1285361259, 84614934, 1627922685, 2023868765, 1987523901, 743493573, 3897769089, 2210613570, 2261081349, 3015057659, 3949711644, 3346092916, 2433639051, 36411806, 1050442, 269209477, 2649742673, 1494221829, 2763524503, 2514491481, 2325312415, 1741242814, 2479923579, 1098250122, 2416211509, 3612906464, 403420662, 3663250314, 1993722098, 365907183, 4270226312, 3962131185, 432952495, 2963635838, 2996289227, 3200289391, 2753231690, 2780286109, 884373163, 1418533204, 3382415762, 499541562, 3369625401, 3421327641, 3526770155, 3109983188, 1157439767, 734593155, ]); assert_eq!(&*bigmant.data, &*expected); assert_eq!(count, max_digits + 1); // No fraction digits. num.integer = b"74109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375332669816033062329967789262837"; num.fraction = None; let (bigmant, count) = slow::parse_mantissa::(num.clone(), max_digits); assert_eq!(&*bigmant.data, &*expected); assert_eq!(count, max_digits + 1); // Multiple of step (check we add our temporary correctly). num.integer = b"7410984687618698162648531893023320585475897039214871466383785237510132609053131277979497545424539885696948470431685765963899850655339096945981621940161728171894510697854671067917687257517734731555330779540854980960845750095811137303474765809687100959097544227100475730780971111893578483867565399878350301522805593404659373979179073872386829939581848166016912201945649993128979841136206248449867871357218035220901702390328579173252022052897402080290685402160661237554998340267130003581248647904138574340187552090159017259254714629617513415977493871857473787096164563890871811984127167305601704549300470526959016576377688490826798697257336652176556794107250876433756084600398490497214911746308553955635418864151316847843631308023759629577398300170898437533266981"; num.fraction = None; let (bigmant, count) = slow::parse_mantissa::(num.clone(), max_digits); let expected = vec_from_u32::<100>(&[ 617018405, 396211401, 2130402383, 3812547827, 4263683770, 3918012496, 1787721490, 2493014694, 435464626, 3720854431, 2928509507, 2677932436, 369049650, 3606588290, 231237141, 2231172875, 3358152367, 95217925, 2777810007, 1016185079, 596681915, 2331711780, 593487272, 4212730845, 339602972, 4097829793, 262427536, 4182115035, 3414687403, 3711518952, 4168896929, 483727327, 1657080031, 2785588628, 1009114769, 482126749, 485376744, 1123705337, 3225501941, 2939050108, 1338451005, 2104263947, 3425461126, 1834224928, 4061025704, 792093815, 2707019125, 3610271203, 4254101529, 1026215278, 4117890107, 1748110416, 2535111606, 80965120, 3823822115, 2354910057, 590658512, 2682089507, 159300272, 1776569442, 3382166479, 3222978591, 540586210, 934713382, 2014123057, 1455555790, 4119131465, 3685912982, 3019947291, 3437891678, 2660105801, 2605860762, 394373515, 4177081532, 1616198650, 1580399082, 2017617452, 3327697130, 315505357, ]); assert_eq!(&*bigmant.data, &*expected); assert_eq!(count, 760); } #[test] #[cfg(feature = "radix")] fn byte_comp_test() { const FORMAT: u128 = STANDARD; // 5e-324 let mut num = Number { mantissa: 2470328229206232720, exponent: -342, is_negative: false, many_digits: true, integer: b"2", fraction: Some(b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999"), }; let fp = ExtendedFloat80 { mant: 1 << 63, exp: -63, }; let result = slow::byte_comp::(num.clone(), fp, -324); assert_eq!(result.mant, 0); assert_eq!(result.exp, 0); // 5e-324, equal, round-down num.fraction = Some(b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125"); let result = slow::byte_comp::(num.clone(), fp, -324); assert_eq!(result.mant, 0); assert_eq!(result.exp, 0); // 5e-324, equal, round-down, many 0s num.fraction = Some(b"47032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281250000000"); let result = slow::byte_comp::(num.clone(), fp, -324); assert_eq!(result.mant, 0); assert_eq!(result.exp, 0); // 5e-324, above, round-up num.fraction = Some(b"47032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281251"); let result = slow::byte_comp::(num.clone(), fp, -324); assert_eq!(result.mant, 1); assert_eq!(result.exp, 0); // 8.98846567431158e+307 let mut num = Number { mantissa: 8988465674311580536, exponent: 289, is_negative: false, many_digits: true, integer: b"8", fraction: Some(b"9884656743115805365666807213050294962762414131308158973971342756154045415486693752413698006024096935349884403114202125541629105369684531108613657287705365884742938136589844238179474556051429647415148697857438797685859063890851407391008830874765563025951597582513936655578157348020066364210154316532161708032"), }; let fp = ExtendedFloat80 { mant: 9223372036854776832, exp: 960 + 1075, }; let result = slow::byte_comp::(num.clone(), fp, 307); assert_eq!(result.mant, 0); assert_eq!(result.exp, 2046); // 8.988465674311582e+307 num.fraction = Some(b"98846567431158053656668072130502949627624141313081589739713427561540454154866937524136980060240969353498844031142021255416291053696845311086136572877053658847429381365898442381794745560514296474151486978574387976858590638908514073910088308747655630259515975825139366555781573480200663642101543165321617080321"); let result = slow::byte_comp::(num.clone(), fp, 307); assert_eq!(result.mant, 1); assert_eq!(result.exp, 2046); } #[test] #[cfg(feature = "radix")] fn compare_bytes_test() { const FORMAT: u128 = STANDARD; // 2^-1074 let num = Bigfloat { data: vec_from_u32(&[ 1725370368, 1252154597, 1017462556, 675087593, 2805901938, 1401824593, 1124332496, 2380663002, 1612846757, 4128923878, 1492915356, 437569744, 2975325085, 3331531962, 3367627909, 730662168, 2699172281, 1440714968, 2778340312, 690527038, 1297115354, 763425880, 1453089653, 331561842, ]), exp: 312, }; let den = Bigfloat { data: vec_from_u32(&[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134217728, ]), exp: 312, }; // Below halfway let mut number = Number { mantissa: 2470328229206232720, exponent: -342, is_negative: false, many_digits: true, integer: b"2", fraction: Some(b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999"), }; assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Less ); // Exactly halfway. number.fraction = Some(b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125"); assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Equal ); // Above halfway. number.fraction = Some(b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125001"); assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Greater ); // 2*2^-1074 let num = Bigfloat { data: vec_from_u32(&[ 881143808, 3756463792, 3052387668, 2025262779, 4122738518, 4205473780, 3372997488, 2847021710, 543572976, 3796837043, 183778774, 1312709233, 336040663, 1404661296, 1512949137, 2191986506, 3802549547, 27177609, 4040053641, 2071581115, 3891346062, 2290277640, 64301663, 994685527, ]), exp: 312, }; let den = Bigfloat { data: vec_from_u32(&[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134217728, ]), exp: 312, }; // Below halfway let mut number = Number { mantissa: 7410984687618698162, exponent: -342, is_negative: false, many_digits: true, integer: b"7", fraction: Some(b"4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984374999"), }; assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Less ); // Exactly halfway. number.fraction = Some(b"4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375"); assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Equal ); // Above halfway. number.fraction = Some(b"4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375001"); assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Greater ); // 4503599627370496*2^971 let num = Bigfloat { data: vec_from_u32(&[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1024, 2147483648, ]), exp: 288, }; let den = Bigfloat { data: vec_from_u32(&[ 1978138624, 2671552565, 2938166866, 3588566204, 1860064291, 2104472219, 2014975858, 2797301608, 462262832, 318515330, 1101517094, 1738264167, 3721375114, 414401884, 1406861075, 3053102637, 387329537, 2051556775, 1867945454, 3717689914, 1434550525, 1446648206, 238915486, ]), exp: 288, }; // Below halfway let mut number = Number { mantissa: 8988465674311580536, exponent: 289, is_negative: false, many_digits: true, integer: b"8", fraction: Some(b"9884656743115805365666807213050294962762414131308158973971342756154045415486693752413698006024096935349884403114202125541629105369684531108613657287705365884742938136589844238179474556051429647415148697857438797685859063890851407391008830874765563025951597582513936655578157348020066364210154316532161708031999"), }; assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Less ); // Exactly halfway. number.fraction = Some(b"9884656743115805365666807213050294962762414131308158973971342756154045415486693752413698006024096935349884403114202125541629105369684531108613657287705365884742938136589844238179474556051429647415148697857438797685859063890851407391008830874765563025951597582513936655578157348020066364210154316532161708032"); assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Equal ); // Above halfway. number.fraction = Some(b"9884656743115805365666807213050294962762414131308158973971342756154045415486693752413698006024096935349884403114202125541629105369684531108613657287705365884742938136589844238179474556051429648741514697857438797685859063890851407391008830874765563025951597582513936655578157348020066364210154316532161708032001"); assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Greater ); // Ensure leading and trailing zeros are ignored. // Below halfway number.integer = b"000008"; number.fraction = Some(b"98846567431158053656668072130502949627624141313081589739713427561540454154866937524136980060240969353498844031142021255416291053696845311086136572877053658847429381365898442381794745560514296474151486978574387976858590638908514073910088308747655630259515975825139366555781573480200663642101543165321617080319990000"); assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Less ); // Exactly halfway. number.integer = b"000008"; number.fraction = Some(b"98846567431158053656668072130502949627624141313081589739713427561540454154866937524136980060240969353498844031142021255416291053696845311086136572877053658847429381365898442381794745560514296474151486978574387976858590638908514073910088308747655630259515975825139366555781573480200663642101543165321617080320000"); assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Equal ); // Above halfway. number.integer = b"000008"; number.fraction = Some(b"98846567431158053656668072130502949627624141313081589739713427561540454154866937524136980060240969353498844031142021255416291053696845311086136572877053658847429381365898442381794745560514296487415146978574387976858590638908514073910088308747655630259515975825139366555781573480200663642101543165321617080320010000"); assert_eq!( slow::compare_bytes::(number.clone(), num.clone(), den.clone()), cmp::Ordering::Greater ); } #[test] fn scientific_exponent_test() { let mut number = Number { exponent: -4, mantissa: 12345, is_negative: false, many_digits: false, integer: &[], fraction: None, }; assert_eq!(slow::scientific_exponent::<{ STANDARD }>(&number), 0); number.exponent = -15; assert_eq!(slow::scientific_exponent::<{ STANDARD }>(&number), -11); number.mantissa = 1234567890123456; assert_eq!(slow::scientific_exponent::<{ STANDARD }>(&number), 0); } #[test] #[cfg(feature = "radix")] fn integral_binary_factor_test() { const TABLE: [u32; 35] = [ 0, 2, 0, 3, 3, 3, 0, 4, 4, 4, 4, 4, 4, 4, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 6, 6, 6, 6, ]; for (index, radix) in (2..37).enumerate() { assert_eq!(slow::integral_binary_factor(radix), TABLE[index]); } } lexical-parse-float-0.8.5/tests/stackvec.rs000064400000000000000000000014460072674642500170420ustar 00000000000000use lexical_parse_float::bigint::{Limb, StackVec}; pub fn vec_from_u32(x: &[u32]) -> StackVec { let mut vec = StackVec::::new(); #[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))] { for &xi in x { vec.try_push(xi as Limb).unwrap(); } } #[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))] { for xi in x.chunks(2) { match xi.len() { 1 => vec.try_push(xi[0] as Limb).unwrap(), 2 => { let xi0 = xi[0] as Limb; let xi1 = xi[1] as Limb; vec.try_push((xi1 << 32) | xi0).unwrap() }, _ => unreachable!(), } } } vec } lexical-parse-float-0.8.5/tests/stackvec_tests.rs000064400000000000000000000376120072674642500202700ustar 00000000000000mod stackvec; use core::cmp; use lexical_parse_float::bigint::{self, Limb, StackVec, LIMB_BITS}; use stackvec::vec_from_u32; const SIZE: usize = 50; type VecType = StackVec; #[test] fn simple_test() { // Test the simple properties of the stack vector. let mut x = VecType::from_u32(1); assert_eq!(x.len(), 1); assert_eq!(x.is_empty(), false); assert_eq!(x.capacity(), SIZE); x.try_push(5).unwrap(); assert_eq!(x.len(), 2); assert_eq!(x.pop(), Some(5)); assert_eq!(x.len(), 1); assert_eq!(&*x, &[1]); x.try_extend(&[2, 3, 4]).unwrap(); assert_eq!(x.len(), 4); assert_eq!(&*x, &[1, 2, 3, 4]); x.try_resize(6, 0).unwrap(); assert_eq!(x.len(), 6); assert_eq!(&*x, &[1, 2, 3, 4, 0, 0]); x.try_resize(0, 0).unwrap(); assert_eq!(x.len(), 0); assert_eq!(x.is_empty(), true); let x = VecType::try_from(&[5, 1]).unwrap(); assert_eq!(x.len(), 2); assert_eq!(x.is_empty(), false); assert_eq!(x.hi16(), (0x8000, true)); if LIMB_BITS == 32 { assert_eq!(x.hi32(), (0x80000002, true)); assert_eq!(x.hi64(), (0x8000000280000000, false)); } else { assert_eq!(x.hi32(), (0x80000000, true)); assert_eq!(x.hi64(), (0x8000000000000002, true)); } let rview = x.rview(); assert_eq!(x[0], 5); assert_eq!(x[1], 1); assert_eq!(rview[0], 1); assert_eq!(rview[1], 5); assert_eq!(rview.get(1), Some(&5)); assert_eq!(rview.get(2), None); assert_eq!(VecType::from_u16(u16::MAX).hi16(), (u16::MAX, false)); assert_eq!(VecType::from_u32(u32::MAX).hi32(), (u32::MAX, false)); assert_eq!(VecType::from_u64(u64::MAX).hi64(), (u64::MAX, false)); } #[test] fn bounds_test() { type ShortVec = StackVec<2>; let mut x = ShortVec::from_u32(1); assert_eq!(x.try_push(2), Some(())); assert_eq!(x.try_push(5), None); assert_eq!(x.try_resize(0, 0), Some(())); assert_eq!(x.try_resize(3, 0), None); } #[test] fn hi32_test() { assert_eq!(VecType::from_u16(0xA).hi32(), (0xA0000000, false)); assert_eq!(VecType::from_u32(0xAB).hi32(), (0xAB000000, false)); assert_eq!(VecType::from_u64(0xAB00000000).hi32(), (0xAB000000, false)); assert_eq!(VecType::from_u64(0xA23456789A).hi32(), (0xA2345678, true)); } #[test] fn hi64_test() { assert_eq!(VecType::from_u16(0xA).hi64(), (0xA000000000000000, false)); assert_eq!(VecType::from_u32(0xAB).hi64(), (0xAB00000000000000, false)); assert_eq!(VecType::from_u64(0xAB00000000).hi64(), (0xAB00000000000000, false)); assert_eq!(VecType::from_u64(0xA23456789A).hi64(), (0xA23456789A000000, false)); } #[test] fn cmp_test() { // Simple let x = VecType::from_u32(1); let y = VecType::from_u32(2); assert_eq!(x.partial_cmp(&x), Some(cmp::Ordering::Equal)); assert_eq!(x.cmp(&x), cmp::Ordering::Equal); assert_eq!(x.cmp(&y), cmp::Ordering::Less); // Check asymmetric let x = VecType::try_from(&[5, 1]).unwrap(); let y = VecType::from_u32(2); assert_eq!(x.cmp(&x), cmp::Ordering::Equal); assert_eq!(x.cmp(&y), cmp::Ordering::Greater); // Check when we use reverse ordering properly. let x = VecType::try_from(&[5, 1, 9]).unwrap(); let y = VecType::try_from(&[6, 2, 8]).unwrap(); assert_eq!(x.cmp(&x), cmp::Ordering::Equal); assert_eq!(x.cmp(&y), cmp::Ordering::Greater); // Complex scenario, check it properly uses reverse ordering. let x = VecType::try_from(&[0, 1, 9]).unwrap(); let y = VecType::try_from(&[4294967295, 0, 9]).unwrap(); assert_eq!(x.cmp(&x), cmp::Ordering::Equal); assert_eq!(x.cmp(&y), cmp::Ordering::Greater); } #[test] fn math_test() { let mut x = VecType::try_from(&[0, 1, 9]).unwrap(); assert_eq!(x.is_normalized(), true); x.try_push(0).unwrap(); assert_eq!(&*x, &[0, 1, 9, 0]); assert_eq!(x.is_normalized(), false); x.normalize(); assert_eq!(&*x, &[0, 1, 9]); assert_eq!(x.is_normalized(), true); x.add_small(1); assert_eq!(&*x, &[1, 1, 9]); x.add_small(Limb::MAX); assert_eq!(&*x, &[0, 2, 9]); x.mul_small(3); assert_eq!(&*x, &[0, 6, 27]); x.mul_small(Limb::MAX); let expected: VecType = if LIMB_BITS == 32 { vec_from_u32(&[0, 4294967290, 4294967274, 26]) } else { vec_from_u32(&[0, 0, 4294967290, 4294967295, 4294967274, 4294967295, 26]) }; assert_eq!(&*x, &*expected); #[cfg(feature = "radix")] { let mut x: VecType = vec_from_u32(&[0, 0, 0, 536870912]); let y: VecType = vec_from_u32(&[3358091099, 2770363594, 2782716766, 217327764]); assert_eq!(x.quorem(&y), 2); let expected: VecType = vec_from_u32(&[1873752394, 3049207402, 3024501058, 102215382]); assert_eq!(&*x, &*expected); } let mut x = VecType::from_u32(0xFFFFFFFF); let y = VecType::from_u32(5); x *= &y; let expected: VecType = vec_from_u32(&[0xFFFFFFFB, 0x4]); assert_eq!(&*x, &*expected); // Test with carry let mut x = VecType::from_u32(1); assert_eq!(&*x, &[1]); x.add_small(Limb::MAX); assert_eq!(&*x, &[0, 1]); } #[test] fn hi_test() { assert_eq!(unsafe { bigint::nonzero(&[0, 0, 0], 0) }, false); assert_eq!(unsafe { bigint::nonzero(&[1, 0, 0], 0) }, true); assert_eq!(bigint::u32_to_hi16_1(1), (0x8000, false)); assert_eq!(bigint::u32_to_hi16_2(1, 4), (0x8000, true)); assert_eq!(bigint::u32_to_hi32_1(1), (0x80000000, false)); assert_eq!(bigint::u32_to_hi32_2(1, 4), (0x80000002, false)); assert_eq!(bigint::u32_to_hi64_1(1), (0x8000000000000000, false)); assert_eq!(bigint::u32_to_hi64_2(1, 4), (0x8000000200000000, false)); assert_eq!(bigint::u32_to_hi64_2(1, 5), (0x8000000280000000, false)); assert_eq!(bigint::u32_to_hi64_3(1, 5, 4), (0x8000000280000002, false)); assert_eq!(bigint::u32_to_hi64_3(1, 5, 5), (0x8000000280000002, true)); assert_eq!(bigint::u64_to_hi16_1(1), (0x8000, false)); assert_eq!(bigint::u64_to_hi16_2(1, 4), (0x8000, true)); assert_eq!(bigint::u64_to_hi32_1(1), (0x80000000, false)); assert_eq!(bigint::u64_to_hi32_2(1, 4), (0x80000000, true)); assert_eq!(bigint::u64_to_hi64_1(1), (0x8000000000000000, false)); assert_eq!(bigint::u64_to_hi64_2(1, 4), (0x8000000000000002, false)); assert_eq!(bigint::u64_to_hi64_2(1, 5), (0x8000000000000002, true)); } #[test] fn scalar_add_test() { assert_eq!(bigint::scalar_add(5, 5), (10, false)); assert_eq!(bigint::scalar_add(Limb::MAX, 1), (0, true)); } #[test] fn scalar_mul_test() { assert_eq!(bigint::scalar_mul(5, 5, 0), (25, 0)); assert_eq!(bigint::scalar_mul(5, 5, 1), (26, 0)); assert_eq!(bigint::scalar_mul(Limb::MAX, 2, 0), (Limb::MAX - 1, 1)); } #[test] fn small_add_test() { let mut x = VecType::from_u32(4294967295); bigint::small_add(&mut x, 5); let expected: VecType = vec_from_u32(&[4, 1]); assert_eq!(&*x, &*expected); let mut x = VecType::from_u32(5); bigint::small_add(&mut x, 7); let expected = VecType::from_u32(12); assert_eq!(&*x, &*expected); // Single carry, internal overflow let mut x = VecType::from_u64(0x80000000FFFFFFFF); bigint::small_add(&mut x, 7); let expected: VecType = vec_from_u32(&[6, 0x80000001]); assert_eq!(&*x, &*expected); // Double carry, overflow let mut x = VecType::from_u64(0xFFFFFFFFFFFFFFFF); bigint::small_add(&mut x, 7); let expected: VecType = vec_from_u32(&[6, 0, 1]); assert_eq!(&*x, &*expected); } #[test] fn small_mul_test() { // No overflow check, 1-int. let mut x = VecType::from_u32(5); bigint::small_mul(&mut x, 7); let expected = VecType::from_u32(35); assert_eq!(&*x, &*expected); // No overflow check, 2-ints. let mut x = VecType::from_u64(0x4000000040000); bigint::small_mul(&mut x, 5); let expected: VecType = vec_from_u32(&[0x00140000, 0x140000]); assert_eq!(&*x, &*expected); // Overflow, 1 carry. let mut x = VecType::from_u32(0x33333334); bigint::small_mul(&mut x, 5); let expected: VecType = vec_from_u32(&[4, 1]); assert_eq!(&*x, &*expected); // Overflow, 1 carry, internal. let mut x = VecType::from_u64(0x133333334); bigint::small_mul(&mut x, 5); let expected: VecType = vec_from_u32(&[4, 6]); assert_eq!(&*x, &*expected); // Overflow, 2 carries. let mut x = VecType::from_u64(0x3333333333333334); bigint::small_mul(&mut x, 5); let expected: VecType = vec_from_u32(&[4, 0, 1]); assert_eq!(&*x, &*expected); } #[test] fn pow_test() { let mut x = VecType::from_u32(1); bigint::pow(&mut x, 5, 2); let expected = VecType::from_u32(25); assert_eq!(&*x, &*expected); let mut x = VecType::from_u32(1); bigint::pow(&mut x, 5, 15); let expected: VecType = vec_from_u32(&[452807053, 7]); assert_eq!(&*x, &*expected); let mut x = VecType::from_u32(1); bigint::pow(&mut x, 5, 16); let expected: VecType = vec_from_u32(&[2264035265, 35]); assert_eq!(&*x, &*expected); let mut x = VecType::from_u32(1); bigint::pow(&mut x, 5, 17); let expected: VecType = vec_from_u32(&[2730241733, 177]); assert_eq!(&*x, &*expected); let mut x = VecType::from_u32(1); bigint::pow(&mut x, 5, 302); let expected: VecType = vec_from_u32(&[ 2443090281, 2149694430, 2297493928, 1584384001, 1279504719, 1930002239, 3312868939, 3735173465, 3523274756, 2025818732, 1641675015, 2431239749, 4292780461, 3719612855, 4174476133, 3296847770, 2677357556, 638848153, 2198928114, 3285049351, 2159526706, 626302612, ]); assert_eq!(&*x, &*expected); } #[test] fn large_add_test() { // Overflow, both single values let mut x = VecType::from_u32(4294967295); let y = VecType::from_u32(5); bigint::large_add(&mut x, &y); let expected: VecType = vec_from_u32(&[4, 1]); assert_eq!(&*x, &*expected); // No overflow, single value let mut x = VecType::from_u32(5); let y = VecType::from_u32(7); bigint::large_add(&mut x, &y); let expected = VecType::from_u32(12); assert_eq!(&*x, &*expected); // Single carry, internal overflow let mut x = VecType::from_u64(0x80000000FFFFFFFF); let y = VecType::from_u32(7); bigint::large_add(&mut x, &y); let expected: VecType = vec_from_u32(&[6, 0x80000001]); assert_eq!(&*x, &*expected); // 1st overflows, 2nd doesn't. let mut x = VecType::from_u64(0x7FFFFFFFFFFFFFFF); let y = VecType::from_u64(0x7FFFFFFFFFFFFFFF); bigint::large_add(&mut x, &y); let expected: VecType = vec_from_u32(&[0xFFFFFFFE, 0xFFFFFFFF]); assert_eq!(&*x, &*expected); // Both overflow. let mut x = VecType::from_u64(0x8FFFFFFFFFFFFFFF); let y = VecType::from_u64(0x7FFFFFFFFFFFFFFF); bigint::large_add(&mut x, &y); let expected: VecType = vec_from_u32(&[0xFFFFFFFE, 0x0FFFFFFF, 1]); assert_eq!(&*x, &*expected); } #[test] fn large_mul_test() { // Test by empty let mut x = VecType::from_u32(0xFFFFFFFF); let y = VecType::new(); bigint::large_mul(&mut x, &y); let expected = VecType::new(); assert_eq!(&*x, &*expected); // Simple case let mut x = VecType::from_u32(0xFFFFFFFF); let y = VecType::from_u32(5); bigint::large_mul(&mut x, &y); let expected: VecType = vec_from_u32(&[0xFFFFFFFB, 0x4]); assert_eq!(&*x, &*expected); // Large u32, but still just as easy. let mut x = VecType::from_u32(0xFFFFFFFF); let y = VecType::from_u32(0xFFFFFFFE); bigint::large_mul(&mut x, &y); let expected: VecType = vec_from_u32(&[0x2, 0xFFFFFFFD]); assert_eq!(&*x, &*expected); // Let's multiply two large values together. let mut x: VecType = vec_from_u32(&[0xFFFFFFFE, 0x0FFFFFFF, 1]); let y: VecType = vec_from_u32(&[0x99999999, 0x99999999, 0xCCCD9999, 0xCCCC]); bigint::large_mul(&mut x, &y); let expected: VecType = vec_from_u32(&[0xCCCCCCCE, 0x5CCCCCCC, 0x9997FFFF, 0x33319999, 0x999A7333, 0xD999]); assert_eq!(&*x, &*expected); } #[test] fn very_large_mul_test() { // Test cases triggered to that would normally use `karatsuba_mul`. // Karatsuba multiplication was ripped out, however, these are useful // test cases. let mut x: VecType = vec_from_u32(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); let y: VecType = vec_from_u32(&[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]); bigint::large_mul(&mut x, &y); let expected: VecType = vec_from_u32(&[ 4, 13, 28, 50, 80, 119, 168, 228, 300, 385, 484, 598, 728, 875, 1040, 1224, 1340, 1435, 1508, 1558, 1584, 1585, 1560, 1508, 1428, 1319, 1180, 1010, 808, 573, 304, ]); assert_eq!(&*x, &*expected); // Test cases triggered to that would normally use `karatsuba_uneven_mul`. let mut x: VecType = vec_from_u32(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); let y: VecType = vec_from_u32(&[ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, ]); bigint::large_mul(&mut x, &y); let expected: VecType = vec_from_u32(&[ 4, 13, 28, 50, 80, 119, 168, 228, 300, 385, 484, 598, 728, 875, 1040, 1224, 1360, 1496, 1632, 1768, 1904, 2040, 2176, 2312, 2448, 2584, 2720, 2856, 2992, 3128, 3264, 3400, 3536, 3672, 3770, 3829, 3848, 3826, 3762, 3655, 3504, 3308, 3066, 2777, 2440, 2054, 1618, 1131, 592, ]); assert_eq!(&*x, &*expected); } #[test] #[cfg(feature = "radix")] fn quorem_test() { let mut x: VecType = vec_from_u32(&[0, 0, 0, 536870912]); let y: VecType = vec_from_u32(&[3358091099, 2770363594, 2782716766, 217327764]); assert_eq!(bigint::large_quorem(&mut x, &y), 2); let expected: VecType = vec_from_u32(&[1873752394, 3049207402, 3024501058, 102215382]); assert_eq!(&*x, &*expected); } #[test] fn bit_length_test() { let x: VecType = vec_from_u32(&[0, 0, 0, 1]); assert_eq!(bigint::bit_length(&x), 97); let x: VecType = vec_from_u32(&[0, 0, 0, 3]); assert_eq!(bigint::bit_length(&x), 98); let x = VecType::from_u32(1 << 31); assert_eq!(bigint::bit_length(&x), 32); } #[test] fn shl_bits_test() { let mut x = VecType::from_u32(0xD2210408); bigint::shl_bits(&mut x, 5); let expected: VecType = vec_from_u32(&[0x44208100, 0x1A]); assert_eq!(&*x, &*expected); } #[test] fn shl_limbs_test() { let mut x = VecType::from_u32(0xD2210408); bigint::shl_limbs(&mut x, 2); let expected: VecType = if LIMB_BITS == 32 { vec_from_u32(&[0, 0, 0xD2210408]) } else { vec_from_u32(&[0, 0, 0, 0, 0xD2210408]) }; assert_eq!(&*x, &*expected); } #[test] fn shl_test() { // Pattern generated via `''.join(["1" +"0"*i for i in range(20)])` let mut x = VecType::from_u32(0xD2210408); bigint::shl(&mut x, 5); let expected: VecType = vec_from_u32(&[0x44208100, 0x1A]); assert_eq!(&*x, &*expected); bigint::shl(&mut x, 32); let expected: VecType = vec_from_u32(&[0, 0x44208100, 0x1A]); assert_eq!(&*x, &*expected); bigint::shl(&mut x, 27); let expected: VecType = vec_from_u32(&[0, 0, 0xD2210408]); assert_eq!(&*x, &*expected); // 96-bits of previous pattern let mut x: VecType = vec_from_u32(&[0x20020010, 0x8040100, 0xD2210408]); bigint::shl(&mut x, 5); let expected: VecType = vec_from_u32(&[0x400200, 0x802004, 0x44208101, 0x1A]); assert_eq!(&*x, &*expected); bigint::shl(&mut x, 32); let expected: VecType = vec_from_u32(&[0, 0x400200, 0x802004, 0x44208101, 0x1A]); assert_eq!(&*x, &*expected); bigint::shl(&mut x, 27); let expected: VecType = vec_from_u32(&[0, 0, 0x20020010, 0x8040100, 0xD2210408]); assert_eq!(&*x, &*expected); } #[test] fn split_radix_test() { assert_eq!(bigint::split_radix(10), (5, 1)); if cfg!(feature = "radix") { assert_eq!(bigint::split_radix(2), (0, 1)); assert_eq!(bigint::split_radix(4), (0, 2)); assert_eq!(bigint::split_radix(8), (0, 3)); assert_eq!(bigint::split_radix(16), (0, 4)); assert_eq!(bigint::split_radix(32), (0, 5)); assert_eq!(bigint::split_radix(14), (7, 1)); } }