├── .gitattributes ├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE-APACHE.txt ├── LICENSE-MIT.txt ├── README.md ├── appveyor.bat ├── appveyor.yml ├── build.rs ├── extprim_literals ├── Cargo.toml ├── LICENSE-APACHE.txt ├── LICENSE-MIT.txt └── src │ └── lib.rs ├── extprim_literals_macros ├── Cargo.toml ├── LICENSE-APACHE.txt ├── LICENSE-MIT.txt └── src │ └── lib.rs ├── extprim_tests ├── Cargo.toml └── tests │ └── literals.rs ├── generate_assembly.sh └── src ├── compiler_rt.rs ├── error.rs ├── format_buffer.rs ├── forward.rs ├── i128.rs ├── lib.rs ├── traits.rs └── u128.rs /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bat eol=crlf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | Cargo.lock 3 | *.swp 4 | *.swo 5 | *.o 6 | *.a 7 | *.pyc 8 | .DS_Store 9 | *.s 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | sudo: false 3 | 4 | addons: 5 | apt: 6 | packages: 7 | - libcurl4-openssl-dev 8 | - libelf-dev 9 | - libdw-dev 10 | - binutils-dev 11 | - gcc-multilib 12 | 13 | matrix: 14 | fast_finish: true 15 | include: 16 | - os: linux 17 | rust: 1.22.1 18 | env: ARCH=x86_64 19 | - os: linux 20 | rust: stable 21 | env: ARCH=x86_64 22 | - os: linux 23 | rust: beta 24 | env: ARCH=x86_64 25 | - os: linux 26 | rust: nightly 27 | env: ARCH=x86_64 28 | - os: osx 29 | rust: stable 30 | env: ARCH=x86_64 31 | - os: linux 32 | rust: nightly 33 | env: ARCH=i686 34 | 35 | install: 36 | - if [ "$TRAVIS_OS_NAME" = 'linux' ]; then OS=unknown-linux-gnu; else OS=apple-darwin; fi 37 | - export HOST=$ARCH-$OS 38 | - export PATH=$HOME/.cargo/bin:$HOME/.local/bin:$PATH 39 | - export FLAGS="" 40 | - if [ "$ARCH" != x86_64 ]; then rustup target add "$HOST"; export FLAGS="--target $HOST"; fi 41 | - rustc -vV 42 | - cargo -vV 43 | 44 | script: 45 | - cargo update 46 | - cargo build $FLAGS --all --no-default-features 47 | - cargo test $FLAGS --all --no-default-features 48 | - cargo clean 49 | - cargo build $FLAGS --all --all-features 50 | - cargo test $FLAGS --all --all-features 51 | - if [ "$TRAVIS_RUST_VERSION" = 'nightly' ]; then cargo bench --all; fi 52 | 53 | after_success: 54 | - > 55 | if [ "$TRAVIS_OS_NAME" = 'linux' ]; then 56 | cargo install cargo-kcov && 57 | ( cargo kcov --print-install-kcov-sh | bash ) && 58 | cargo kcov --coveralls -- --verify; 59 | fi 60 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "extprim" 3 | version = "1.7.1" 4 | authors = ["kennytm "] 5 | description = "Extra primitive types (u128, i128)" 6 | repository = "https://github.com/kennytm/extprim" 7 | license = "MIT/Apache-2.0" 8 | keywords = ["primitives","u128","i128"] 9 | categories = ["algorithms"] 10 | documentation = "https://docs.rs/extprim" 11 | build = "build.rs" 12 | 13 | include = [ 14 | "build.rs", 15 | "src/*.rs", 16 | "Cargo.toml", 17 | "README.md", 18 | "LICENSE*.txt", 19 | ] 20 | 21 | [badges] 22 | travis-ci = { repository = "kennytm/extprim" } 23 | appveyor = { repository = "kennytm/extprim" } 24 | is-it-maintained-issue-resolution = { repository = "kennytm/extprim" } 25 | is-it-maintained-open-issues = { repository = "kennytm/extprim" } 26 | coveralls = { repository = "kennytm/extprim" } 27 | 28 | [workspace] 29 | members = ["extprim_literals", "extprim_literals_macros", "extprim_tests"] 30 | 31 | [dependencies] 32 | # note: upgrading to rand 0.7 requires 'dyn' support i.e. rust 1.27+ 33 | rand = { version = "0.6", optional = true } 34 | num-traits = "0.2" 35 | serde = { version = "1", optional = true, features = ["derive"] } 36 | 37 | [dev-dependencies] 38 | extprim_literals = { version = "2.0", path = "./extprim_literals" } 39 | # note: pin the version of serde_derive to 1.0.98 or below, 40 | # so we don't need to depend on proc-macro2 v1.0 41 | serde_derive = ">=1.0.0,<=1.0.98" 42 | 43 | [build-dependencies] 44 | rustc_version = "0.2" 45 | semver = "0.9" 46 | 47 | [features] 48 | default = ["use-std", "rand", "serde"] 49 | use-std = [] 50 | 51 | -------------------------------------------------------------------------------- /LICENSE-APACHE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /LICENSE-MIT.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 kennytm 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | extprim 2 | ======= 3 | 4 | [![Travis (Linux and OS X) Build status](https://travis-ci.org/kennytm/extprim.svg?branch=master)](https://travis-ci.org/kennytm/extprim) 5 | [![AppVeyor (Windows) Build status](https://ci.appveyor.com/api/projects/status/59h8ugya24odwtgd/branch/master?svg=true)](https://ci.appveyor.com/project/kennytm/extprim/branch/master) 6 | [![Coverage Status](https://coveralls.io/repos/github/kennytm/extprim/badge.svg?branch=master)](https://coveralls.io/github/kennytm/extprim?branch=master) 7 | [![crates.io](http://meritbadge.herokuapp.com/extprim)](https://crates.io/crates/extprim) 8 | [![MIT / Apache 2.0](https://img.shields.io/badge/license-MIT%20%2f%20Apache%202.0-blue.svg)](./LICENSE-APACHE.txt) 9 | 10 | > *Thanks to [RFC 1504 “int128”](https://github.com/rust-lang/rfcs/blob/master/text/1504-int128.md), you can use `i128` 11 | > and `u128` directly on nightly Rust starting from 1.16. Using the built-in types are preferred.* 12 | 13 | Extra primitive types for stable Rust. Currently includes: 14 | 15 | * `u128` (unsigned 128-bit integers) 16 | * `i128` (signed 128-bit integers) 17 | 18 | [Documentation](https://docs.rs/extprim) 19 | 20 | You may also find other primitive types in other crates: 21 | 22 | * `u12` → [twelve_bit](https://crates.io/crates/twelve_bit) 23 | * `f16` → [half](https://crates.io/crates/half) 24 | * `d128` → [decimal](https://crates.io/crates/decimal) 25 | * `Complex` → [num-complex](https://crates.io/crates/num-complex) 26 | 27 | Usage 28 | ----- 29 | 30 | ```toml 31 | # Cargo.toml 32 | [dependencies] 33 | extprim = "1" 34 | ``` 35 | 36 | If you want to use the `u128!()` and `i128!()` macros, please include the `extprim_literals` plugin. 37 | 38 | ```toml 39 | # Cargo.toml 40 | [dependencies] 41 | extprim = "1" 42 | extprim_literals = "2" 43 | ``` 44 | 45 | Example 46 | ------- 47 | 48 | ```rust 49 | #[macro_use] 50 | extern crate extprim_literals; 51 | extern crate extprim; 52 | 53 | use std::str::FromStr; 54 | use extprim::i128::i128; 55 | 56 | fn main() { 57 | let a = i128::from_str("100000000000000000000000000000000000000").unwrap(); 58 | // convert string to u128 or i128 59 | let b = i128::new(10).pow(38); 60 | // 64-bit integers can be directly new'ed 61 | assert_eq!(a, b); 62 | 63 | let c = i128::from_parts(5421010862427522170, 687399551400673280); 64 | // represent using the higher- and lower-64-bit parts 65 | let d = c - a; 66 | // standard operators like +, -, *, /, %, etc. work as expected. 67 | assert_eq!(d, i128::zero()); 68 | 69 | const e: i128 = i128!(100000000000000000000000000000000000000); 70 | // use the literal macros 71 | assert_eq!(a, e); 72 | } 73 | ``` 74 | 75 | -------------------------------------------------------------------------------- /appveyor.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Please refer to https://github.com/briansmith/ring/blob/master/mk/appveyor.bat. 4 | 5 | SETLOCAL EnableDelayedExpansion 6 | SET VCVARSALL="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" 7 | 8 | ECHO Platform: %PLATFORM% 9 | 10 | IF [%PLATFORM%] NEQ [x64] GOTO Win32 11 | SET ARCH=x86_64 12 | CALL %VCVARSALL% amd64 13 | IF %ERRORLEVEL% NEQ 0 EXIT 1 14 | GOTO Download 15 | :Win32 16 | IF [%PLATFORM%] NEQ [Win32] EXIT 1 17 | SET ARCH=i686 18 | CALL %VCVARSALL% amd64_x86 19 | IF %ERRORLEVEL% NEQ 0 EXIT 1 20 | GOTO Download 21 | 22 | :Download 23 | SET RUST_DIR=%APPVEYOR_BUILD_FOLDER%\rust 24 | SET RUST_URL=https://static.rust-lang.org/dist/rust-%RUST%-%ARCH%-pc-windows-%ABI%.msi 25 | IF EXIST %RUST_DIR% ( 26 | ECHO Rust already installed in %RUST_DIR% 27 | DIR /A %RUST_DIR% 28 | ) ELSE ( 29 | ECHO Going to download Rust from %RUST_URL% and install to %RUST_DIR% 30 | MKDIR build 31 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%RUST_URL%', 'build\rust.msi')" 32 | IF %ERRORLEVEL% NEQ 0 EXIT 1 33 | 34 | START /W MSIEXEC /i build\rust.msi INSTALLDIR="%RUST_DIR%" /quiet /qn /norestart 35 | IF %ERRORLEVEL% NEQ 0 EXIT 1 36 | ) 37 | 38 | SET PATH=%RUST_DIR%\bin;%PATH% 39 | 40 | @ECHO ON 41 | 42 | LINK /HELP 43 | CL 44 | rustc --version 45 | cargo --version 46 | 47 | cargo build --all --no-default-features 48 | IF %ERRORLEVEL% NEQ 0 EXIT 1 49 | 50 | cargo test --all --no-default-features 51 | IF %ERRORLEVEL% NEQ 0 EXIT 1 52 | 53 | cargo build --all --all-features 54 | IF %ERRORLEVEL% NEQ 0 EXIT 1 55 | 56 | cargo test --all --all-features 57 | IF %ERRORLEVEL% NEQ 0 EXIT 1 58 | 59 | cargo bench --all-features 60 | IF %ERRORLEVEL% NEQ 0 EXIT 1 61 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | os: Visual Studio 2015 2 | 3 | platform: 4 | - Win32 5 | - x64 6 | 7 | branches: 8 | only: 9 | - master 10 | 11 | environment: 12 | matrix: 13 | - RUST: 1.22.1 14 | ABI: msvc 15 | - RUST: 1.22.1 16 | ABI: gnu 17 | - RUST: 1.43.1 18 | ABI: msvc 19 | - RUST: 1.43.1 20 | ABI: gnu 21 | - RUST: beta 22 | ABI: msvc 23 | - RUST: beta 24 | ABI: gnu 25 | - RUST: nightly 26 | ABI: msvc 27 | - RUST: nightly 28 | ABI: gnu 29 | 30 | cache: 31 | - rust -> appveyor.* 32 | - target -> Cargo.toml 33 | - extprim_tests\target -> **\Cargo.toml 34 | - '%USERPROFILE%\.cargo' 35 | 36 | build_script: appveyor.bat 37 | 38 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | extern crate rustc_version; 2 | extern crate semver; 3 | use rustc_version::{version_meta, Channel}; 4 | use semver::Version; 5 | 6 | pub fn main() { 7 | let version = version_meta().unwrap(); 8 | let channel = match version.channel { 9 | Channel::Dev | Channel::Nightly => "unstable", 10 | Channel::Beta | Channel::Stable => "stable", 11 | }; 12 | println!("cargo:rustc-cfg=extprim_channel=\"{}\"", channel); 13 | if version.semver >= Version::new(1, 26, 0) { 14 | println!("cargo:rustc-cfg=extprim_has_stable_i128"); 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /extprim_literals/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "extprim_literals" 3 | version = "2.0.3" 4 | authors = ["kennytm "] 5 | description = "Plugin for creating extra primitive types literals (u128!(n), i128!(n))" 6 | repository = "https://github.com/kennytm/extprim" 7 | license = "MIT/Apache-2.0" 8 | keywords = ["primitives","u128","i128"] 9 | documentation = "https://docs.rs/extprim/" 10 | 11 | include = [ 12 | "src/*.rs", 13 | "Cargo.toml", 14 | "LICENSE-*.txt", 15 | ] 16 | 17 | [dependencies] 18 | extprim_literals_macros = { path = "../extprim_literals_macros", version = "2.0" } 19 | procedural-masquerade = "0.1" 20 | 21 | [dev-dependencies] 22 | extprim = { path = "../", version = "1" } 23 | -------------------------------------------------------------------------------- /extprim_literals/LICENSE-APACHE.txt: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE.txt -------------------------------------------------------------------------------- /extprim_literals/LICENSE-MIT.txt: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT.txt -------------------------------------------------------------------------------- /extprim_literals/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Literal macros for `extprim`. 2 | //! 3 | //! This crate provides a syntex extension (on stable) so that the `extprim` types can be 4 | //! constructed at compile-time using the `i128!()` and `u128!()` macros. 5 | //! 6 | //! Setup 7 | //! ===== 8 | //! 9 | //! Simply add `extprim_literals` to dependencies in `Cargo.toml`: 10 | //! 11 | //! ```toml 12 | //! [dependencies] 13 | //! extprim_literals = "2" 14 | //! ``` 15 | //! 16 | //! Use the macros in `src/consts.rs`: 17 | //! 18 | //! ``` 19 | //! #[macro_use] 20 | //! extern crate extprim_literals; 21 | //! extern crate extprim; 22 | //! use extprim::u128::u128; 23 | //! 24 | //! const TEN: u128 = u128!(10); 25 | //! # fn main() {} 26 | //! ``` 27 | 28 | #[allow(unused_imports)] // <- why do we need this at all? 29 | #[macro_use] extern crate extprim_literals_macros; 30 | #[macro_use] extern crate procedural_masquerade; 31 | 32 | pub use extprim_literals_macros::*; 33 | 34 | define_invoke_proc_macro!(internal_extprim_literals_macros_invoke); 35 | 36 | /// Creates an unsigned 128-bit integer at compile time. The content can be any integer literals 37 | /// supported by Rust, e.g. 38 | /// 39 | /// ``` 40 | /// #[macro_use] extern crate extprim_literals; 41 | /// extern crate extprim; 42 | /// use extprim::u128::u128; 43 | /// 44 | /// # fn main() { 45 | /// u128!(190645052318211650775886739373212217031); 46 | /// u128!(290_016_114_491_568_400_953_264_683_755_668_101_244); 47 | /// u128!(0x1755_7146_02da_b606_e059_515e_7938_5189); 48 | /// u128!(0o3653247246101356646675471111622746760005231); 49 | /// u128!(0b11001001000000101100010000101110100001100110100100110110000100011110110110010111); 50 | /// # } 51 | /// ``` 52 | #[macro_export] 53 | macro_rules! u128 { 54 | ($e:tt) => { 55 | { 56 | internal_extprim_literals_macros_invoke! { 57 | internal_extprim_literals_macros_u128!($e) 58 | } 59 | VALUE 60 | } 61 | } 62 | } 63 | 64 | /// Creates a signed 128-bit integer at compile time. The content can be any integer literals 65 | /// supported by Rust, e.g. 66 | /// 67 | /// ``` 68 | /// #[macro_use] extern crate extprim_literals; 69 | /// extern crate extprim; 70 | /// use extprim::i128::i128; 71 | /// 72 | /// # fn main() { 73 | /// i128!(123623219786789911069641050508607316353); 74 | /// i128!(+1241909465635371210237387091769850650); 75 | /// i128!(-42128403654828209595896121373164578595); 76 | /// i128!(-0x34c1b7a2_2955e5bb_03cc1a88_342b9e8d); 77 | /// i128!(0o1_151760_574675_745253_103376_166404_235110_762614); 78 | /// i128!(-0b11000111001101001100001010010111110101000101011011011111101111111111110101110110); 79 | /// # } 80 | /// ``` 81 | #[macro_export] 82 | macro_rules! i128 { 83 | (+ $e:tt) => { 84 | { 85 | internal_extprim_literals_macros_invoke! { 86 | internal_extprim_literals_macros_i128!($e) 87 | } 88 | VALUE 89 | } 90 | }; 91 | (- $e:tt) => { 92 | { 93 | internal_extprim_literals_macros_invoke! { 94 | internal_extprim_literals_macros_i128!(-$e) 95 | } 96 | VALUE 97 | } 98 | }; 99 | ($e:tt) => { 100 | { 101 | internal_extprim_literals_macros_invoke! { 102 | internal_extprim_literals_macros_i128!($e) 103 | } 104 | VALUE 105 | } 106 | }; 107 | } 108 | 109 | /// Provided for backward-compatibility only. This method does nothing. 110 | #[deprecated(since="2.0.0", note="plugin registration is no longer required, and this method is no-op now")] 111 | pub fn register(_: T) {} 112 | -------------------------------------------------------------------------------- /extprim_literals_macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "extprim_literals_macros" 3 | version = "2.0.3" 4 | authors = ["kennytm "] 5 | description = "Internal crate to support `extprim_literals`. You typically don't need this crate directly." 6 | repository = "https://github.com/kennytm/extprim" 7 | license = "MIT/Apache-2.0" 8 | documentation = "https://docs.rs/extprim/" 9 | 10 | include = [ 11 | "src/*.rs", 12 | "Cargo.toml", 13 | "LICENSE-*.txt", 14 | ] 15 | 16 | [lib] 17 | name = "extprim_literals_macros" 18 | proc-macro = true 19 | 20 | [dependencies] 21 | extprim = { path = "../", version = "1" } 22 | procedural-masquerade = "0.1" 23 | -------------------------------------------------------------------------------- /extprim_literals_macros/LICENSE-APACHE.txt: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE.txt -------------------------------------------------------------------------------- /extprim_literals_macros/LICENSE-MIT.txt: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT.txt -------------------------------------------------------------------------------- /extprim_literals_macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate procedural_masquerade; 2 | extern crate proc_macro; 3 | extern crate extprim; 4 | 5 | use extprim::u128::u128; 6 | use extprim::i128::i128; 7 | use extprim::traits::parse_rust_int_lit; 8 | 9 | define_proc_macros! { 10 | pub fn internal_extprim_literals_macros_u128(input: &str) -> String { 11 | match parse_rust_int_lit::(input, false) { 12 | Ok(value) => format!(" 13 | const VALUE: ::extprim::u128::u128 = ::extprim::u128::u128 {{ 14 | lo: {0}, 15 | hi: {1}, 16 | }}; 17 | ", value.lo, value.hi), 18 | Err(e) => panic!("{}", e), 19 | } 20 | } 21 | 22 | pub fn internal_extprim_literals_macros_i128(input: &str) -> String { 23 | let mut trimmed_input = input; 24 | let is_negative = input.starts_with("-"); 25 | if is_negative { 26 | trimmed_input = input[1..].trim_left(); 27 | } 28 | match parse_rust_int_lit::(trimmed_input, is_negative) { 29 | Ok(value) => format!(" 30 | const VALUE: ::extprim::i128::i128 = ::extprim::i128::i128(::extprim::u128::u128{{ 31 | lo: {0}, 32 | hi: {1}, 33 | }}); 34 | ", value.0.lo, value.0.hi), 35 | Err(e) => panic!("{}", e), 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /extprim_tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "extprim_tests" 3 | version = "1.3.1" 4 | authors = ["kennytm "] 5 | description = "Test case for extprim literals" 6 | repository = "https://github.com/kennytm/extprim" 7 | license = "MIT/Apache-2.0" 8 | publish = false 9 | 10 | include = [ 11 | "tests/*.rs*", 12 | "Cargo.toml", 13 | ] 14 | 15 | [dev-dependencies] 16 | extprim = { path = "../", version = "1" } 17 | extprim_literals = { path = "../extprim_literals", version = "2" } 18 | -------------------------------------------------------------------------------- /extprim_tests/tests/literals.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate extprim_literals; 2 | extern crate extprim; 3 | 4 | use extprim::u128::u128; 5 | use extprim::i128::i128; 6 | 7 | use std::{i64, u64}; 8 | 9 | const U0: u128 = u128!(0); 10 | const U1: u128 = u128!(209821153008728146027079839901507889163); 11 | const U2: u128 = u128!(0x974abc531b71e0164e6a5cb291feb9b4); 12 | const U2U: u128 = u128!(0x974ABC531B71E0164E6A5CB291FEB9B4); 13 | const U3: u128 = u128!(0o1504503716555404565627130725154340050405661); 14 | const U4: u128 = u128!(0b110010111110111011100011110010011010110101101001011011100100100001000100101010010001101111101111011000111100010010111010010011); 15 | const U5: u128 = u128!(123_456_789_123_456_789_123_456_789); 16 | const U6: u128 = u128!(0x0123_4567_89ab_cdef_fdec_ba98_7654_3210); 17 | 18 | const I0: i128 = i128!(0); 19 | const I0P: i128 = i128!(+0); 20 | const I0N: i128 = i128!(-0); 21 | const I1: i128 = i128!(1); 22 | const I1P: i128 = i128!(+ 1); 23 | const I1N: i128 = i128!(- 1); 24 | const IMIN: i128 = i128!(-170141183460469231731687303715884105728); 25 | const IMAX: i128 = i128!(170141183460469231731687303715884105727); 26 | const I2: i128 = i128!(0x48e7f56608dd8c4d926f769042424b3e); 27 | const I3: i128 = i128!(-0x1c41ff3676b8022eeb2455bf0fc39bae); 28 | const I4: i128 = i128!(0o1625313102262713663604433414224157560730117); 29 | const I5: i128 = i128!(-0o1456641431070074642031455660272641534005603); 30 | const I6: i128 = i128!(-0b1011000000000000011110010110110001001111101010100110011001001111001100010101110100010011100101111110100110011000001101100011000); 31 | const I7: i128 = i128!(0b1000001011111110010001001110010001010101110001001111001010001000001011010001010110000001111100010100010011001000111101011000010); 32 | 33 | #[test] 34 | fn test_literals_u() { 35 | assert_eq!(u128::from_parts(0, 0), U0); 36 | assert_eq!(u128::from_parts(11374427496273824550, 13269521563554916363), U1); 37 | assert_eq!(u128::from_parts(10901732913132462102, 5650430604513032628), U2); 38 | assert_eq!(u128::from_parts(10901732913132462102, 5650430604513032628), U2U); 39 | assert_eq!(u128::from_parts(7535716751783851467, 10825148027977730993), U3); 40 | assert_eq!(u128::from_parts(3673733272373451666, 1236879095157042835), U4); 41 | assert_eq!(u128::from_parts(6692605, 17502027875430457109), U5); 42 | assert_eq!(u128::from_parts(0x0123_4567_89ab_cdef, 0xfdec_ba98_7654_3210), U6); 43 | } 44 | 45 | #[test] 46 | fn test_literals_i() { 47 | assert_eq!(i128::from_parts(0, 0), I0); 48 | assert_eq!(i128::from_parts(0, 0), I0P); 49 | assert_eq!(i128::from_parts(0, 0), I0N); 50 | assert_eq!(i128::from_parts(0, 1), I1); 51 | assert_eq!(i128::from_parts(0, 1), I1P); 52 | assert_eq!(i128::from_parts(-1, !0), I1N); 53 | assert_eq!(i128::from_parts(i64::MIN, 0), IMIN); 54 | assert_eq!(i128::from_parts(i64::MAX, u64::MAX), IMAX); 55 | assert_eq!(i128::from_parts(5253437308935179341, 10551782813911370558), I2); 56 | assert_eq!(i128::from_parts(-2036189115933262383, 1502982096543310930), I3); 57 | assert_eq!(i128::from_parts(8263175210112889794, 5107514375380643919), I4); 58 | assert_eq!(i128::from_parts(-7339205793792238093, 3785825598875628669), I5); 59 | assert_eq!(i128::from_parts(-6341135028387656488, 7444861624918467816), I6); 60 | assert_eq!(i128::from_parts(4719528808248670532, 1624322789729401538), I7); 61 | } 62 | 63 | // vim: ft=rust 64 | -------------------------------------------------------------------------------- /generate_assembly.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | TARGET=aarch64-apple-ios 4 | 5 | rustup run stable cargo rustc --target $TARGET --release --no-default-features -- --emit asm -C no-stack-check 6 | cat target/$TARGET/release/extprim.s | c++filt | expand -t 8 | sed 's/\$LT\$//g;s/\$C\$/,/g;s/\$u20\$/ /g;s/\$u27\$/'"'"'/g;s/\$u7b\$/{/g;s/\$u7d\$/}/g;' > lib.s 7 | 8 | -------------------------------------------------------------------------------- /src/compiler_rt.rs: -------------------------------------------------------------------------------- 1 | pub use self::detail::{udiv128, umod128, udivmod128}; 2 | 3 | #[cfg(extprim_has_stable_i128)] 4 | pub mod builtins { 5 | pub type I128 = i128; 6 | pub type U128 = u128; 7 | } 8 | 9 | #[cfg(all(target_pointer_width="64", unix))] 10 | mod detail { 11 | use u128::u128; 12 | use std::mem::uninitialized; 13 | 14 | // Prefer to use the C version if possible. Those should be more up-to-date. 15 | extern "C" { 16 | fn __udivti3(a: u128, b: u128) -> u128; 17 | fn __umodti3(a: u128, b: u128) -> u128; 18 | fn __udivmodti4(a: u128, b: u128, rem: *mut u128) -> u128; 19 | } 20 | 21 | pub fn udiv128(a: u128, b: u128) -> u128 { 22 | unsafe { __udivti3(a, b) } 23 | } 24 | 25 | pub fn umod128(a: u128, b: u128) -> u128 { 26 | unsafe { __umodti3(a, b) } 27 | } 28 | 29 | pub fn udivmod128(a: u128, b: u128) -> (u128, u128) { 30 | unsafe { 31 | let mut rem = uninitialized(); 32 | let div = __udivmodti4(a, b, &mut rem); 33 | (div, rem) 34 | } 35 | } 36 | } 37 | 38 | #[cfg(not(all(target_pointer_width="64", unix)))] 39 | mod detail { 40 | use u128::{u128, ZERO}; 41 | use std::mem::uninitialized; 42 | 43 | pub fn udiv128(a: u128, b: u128) -> u128 { 44 | udivmodti4(a, b, None) 45 | } 46 | 47 | pub fn umod128(a: u128, b: u128) -> u128 { 48 | udivmod128(a, b).1 49 | } 50 | 51 | pub fn udivmod128(a: u128, b: u128) -> (u128, u128) { 52 | let mut rem = unsafe { uninitialized() }; 53 | let div = udivmodti4(a, b, Some(&mut rem)); 54 | (div, rem) 55 | } 56 | 57 | fn udivmodti4(n: u128, d: u128, rem: Option<&mut u128>) -> u128 { 58 | // Source is based on 59 | // http://llvm.org/klaus/compiler-rt/blob/master/lib/builtins/udivmodti4.c. 60 | // compiler-rt is an LLVM project. It is licensed in MIT and UIOSL. 61 | 62 | if n < d { 63 | rem.map(|r| { *r = n; }); 64 | return ZERO; 65 | } 66 | 67 | let sr = match (n.hi, n.lo, d.hi, d.lo) { 68 | (0, x, 0, y) => { 69 | rem.map(|r| { 70 | r.hi = 0; 71 | r.lo = x % y; 72 | }); 73 | return u128::new(x / y); 74 | }, 75 | (x, 0, y, 0) => { 76 | rem.map(|r| { 77 | r.hi = x % y; 78 | r.lo = 0; 79 | }); 80 | return u128::new(x / y); 81 | }, 82 | (_, _, dh, 0) if dh.is_power_of_two() => { 83 | rem.map(|r| { 84 | r.lo = n.lo; 85 | r.hi = n.hi & (dh - 1); 86 | }); 87 | return u128::new(n.hi >> dh.trailing_zeros()); 88 | }, 89 | (_, _, 0, dl) if dl.is_power_of_two() => { 90 | rem.map(|r| { 91 | r.lo = n.lo & (dl - 1); 92 | r.hi = 0; 93 | }); 94 | return n >> dl.trailing_zeros(); 95 | } 96 | _ => { 97 | d.leading_zeros() - n.leading_zeros() + 1 98 | }, 99 | }; 100 | 101 | let mut q = n << (128 - sr); 102 | let mut r = n >> sr; 103 | let mut carry = 0; 104 | for _ in 0 .. sr { 105 | r = r << 1; 106 | r.lo |= q.hi >> 63; 107 | q = q << 1; 108 | q.lo |= carry; 109 | carry = 0; 110 | if r >= d { 111 | r = r - d; 112 | carry = 1; 113 | } 114 | } 115 | q = q << 1; 116 | q.lo |= carry; 117 | rem.map(|rp| { *rp = r; }); 118 | q 119 | } 120 | } 121 | 122 | 123 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use core::num::ParseIntError; 2 | use core::mem::transmute; 3 | 4 | pub fn invalid_digit() -> ParseIntError { 5 | unsafe { transmute(1u8) } 6 | } 7 | 8 | pub fn underflow() -> ParseIntError { 9 | unsafe { transmute(3u8) } 10 | } 11 | 12 | pub fn overflow() -> ParseIntError { 13 | unsafe { transmute(2u8) } 14 | } 15 | 16 | pub fn empty() -> ParseIntError { 17 | unsafe { transmute(0u8) } 18 | } 19 | 20 | pub fn is_overflow(e: &ParseIntError) -> bool { 21 | *e == overflow() 22 | } 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use error; 27 | 28 | #[test] 29 | fn test_local_parse_int_error_to_std() { 30 | assert_fmt_eq!("invalid digit found in string", 29, "{}", error::invalid_digit()); 31 | assert_fmt_eq!("cannot parse integer from empty string", 38, "{}", error::empty()); 32 | assert_fmt_eq!("number too large to fit in target type", 38, "{}", error::overflow()); 33 | assert_fmt_eq!("number too small to fit in target type", 38, "{}", error::underflow()); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/format_buffer.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::str::from_utf8_unchecked; 3 | 4 | /// An internal structure used to format numbers. This is not intended for general use, since 5 | /// irrelevant error checking is intentionally omitted. 6 | pub struct FormatBuffer<'a> { 7 | buffer: &'a mut [u8], 8 | len: usize, 9 | } 10 | 11 | impl<'a> FormatBuffer<'a> { 12 | pub fn new(buffer: &mut [u8]) -> FormatBuffer { 13 | FormatBuffer { 14 | buffer: buffer, 15 | len: 0, 16 | } 17 | } 18 | 19 | pub unsafe fn into_str(self) -> &'a str { 20 | from_utf8_unchecked(&self.buffer[.. self.len]) 21 | } 22 | } 23 | 24 | impl<'a> fmt::Write for FormatBuffer<'a> { 25 | fn write_str(&mut self, s: &str) -> fmt::Result { 26 | let bytes = s.as_bytes(); 27 | let new_len = self.len + bytes.len(); 28 | self.buffer[self.len .. new_len].copy_from_slice(bytes); 29 | self.len = new_len; 30 | Ok(()) 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | macro_rules! assert_fmt_eq { 36 | ($expected:expr, $max_len:expr, $($args:expr),*) => { 37 | { 38 | use ::std::fmt::Write; 39 | 40 | let mut buffer = [0u8; $max_len]; 41 | let mut buf = ::format_buffer::FormatBuffer::new(&mut buffer); 42 | write!(&mut buf, $($args),*).unwrap(); 43 | assert_eq!($expected, unsafe { buf.into_str() }); 44 | } 45 | } 46 | } 47 | 48 | #[test] 49 | fn test_format_buffer() { 50 | assert_fmt_eq!("001234", 6, "{:06}", 1234); 51 | assert_fmt_eq!("5678", 16, "{}{}{}", 5, 6, 78); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/forward.rs: -------------------------------------------------------------------------------- 1 | macro_rules! forward_symmetric { 2 | ( 3 | $(#[$cattr:meta])* 4 | impl $tn:ident($name:ident, $cname:ident, $wname:ident, $oname:ident) for $target:ty 5 | ) => { 6 | forward_symmetric!( 7 | $(#[$cattr])* 8 | impl $tn<$target>($name, $cname, $wname, $oname) for $target 9 | ); 10 | }; 11 | ( 12 | $(#[$cattr:meta])* 13 | impl $tn:ident<$arg:ty>($name:ident, $cname:ident, $wname:ident, $oname:ident) for $target:ty 14 | ) => { 15 | forward_impl! { 16 | $(#[$cattr])* 17 | impl $tn< 18 | $arg; 19 | $arg { y => y }; 20 | Wrapping<$arg> { x => x.0 } 21 | > ($name, $cname, $wname, $oname) for $target, "arithmetic operation overflowed" 22 | } 23 | } 24 | } 25 | 26 | macro_rules! forward_shift { 27 | ( 28 | $(#[$cattr:meta])* 29 | impl $tn:ident($name:ident, $cname:ident, $wname:ident, $oname:ident) for $target:ty 30 | ) => { 31 | forward_impl! { 32 | $(#[$cattr])* 33 | impl $tn< 34 | u32; 35 | u8|u16|u32|u64|usize|i8|i16|i32|i64|isize { y => y.to_u32().unwrap_or_else(|| panic!("shift operation overflowed")) }; 36 | u32 { x => x } 37 | > ($name, $cname, $wname, $oname) for $target, "shift operation overflowed" 38 | } 39 | } 40 | } 41 | 42 | macro_rules! forward_assign { 43 | ($tn:ident($name:ident, $fwd:ident) for $target:ty) => { 44 | forward_assign!($tn<$target>($name, $fwd) for $target); 45 | }; 46 | ($tn:ident<$($targ:ty)|+>($name:ident, $fwd:ident) for $target:ty) => { 47 | $(impl $tn<$targ> for $target { 48 | fn $name(&mut self, other: $targ) { 49 | *self = self.$fwd(other); 50 | } 51 | })+ 52 | } 53 | } 54 | 55 | macro_rules! forward_impl { 56 | ( 57 | $(#[$cattr:meta])* 58 | impl $tn:ident< 59 | $arg:ty; 60 | $($targ:ty)|+ { $t:pat => $uncheck_cast:expr }; 61 | $wrarg:ty { $u:pat => $unwrap:expr } 62 | > ($name:ident, $cname:ident, $wname:ident, $oname:ident) for $target:ty, 63 | $emsg:expr 64 | ) => { 65 | impl $target { 66 | $(#[$cattr])* 67 | pub fn $cname(self, other: $arg) -> Option<$target> { 68 | match self.$oname(other) { 69 | (v, false) => Some(v), 70 | (_, true) => None, 71 | } 72 | } 73 | } 74 | 75 | $(impl $tn<$targ> for $target { 76 | type Output = Self; 77 | #[cfg(debug_assertions)] 78 | #[allow(unused_comparisons, overflowing_literals)] 79 | fn $name(self, other: $targ) -> Self { 80 | let other = match other { 81 | $t => $uncheck_cast, 82 | }; 83 | self.$cname(other).unwrap_or_else(|| panic!($emsg)) 84 | } 85 | #[cfg(not(debug_assertions))] 86 | fn $name(self, other: $targ) -> Self { 87 | self.$wname(match other { $t => $uncheck_cast }) 88 | } 89 | })+ 90 | 91 | impl $tn<$wrarg> for Wrapping<$target> { 92 | type Output = Self; 93 | fn $name(self, other: $wrarg) -> Self { 94 | match other { 95 | $u => Wrapping((self.0).$wname($unwrap)) 96 | } 97 | } 98 | } 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /src/i128.rs: -------------------------------------------------------------------------------- 1 | //! Signed 128-bit integer. 2 | 3 | use std::cmp::Ordering; 4 | use std::fmt::{self, Write}; 5 | use std::iter::{Product, Sum}; 6 | use std::num::ParseIntError; 7 | use std::ops::*; 8 | use std::str::FromStr; 9 | 10 | #[cfg(feature="rand")] use rand::Rng; 11 | #[cfg(feature="rand")] use rand::distributions::{Standard, Distribution}; 12 | use num_traits::*; 13 | 14 | use error; 15 | use format_buffer::FormatBuffer; 16 | use traits::{ToExtraPrimitive, Wrapping}; 17 | use u128::u128; 18 | #[cfg(extprim_has_stable_i128)] use compiler_rt::builtins::{U128, I128}; 19 | 20 | //{{{ Structure 21 | 22 | /// Number of bits a signed 128-bit number occupies. 23 | pub const BITS: usize = 128; 24 | 25 | /// Number of bytes a signed 128-bit number occupies. 26 | pub const BYTES: usize = 16; 27 | 28 | /// The smallest signed 128-bit integer (`-170_141_183_460_469_231_731_687_303_715_884_105_728`). 29 | pub const MIN: i128 = i128(u128 { lo: 0, hi: 0x8000000000000000 }); 30 | 31 | /// The largest signed 128-bit integer (`170_141_183_460_469_231_731_687_303_715_884_105_727`). 32 | pub const MAX: i128 = i128(u128 { lo: !0, hi: 0x7fffffffffffffff }); 33 | 34 | /// The constant 0. 35 | pub const ZERO: i128 = i128(::u128::ZERO); 36 | 37 | /// The constant 1. 38 | pub const ONE: i128 = i128(::u128::ONE); 39 | 40 | /// An signed 128-bit number. 41 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 42 | #[derive(Default, Copy, Clone, Hash, PartialEq, Eq)] 43 | #[repr(C)] 44 | #[allow(non_camel_case_types)] 45 | pub struct i128( 46 | #[doc(hidden)] 47 | pub u128, 48 | ); 49 | 50 | impl i128 { 51 | /// Constructs a new 128-bit integer from a 64-bit integer. 52 | #[cfg(extprim_channel="stable")] 53 | pub fn new(lo: i64) -> i128 { 54 | i128(u128 { lo: lo as u64, hi: (lo >> 63) as u64 }) 55 | } 56 | 57 | /// Constructs a new 128-bit integer from a 64-bit integer. 58 | #[cfg(extprim_channel="unstable")] 59 | pub const fn new(lo: i64) -> i128 { 60 | i128(u128 { lo: lo as u64, hi: (lo >> 63) as u64 }) 61 | } 62 | 63 | /// Constructs a new 128-bit integer from the built-in 128-bit integer. 64 | #[cfg(extprim_has_stable_i128)] 65 | #[cfg(extprim_channel="stable")] 66 | pub fn from_built_in(value: I128) -> i128 { 67 | i128(u128::from_built_in(value as U128)) 68 | } 69 | 70 | /// Constructs a new 128-bit integer from the built-in 128-bit integer. 71 | #[cfg(extprim_has_stable_i128)] 72 | #[cfg(extprim_channel="unstable")] 73 | pub const fn from_built_in(value: I128) -> i128 { 74 | i128(u128::from_built_in(value as U128)) 75 | } 76 | 77 | /// Constructs a new 128-bit integer from the high-64-bit and low-64-bit parts. 78 | /// 79 | /// The new integer can be considered as `hi * 2**64 + lo`. 80 | /// 81 | /// ``` 82 | /// use extprim::i128::i128; 83 | /// let number = i128::from_parts(-6692605943, 4362896299872285998); 84 | /// assert_eq!(format!("{}", number), "-123456789012345678901234567890"); 85 | /// // Note: -123456789012345678901234567890 = -6692605943 << 64 | 4362896299872285998 86 | /// ``` 87 | #[cfg(extprim_channel="stable")] 88 | pub fn from_parts(hi: i64, lo: u64) -> i128 { 89 | i128(u128 { lo: lo, hi: hi as u64 }) 90 | } 91 | 92 | /// Constructs a new 128-bit integer from the high-64-bit and low-64-bit parts. 93 | /// 94 | /// The new integer can be considered as `hi * 2**64 + lo`. 95 | /// 96 | /// ``` 97 | /// use extprim::i128::i128; 98 | /// let number = i128::from_parts(-6692605943, 4362896299872285998); 99 | /// assert_eq!(format!("{}", number), "-123456789012345678901234567890"); 100 | /// // Note: -123456789012345678901234567890 = -6692605943 << 64 | 4362896299872285998 101 | /// ``` 102 | #[cfg(extprim_channel="unstable")] 103 | pub const fn from_parts(hi: i64, lo: u64) -> i128 { 104 | i128(u128 { lo: lo, hi: hi as u64 }) 105 | } 106 | 107 | /// Fetch the lower-64-bit of the number. 108 | /// 109 | /// # Examples 110 | /// 111 | /// ```rust 112 | /// use extprim::i128::i128; 113 | /// 114 | /// let number = i128::from_str_radix("-2ec6f5f523d047254447e8b26a3665", 16).unwrap(); 115 | /// assert_eq!(number.low64(), 0xdabbb8174d95c99bu64); 116 | /// ``` 117 | pub fn low64(self) -> u64 { 118 | self.0.lo 119 | } 120 | 121 | /// Fetch the higher-64-bit of the number. 122 | /// 123 | /// # Examples 124 | /// 125 | /// ```rust 126 | /// use extprim::i128::i128; 127 | /// 128 | /// let number = i128::from_str_radix("-2ec6f5f523d047254447e8b26a3665", 16).unwrap(); 129 | /// assert_eq!(number.high64(), -0x2ec6f5f523d048i64); 130 | /// ``` 131 | pub fn high64(self) -> i64 { 132 | self.0.hi as i64 133 | } 134 | 135 | /// Convert this number to unsigned with wrapping. 136 | /// 137 | /// # Examples 138 | /// 139 | /// ```rust 140 | /// use extprim::u128::u128; 141 | /// use extprim::i128::i128; 142 | /// 143 | /// let a = u128::from_str_radix( "ffd1390a0adc2fb8dabbb8174d95c99b", 16).unwrap(); 144 | /// let b = i128::from_str_radix("-002ec6f5f523d047254447e8b26a3665", 16).unwrap(); 145 | /// assert_eq!(a.as_i128(), b); 146 | /// assert_eq!(b.as_u128(), a); 147 | /// ``` 148 | pub fn as_u128(self) -> u128 { 149 | self.0 150 | } 151 | 152 | /// Converts this number to the built-in 128-bit integer type. 153 | #[cfg(extprim_has_stable_i128)] 154 | pub fn as_built_in(self) -> I128 { 155 | (self.high64() as I128) << 64 | self.low64() as I128 156 | } 157 | } 158 | 159 | #[cfg(test)] 160 | mod structure_tests { 161 | use i128::i128; 162 | use std::i64; 163 | 164 | #[test] 165 | fn test_new() { 166 | assert_eq!(i128::from_parts(0, 66), i128::new(66)); 167 | assert_eq!(i128::from_parts(-1, !65), i128::new(-66)); 168 | assert_eq!(i128::from_parts(-1, 0x8000000000000000), i128::new(i64::MIN)); 169 | } 170 | } 171 | 172 | //}}} 173 | 174 | //{{{ Rand 175 | 176 | #[cfg(feature="rand")] 177 | impl Distribution for Standard { 178 | fn sample(&self, rng: &mut R) -> i128 { 179 | i128(self.sample(rng)) 180 | } 181 | } 182 | 183 | //}}} 184 | 185 | //{{{ Add, Sub 186 | 187 | impl i128 { 188 | /// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of 189 | /// the type. 190 | /// 191 | /// # Examples 192 | /// 193 | /// ```rust 194 | /// use extprim::i128::i128; 195 | /// 196 | /// assert_eq!(i128::new(5).wrapping_add(i128::new(-6)), i128::new(-1)); 197 | /// assert_eq!(i128::max_value().wrapping_add(i128::one()), i128::min_value()); 198 | /// ``` 199 | pub fn wrapping_add(self, other: i128) -> i128 { 200 | i128(self.0.wrapping_add(other.0)) 201 | } 202 | 203 | /// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary of 204 | /// the type. 205 | /// 206 | /// # Examples 207 | /// 208 | /// ```rust 209 | /// use extprim::i128::i128; 210 | /// 211 | /// assert_eq!(i128::new(6).wrapping_sub(i128::new(13)), i128::new(-7)); 212 | /// assert_eq!(i128::min_value().wrapping_sub(i128::one()), i128::max_value()); 213 | /// ``` 214 | pub fn wrapping_sub(self, other: i128) -> i128 { 215 | i128(self.0.wrapping_sub(other.0)) 216 | } 217 | 218 | /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary of the type. 219 | /// 220 | /// The only case where such wrapping can occur is when one negates MIN on a signed type (where 221 | /// MIN is the negative minimal value for the type); this is a positive value that is too large 222 | /// to represent in the type. In such a case, this function returns MIN itself. 223 | /// 224 | /// # Examples 225 | /// 226 | /// ```rust 227 | /// use extprim::i128::i128; 228 | /// 229 | /// assert_eq!(i128::new(7).wrapping_neg(), i128::new(-7)); 230 | /// assert_eq!(i128::min_value().wrapping_neg(), i128::min_value()); 231 | /// ``` 232 | pub fn wrapping_neg(self) -> i128 { 233 | i128(self.0.wrapping_neg()) 234 | } 235 | 236 | /// Calculates `self + other`. 237 | /// 238 | /// Returns a tuple of the addition along with a boolean indicating whether an arithmetic 239 | /// overflow would occur. If an overflow would have occurred then the wrapped value is 240 | /// returned. 241 | /// 242 | /// # Examples 243 | /// 244 | /// ```rust 245 | /// use extprim::i128::i128; 246 | /// 247 | /// assert_eq!(i128::new(6).overflowing_add(i128::new(13)), (i128::new(19), false)); 248 | /// assert_eq!(i128::max_value().overflowing_add(i128::one()), (i128::min_value(), true)); 249 | /// ``` 250 | pub fn overflowing_add(self, other: i128) -> (i128, bool) { 251 | let left_sign = self.is_negative(); 252 | let right_sign = other.is_negative(); 253 | let res = self.wrapping_add(other); 254 | let res_sign = res.is_negative(); 255 | (res, left_sign == right_sign && res_sign != left_sign) 256 | } 257 | 258 | /// Calculates `self - other`. 259 | /// 260 | /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic 261 | /// overflow would occur. If an overflow would have occurred then the wrapped value is 262 | /// returned. 263 | /// 264 | /// # Examples 265 | /// 266 | /// ```rust 267 | /// use extprim::i128::i128; 268 | /// 269 | /// assert_eq!(i128::new(3).overflowing_sub(i128::new(8)), (i128::new(-5), false)); 270 | /// assert_eq!(i128::min_value().overflowing_sub(i128::max_value()), (i128::one(), true)); 271 | /// ``` 272 | pub fn overflowing_sub(self, other: i128) -> (i128, bool) { 273 | let left_sign = self.is_negative(); 274 | let right_sign = other.is_negative(); 275 | let res = self.wrapping_sub(other); 276 | let res_sign = res.is_negative(); 277 | (res, left_sign != right_sign && res_sign != left_sign) 278 | } 279 | 280 | /// Negates `self`, overflowing if this is equal to the minimum value. 281 | /// 282 | /// Returns a tuple of the negated version of self along with a boolean indicating whether an 283 | /// overflow happened. If self is the minimum value (`i128::MIN`), then the minimum value will 284 | /// be returned again and true will be returned for an overflow happening. 285 | /// 286 | /// # Examples 287 | /// 288 | /// ```rust 289 | /// use extprim::i128::i128; 290 | /// 291 | /// assert_eq!(i128::new(7).overflowing_neg(), (i128::new(-7), false)); 292 | /// assert_eq!(i128::min_value().overflowing_neg(), (i128::min_value(), true)); 293 | /// ``` 294 | pub fn overflowing_neg(self) -> (i128, bool) { 295 | (self.wrapping_neg(), self == MIN) 296 | } 297 | 298 | /// Checked negation. Computes `-self`, returning `None` if `self == MIN`. 299 | /// 300 | /// # Examples 301 | /// 302 | /// ```rust 303 | /// use extprim::i128::i128; 304 | /// 305 | /// assert_eq!(i128::new(7).checked_neg(), Some(i128::new(-7))); 306 | /// assert_eq!(i128::min_value().checked_neg(), None); 307 | /// ``` 308 | pub fn checked_neg(self) -> Option { 309 | match self.overflowing_neg() { 310 | (v, false) => Some(v), 311 | (_, true) => None, 312 | } 313 | } 314 | 315 | /// Saturating integer addition. Computes `self + other`, saturating at the numeric bounds 316 | /// instead of overflowing. 317 | /// 318 | /// # Examples 319 | /// 320 | /// ```rust 321 | /// use extprim::i128::i128; 322 | /// 323 | /// assert_eq!(i128::new(6).saturating_add(i128::new(13)), i128::new(19)); 324 | /// assert_eq!(i128::max_value().saturating_add(i128::new(2)), i128::max_value()); 325 | /// assert_eq!(i128::min_value().saturating_add(i128::new(-2)), i128::min_value()); 326 | /// ``` 327 | pub fn saturating_add(self, other: i128) -> i128 { 328 | self.checked_add(other) 329 | .unwrap_or_else(|| if other.is_negative() { MIN } else { MAX }) 330 | } 331 | 332 | /// Saturating integer subtraction. Computes `self - other`, saturating at the numeric bounds 333 | /// instead of overflowing. 334 | /// 335 | /// # Examples 336 | /// 337 | /// ```rust 338 | /// use extprim::i128::i128; 339 | /// 340 | /// assert_eq!(i128::new(3).saturating_sub(i128::new(8)), i128::new(-5)); 341 | /// assert_eq!(i128::max_value().saturating_sub(i128::new(-2)), i128::max_value()); 342 | /// assert_eq!(i128::min_value().saturating_sub(i128::new(2)), i128::min_value()); 343 | /// ``` 344 | pub fn saturating_sub(self, other: i128) -> i128 { 345 | self.checked_sub(other) 346 | .unwrap_or_else(|| if other.is_negative() { MAX } else { MIN }) 347 | } 348 | 349 | /// Saturating integer negation. Computes `-self`, saturating at numeric bounds instead of 350 | /// overflowing. 351 | /// 352 | /// # Examples 353 | /// 354 | /// ```rust 355 | /// use extprim::i128::i128; 356 | /// 357 | /// assert_eq!(i128::new(7).saturating_neg(), i128::new(-7)); 358 | /// assert_eq!(i128::min_value().saturating_neg(), i128::max_value()); 359 | /// assert_eq!(i128::max_value().saturating_neg(), i128::min_value() + i128::one()); 360 | /// ``` 361 | pub fn saturating_neg(self) -> i128 { 362 | self.checked_neg().unwrap_or(MAX) 363 | } 364 | } 365 | 366 | forward_symmetric! { 367 | /// Checked integer addition. Computes `self + other`, returning `None` if overflow occurred. 368 | /// 369 | /// # Examples 370 | /// 371 | /// ```rust 372 | /// use extprim::i128::i128; 373 | /// 374 | /// assert_eq!(i128::new(5).checked_add(i128::new(-6)), Some(i128::new(-1))); 375 | /// assert_eq!(i128::max_value().checked_add(i128::one()), None); 376 | /// ``` 377 | impl Add(add, checked_add, wrapping_add, overflowing_add) for i128 378 | } 379 | forward_symmetric! { 380 | /// Checked integer subtraction. Computes `self - other`, returning `None` if underflow 381 | /// occurred. 382 | /// 383 | /// # Examples 384 | /// 385 | /// ```rust 386 | /// use extprim::i128::i128; 387 | /// 388 | /// assert_eq!(i128::new(6).checked_sub(i128::new(13)), Some(i128::new(-7))); 389 | /// assert_eq!(i128::min_value().checked_sub(i128::one()), None); 390 | /// ``` 391 | impl Sub(sub, checked_sub, wrapping_sub, overflowing_sub) for i128 392 | } 393 | forward_assign!(AddAssign(add_assign, add) for i128); 394 | forward_assign!(SubAssign(sub_assign, sub) for i128); 395 | 396 | impl Neg for i128 { 397 | type Output = Self; 398 | fn neg(self) -> Self { 399 | self.checked_neg().unwrap_or_else(|| panic!("arithmetic operation overflowed")) 400 | } 401 | } 402 | 403 | impl Neg for Wrapping { 404 | type Output = Self; 405 | fn neg(self) -> Self { 406 | Wrapping(self.0.wrapping_neg()) 407 | } 408 | } 409 | 410 | impl CheckedAdd for i128 { 411 | fn checked_add(&self, other: &Self) -> Option { 412 | Self::checked_add(*self, *other) 413 | } 414 | } 415 | 416 | impl CheckedSub for i128 { 417 | fn checked_sub(&self, other: &Self) -> Option { 418 | Self::checked_sub(*self, *other) 419 | } 420 | } 421 | 422 | impl Saturating for i128 { 423 | fn saturating_add(self, other: Self) -> Self { 424 | Self::saturating_add(self, other) 425 | } 426 | 427 | fn saturating_sub(self, other: Self) -> Self { 428 | Self::saturating_add(self, other) 429 | } 430 | } 431 | 432 | #[cfg(test)] 433 | mod add_sub_tests { 434 | use i128::{i128, ONE, MAX, MIN}; 435 | 436 | #[test] 437 | fn test_add() { 438 | assert_eq!(i128::from_parts(23, 12) + i128::from_parts(78, 45), 439 | i128::from_parts(101, 57)); 440 | assert_eq!(i128::from_parts(-0x0151b4d672066e52, 0x21b6c7c3766908a7) + 441 | i128::from_parts(0x08a45eef16781327, 0xff1049ddf49ff8a8), 442 | i128::from_parts(0x0752aa18a471a4d6, 0x20c711a16b09014f)); 443 | } 444 | 445 | #[test] 446 | #[should_panic(expected="arithmetic operation overflowed")] 447 | fn test_add_overflow_above() { 448 | let _ = MAX + ONE; 449 | } 450 | 451 | #[test] 452 | #[should_panic(expected="arithmetic operation overflowed")] 453 | fn test_add_overflow_below() { 454 | let _ = MIN + i128::from_parts(-1, !0); 455 | } 456 | 457 | #[test] 458 | fn test_sub() { 459 | assert_eq!(i128::from_parts(78, 45) - i128::from_parts(23, 12), 460 | i128::from_parts(55, 33)); 461 | assert_eq!(i128::from_parts(23, 12) - i128::from_parts(78, 45), 462 | i128::from_parts(-56, !32)); 463 | assert_eq!(i128::from_parts(-0x0151b4d672066e52, 0x21b6c7c3766908a7) - 464 | i128::from_parts(0x08a45eef16781327, 0xff1049ddf49ff8a8), 465 | i128::from_parts(-0x09f613c5887e817a, 0x22a67de581c90fff)); 466 | assert_eq!(i128::from_parts(3565142335064920496, 15687467940602204387) - 467 | i128::from_parts(4442421226426414073, 17275749316209243331), 468 | i128::from_parts(-877278891361493578, 16858462698102512672)); 469 | } 470 | 471 | #[test] 472 | #[should_panic(expected="arithmetic operation overflowed")] 473 | fn test_sub_overflow_above() { 474 | let _ = MAX - i128::from_parts(-1, !0); 475 | } 476 | 477 | #[test] 478 | #[should_panic(expected="arithmetic operation overflowed")] 479 | fn test_sub_overflow_below() { 480 | let _ = MIN - ONE; 481 | } 482 | 483 | #[test] 484 | #[should_panic(expected="arithmetic operation overflowed")] 485 | fn test_neg_min() { 486 | let _ = -MIN; 487 | } 488 | 489 | #[test] 490 | fn test_neg() { 491 | let neg1 = i128::from_parts(-1, !0); 492 | assert_eq!(neg1, -ONE); 493 | assert_eq!(ONE, -neg1); 494 | 495 | assert_eq!(MIN.wrapping_neg(), MIN); 496 | assert_eq!(MIN.overflowing_neg(), (MIN, true)); 497 | assert_eq!(MIN.saturating_neg(), MAX); 498 | assert_eq!(MIN.checked_neg(), None); 499 | } 500 | } 501 | 502 | //}}} 503 | 504 | //{{{ PartialOrd, Ord 505 | 506 | impl PartialOrd for i128 { 507 | fn partial_cmp(&self, other: &i128) -> Option { 508 | Some(self.cmp(other)) 509 | } 510 | } 511 | 512 | impl Ord for i128 { 513 | fn cmp(&self, other: &i128) -> Ordering { 514 | (self.high64(), self.low64()).cmp(&(other.high64(), other.low64())) 515 | } 516 | } 517 | 518 | #[cfg(test)] 519 | mod cmp_tests { 520 | use i128::{i128, MIN, MAX}; 521 | use u128::u128; 522 | 523 | const TEST_CASES: &'static [i128; 7] = &[ 524 | MIN, 525 | i128(u128 { lo: 0, hi: !0 }), 526 | i128(u128 { lo: !0, hi: !0 }), 527 | i128(u128 { lo: 0, hi: 0 }), 528 | i128(u128 { lo: 1, hi: 0 }), 529 | i128(u128 { lo: 0, hi: 1 }), 530 | MAX 531 | ]; 532 | 533 | #[test] 534 | fn test_ord() { 535 | for (i, a) in TEST_CASES.iter().enumerate() { 536 | for (j, b) in TEST_CASES.iter().enumerate() { 537 | assert_eq!(i.cmp(&j), a.cmp(b)); 538 | } 539 | } 540 | } 541 | } 542 | 543 | //}}} 544 | 545 | //{{{ Not, BitAnd, BitOr, BitXor 546 | 547 | impl Not for i128 { 548 | type Output = Self; 549 | fn not(self) -> Self { 550 | i128(!self.0) 551 | } 552 | } 553 | 554 | impl BitAnd for i128 { 555 | type Output = Self; 556 | fn bitand(self, other: Self) -> Self { 557 | i128(self.0 & other.0) 558 | } 559 | } 560 | 561 | impl BitOr for i128 { 562 | type Output = Self; 563 | fn bitor(self, other: Self) -> Self { 564 | i128(self.0 | other.0) 565 | } 566 | } 567 | 568 | impl BitXor for i128 { 569 | type Output = Self; 570 | fn bitxor(self, other: Self) -> Self { 571 | i128(self.0 ^ other.0) 572 | } 573 | } 574 | 575 | impl Not for Wrapping { 576 | type Output = Self; 577 | fn not(self) -> Self { 578 | Wrapping(!self.0) 579 | } 580 | } 581 | 582 | impl BitAnd for Wrapping { 583 | type Output = Self; 584 | fn bitand(self, other: Self) -> Self { 585 | Wrapping(self.0 & other.0) 586 | } 587 | } 588 | 589 | impl BitOr for Wrapping { 590 | type Output = Self; 591 | fn bitor(self, other: Self) -> Self { 592 | Wrapping(self.0 | other.0) 593 | } 594 | } 595 | 596 | impl BitXor for Wrapping { 597 | type Output = Self; 598 | fn bitxor(self, other: Self) -> Self { 599 | Wrapping(self.0 ^ other.0) 600 | } 601 | } 602 | 603 | forward_assign!(BitAndAssign(bitand_assign, bitand) for i128); 604 | forward_assign!(BitOrAssign(bitor_assign, bitor) for i128); 605 | forward_assign!(BitXorAssign(bitxor_assign, bitxor) for i128); 606 | 607 | #[cfg(test)] 608 | mod bitwise_tests { 609 | use i128::i128; 610 | 611 | #[test] 612 | fn test_not() { 613 | assert_eq!(i128::from_parts(0x491d3b2d80d706a6, 0x1eb41c5d2ad1a379), 614 | !i128::from_parts(-0x491d3b2d80d706a7, 0xe14be3a2d52e5c86)); 615 | } 616 | 617 | #[test] 618 | fn test_bit_and() { 619 | assert_eq!(i128::from_parts(-0x75007aa6237d556f, 0x8bbf525fb0c5cd79) & 620 | i128::from_parts(-0x7231336af452490f, 0xb26ab6ca714bce40), 621 | i128::from_parts(-0x77317beef77f5d6f, 0x822a124a3041cc40)); 622 | } 623 | 624 | #[test] 625 | fn test_bit_or() { 626 | assert_eq!(i128::from_parts(-0x1c481f51e1707415, 0x5c76dd080dd43e30) | 627 | i128::from_parts(0x35591b16599e2ece, 0x2e2957ca426d7b07), 628 | i128::from_parts(-0x8000441a0605011, 0x7e7fdfca4ffd7f37)); 629 | } 630 | 631 | #[test] 632 | fn test_bit_xor() { 633 | assert_eq!(i128::from_parts(0x50b17617e8f6ee49, 0x1b06f037a9187c71) ^ 634 | i128::from_parts(0x206f313ea29823bd, 0x66e0bc7aa198785a), 635 | i128::from_parts(0x70de47294a6ecdf4, 0x7de64c4d0880042b)); 636 | } 637 | } 638 | 639 | //}}} 640 | 641 | //{{{ Shl, Shr 642 | 643 | impl i128 { 644 | /// Panic-free bitwise shift-left; yields `self << (shift % 128)`. 645 | /// 646 | /// Note that this is not the same as a rotate-left; the RHS of a wrapping shift-left is 647 | /// restricted to the range of the type, rather than the bits shifted out of the LHS being 648 | /// returned to the other end. The primitive integer types all implement a `rotate_left` 649 | /// function, which may be what you want instead. 650 | /// 651 | /// # Examples 652 | /// 653 | /// ```rust 654 | /// use extprim::i128::i128; 655 | /// 656 | /// assert_eq!(i128::new(1).wrapping_shl(127), i128::min_value()); 657 | /// assert_eq!(i128::new(19).wrapping_shl(256), i128::new(19)); 658 | /// ``` 659 | pub fn wrapping_shl(self, shift: u32) -> i128 { 660 | i128(self.0.wrapping_shl(shift)) 661 | } 662 | 663 | /// Panic-free bitwise shift-right; yields `self >> (shift % 128). 664 | /// 665 | /// Note that this is not the same as a rotate-right; the RHS of a wrapping shift-right is 666 | /// restricted to the range of the type, rather than the bits shifted out of the LHS being 667 | /// returned to the other end. The primitive integer types all implement a `rotate_right` 668 | /// function, which may be what you want instead. 669 | /// 670 | /// # Examples 671 | /// 672 | /// ```rust 673 | /// use extprim::i128::i128; 674 | /// 675 | /// assert_eq!(i128::new(-50).wrapping_shr(2), i128::new(-13)); 676 | /// assert_eq!(i128::new(19).wrapping_shr(257), i128::new(9)); 677 | /// ``` 678 | pub fn wrapping_shr(self, shift: u32) -> i128 { 679 | let hi = self.high64(); 680 | let lo = self.low64(); 681 | 682 | let (hi, lo) = if (shift & 64) != 0 { 683 | (hi >> 63, (hi >> (shift & 63)) as u64) 684 | } else { 685 | let new_hi = hi.wrapping_shr(shift); 686 | let mut new_lo = lo.wrapping_shr(shift); 687 | if (shift & 127) != 0 { 688 | new_lo |= (hi as u64).wrapping_shl(64u32.wrapping_sub(shift)); 689 | } 690 | (new_hi, new_lo) 691 | }; 692 | 693 | i128::from_parts(hi, lo) 694 | } 695 | 696 | /// Shifts `self` left by `other` bits. 697 | /// 698 | /// Returns a tuple of the shifted version of self along with a boolean indicating whether the 699 | /// shift value was larger than or equal to the number of bits. If the shift value is too 700 | /// large, then value is masked by `0x7f`, and this value is then used to perform the shift. 701 | /// 702 | /// # Examples 703 | /// 704 | /// ```rust 705 | /// use extprim::i128::i128; 706 | /// 707 | /// assert_eq!(i128::new(1).overflowing_shl(127), (i128::min_value(), false)); 708 | /// assert_eq!(i128::new(19).overflowing_shl(256), (i128::new(19), true)); 709 | /// ``` 710 | pub fn overflowing_shl(self, other: u32) -> (i128, bool) { 711 | (self.wrapping_shl(other), other >= 128) 712 | } 713 | 714 | /// Shifts `self` right by `other` bits. 715 | /// 716 | /// Returns a tuple of the shifted version of self along with a boolean indicating whether the 717 | /// shift value was larger than or equal to the number of bits. If the shift value is too 718 | /// large, then value is masked by `0x7f`, and this value is then used to perform the shift. 719 | /// 720 | /// # Examples 721 | /// 722 | /// ```rust 723 | /// use extprim::i128::i128; 724 | /// 725 | /// assert_eq!(i128::new(-50).overflowing_shr(2), (i128::new(-13), false)); 726 | /// assert_eq!(i128::new(19).overflowing_shr(257), (i128::new(9), true)); 727 | /// ``` 728 | pub fn overflowing_shr(self, other: u32) -> (i128, bool) { 729 | (self.wrapping_shr(other), other >= 128) 730 | } 731 | } 732 | 733 | forward_shift!( 734 | /// Checked shift left. Computes `self << other`, returning `None` if rhs is larger than or 735 | /// equal to the number of bits in `self` (128). 736 | /// 737 | /// # Examples 738 | /// 739 | /// ```rust 740 | /// use extprim::i128::i128; 741 | /// 742 | /// assert_eq!(i128::new(1).checked_shl(127), Some(i128::min_value())); 743 | /// assert_eq!(i128::new(19).checked_shl(256), None); 744 | /// ``` 745 | impl Shl(shl, checked_shl, wrapping_shl, overflowing_shl) for i128 746 | ); 747 | forward_shift!( 748 | /// Checked shift right. Computes `self >> other`, returning `None` if the shift is larger than 749 | /// or equal to the number of bits in `self` (128). 750 | /// 751 | /// # Examples 752 | /// 753 | /// ```rust 754 | /// use extprim::i128::i128; 755 | /// 756 | /// assert_eq!(i128::new(-50).checked_shr(2), Some(i128::new(-13))); 757 | /// assert_eq!(i128::new(19).checked_shr(257), None); 758 | /// ``` 759 | impl Shr(shr, checked_shr, wrapping_shr, overflowing_shr) for i128 760 | ); 761 | forward_assign!(ShlAssign(shl_assign, shl) for i128); 762 | forward_assign!(ShrAssign(shr_assign, shr) for i128); 763 | 764 | #[cfg(test)] 765 | mod shift_tests { 766 | use i128::i128; 767 | 768 | #[test] 769 | fn test_shl() { 770 | assert_eq!(i128::from_parts(0x1e5c7801b0e575f7, 0x53f09dac5b28f152) << 0, 771 | i128::from_parts(0x1e5c7801b0e575f7, 0x53f09dac5b28f152)); 772 | assert_eq!(i128::from_parts(0x1e5c7801b0e575f7, 0x53f09dac5b28f152) << 1, 773 | i128::from_parts(0x3cb8f00361caebee, 0xa7e13b58b651e2a4)); 774 | assert_eq!(i128::from_parts(0x1e5c7801b0e575f7, 0x53f09dac5b28f152) << 64, 775 | i128::from_parts(0x53f09dac5b28f152, 0x0)); 776 | assert_eq!(i128::from_parts(0x1e5c7801b0e575f7, 0x53f09dac5b28f152) << 120, 777 | i128::from_parts(0x5200000000000000, 0x0)); 778 | 779 | assert_eq!(i128::from_parts(-0x7fdac9c2232ae28, 0x509d78e4a3008bcd) << 0, 780 | i128::from_parts(-0x7fdac9c2232ae28, 0x509d78e4a3008bcd)); 781 | assert_eq!(i128::from_parts(-0x7fdac9c2232ae28, 0x509d78e4a3008bcd) << 1, 782 | i128::from_parts(-0xffb593844655c50, 0xa13af1c94601179a)); 783 | assert_eq!(i128::from_parts(-0x7fdac9c2232ae28, 0x509d78e4a3008bcd) << 64, 784 | i128::from_parts(0x509d78e4a3008bcd, 0x0)); 785 | assert_eq!(i128::from_parts(-0x7fdac9c2232ae28, 0x509d78e4a3008bcd) << 120, 786 | i128::from_parts(-0x3300000000000000, 0x0)); 787 | } 788 | 789 | #[test] 790 | fn test_shr() { 791 | assert_eq!(i128::from_parts(0x1e5c7801b0e575f7, 0x53f09dac5b28f152) >> 0, 792 | i128::from_parts(0x1e5c7801b0e575f7, 0x53f09dac5b28f152)); 793 | assert_eq!(i128::from_parts(0x1e5c7801b0e575f7, 0x53f09dac5b28f152) >> 1, 794 | i128::from_parts(0x0f2e3c00d872bafb, 0xa9f84ed62d9478a9)); 795 | assert_eq!(i128::from_parts(0x1e5c7801b0e575f7, 0x53f09dac5b28f152) >> 64, 796 | i128::from_parts(0x0, 0x1e5c7801b0e575f7)); 797 | assert_eq!(i128::from_parts(0x1e5c7801b0e575f7, 0x53f09dac5b28f152) >> 120, 798 | i128::from_parts(0x0, 0x1e)); 799 | 800 | assert_eq!(i128::from_parts(-0x7fdac9c2232ae28, 0x509d78e4a3008bcd) >> 0, 801 | i128::from_parts(-0x7fdac9c2232ae28, 0x509d78e4a3008bcd)); 802 | assert_eq!(i128::from_parts(-0x7fdac9c2232ae28, 0x509d78e4a3008bcd) >> 1, 803 | i128::from_parts(-0x3fed64e11195714, 0x284ebc72518045e6)); 804 | assert_eq!(i128::from_parts(-0x7fdac9c2232ae28, 0x509d78e4a3008bcd) >> 64, 805 | i128::from_parts(-1, 0xf8025363ddcd51d8)); 806 | assert_eq!(i128::from_parts(-0x7fdac9c2232ae28, 0x509d78e4a3008bcd) >> 120, 807 | i128::from_parts(-1, 0xfffffffffffffff8)); 808 | } 809 | } 810 | 811 | #[cfg(all(test, extprim_channel="unstable"))] 812 | mod shift_bench { 813 | use i128::i128; 814 | use test::{Bencher, black_box}; 815 | 816 | // randomize shift range to avoid possible branch prediction effect. 817 | const BENCH_SHIFTS: &'static [u32] = &[ 818 | 77, 45, 57, 7, 34, 75, 38, 89, 89, 66, 16, 111, 66, 123, 14, 80, 94, 43, 819 | 46, 86, 121, 31, 123, 33, 23, 57, 50, 28, 26, 46, 8, 88, 74, 55, 108, 820 | 127, 1, 70, 73, 2, 1, 45, 36, 96, 124, 124, 91, 63, 25, 94, 8, 68, 41, 821 | 127, 107, 10, 111, 98, 97, 72, 78, 10, 125, 17, 62, 3, 65, 67, 13, 41, 822 | 68, 109, 23, 100, 98, 16, 78, 13, 0, 63, 107, 64, 13, 23, 69, 73, 2, 38, 823 | 16, 9, 124, 120, 39, 119, 3, 15, 25, 11, 84, 102, 69, 58, 39, 116, 66, 824 | 87, 111, 17, 11, 29, 35, 123, 23, 38, 43, 85, 32, 7, 34, 84, 27, 35, 825 | 122, 64, 33, 83, 78, 105, 31, 5, 58, 25, 21, 34, 15, 94, 10, 23, 48, 89, 826 | 23, 99, 110, 105, 32, 7, 116, 31, 10, 14, 22, 84, 40, 57, 7, 35, 8, 95, 827 | 121, 66, 95, 103, 26, 62, 24, 36, 48, 58, 122, 66, 37, 56, 35, 87, 36, 828 | 41, 75, 37, 25, 40, 60, 39, 94, 18, 33, 113, 34, 66, 34, 34, 88, 95, 81, 829 | 115, 10, 67, 33, 34, 23, 53, 10, 119, 54, 107, 37, 17, 85, 42, 83, 85, 830 | 102, 104, 94, 24, 97, 104, 93, 9, 95, 75, 41, 112, 64, 63, 72, 3, 26, 831 | 65, 103, 88, 121, 105, 98, 82, 89, 30, 37, 64, 68, 41, 93, 57, 105, 100, 832 | 108, 102, 44, 17, 61, 72, 33, 126, 73, 105, 0, 119, 97, 28, 9, 101, 44, 833 | ]; 834 | 835 | #[bench] 836 | fn bench_shr(bencher: &mut Bencher) { 837 | let number = i128::from_parts(-8704825901651121218, 3937562729638942691); 838 | bencher.iter(|| { 839 | for i in BENCH_SHIFTS { 840 | black_box(number.wrapping_shr(*i)); 841 | } 842 | }); 843 | } 844 | } 845 | 846 | //}}} 847 | 848 | //{{{ Mul 849 | 850 | /// Converts a signed integer `x` into the sign (whether it is negative) and the absolute value 851 | /// `|x|`. 852 | fn sign_abs(x: i128) -> (bool, u128) { 853 | if x.is_negative() { 854 | (true, x.0.wrapping_neg()) 855 | } else { 856 | (false, x.0) 857 | } 858 | } 859 | 860 | /// Reassembles a sign and absolute value back to a signed integer. 861 | fn from_sign_abs(sign: bool, abs: u128) -> i128 { 862 | i128(if sign { abs.wrapping_neg() } else { abs }) 863 | } 864 | 865 | impl i128 { 866 | /// Calculates the multiplication of `self` and `other`. 867 | /// 868 | /// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic 869 | /// overflow would occur. If an overflow would have occurred then the wrapped value is returned. 870 | /// 871 | /// # Examples 872 | /// 873 | /// ```rust 874 | /// use extprim::i128::i128; 875 | /// 876 | /// assert_eq!(i128::new(-6).overflowing_mul(i128::new(11)), (i128::new(-66), false)); 877 | /// 878 | /// let a = i128::from_parts(3, 1); 879 | /// let b = i128::from_parts(-1, 3); 880 | /// assert_eq!(a.overflowing_mul(b), (i128::from_parts(8, 3), true)); 881 | /// ``` 882 | pub fn overflowing_mul(self, other: i128) -> (i128, bool) { 883 | if self == ZERO || other == ZERO { 884 | return (ZERO, false); 885 | } 886 | 887 | let (sa, a) = sign_abs(self); 888 | let (sb, b) = sign_abs(other); 889 | let res_is_neg = sa != sb; 890 | 891 | let (res, res_overflow) = a.overflowing_mul(b); 892 | let res = from_sign_abs(res_is_neg, res); 893 | (res, res_overflow || res.is_negative() != res_is_neg) 894 | } 895 | 896 | /// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary 897 | /// of the type. 898 | /// 899 | /// # Examples 900 | /// 901 | /// ```rust 902 | /// use extprim::i128::i128; 903 | /// 904 | /// assert_eq!(i128::new(-6).wrapping_mul(i128::new(11)), i128::new(-66)); 905 | /// 906 | /// let a = i128::from_parts(3, 1); 907 | /// let b = i128::from_parts(-1, 3); 908 | /// assert_eq!(a.wrapping_mul(b), i128::from_parts(8, 3)); 909 | /// ``` 910 | pub fn wrapping_mul(self, other: i128) -> i128 { 911 | i128(self.0.wrapping_mul(other.0)) 912 | } 913 | 914 | /// Saturating integer multiplication. Computes `self * other`, saturating at the numeric 915 | /// bounds instead of overflowing. 916 | /// 917 | /// # Examples 918 | /// 919 | /// ```rust 920 | /// use extprim::i128::i128; 921 | /// 922 | /// assert_eq!(i128::new(-6).saturating_mul(i128::new(11)), i128::new(-66)); 923 | /// 924 | /// let a = i128::from_parts(3, 1); 925 | /// let b = i128::from_parts(-1, 3); 926 | /// assert_eq!(a.saturating_mul(b), i128::min_value()); 927 | /// ``` 928 | pub fn saturating_mul(self, other: i128) -> i128 { 929 | self.checked_mul(other).unwrap_or_else(|| { 930 | if self.is_negative() == other.is_negative() { MAX } else { MIN } 931 | }) 932 | } 933 | } 934 | 935 | forward_symmetric! { 936 | /// Checked integer multiplication. Computes `self * other`, returning `None` if underflow or 937 | /// overflow occurred. 938 | /// 939 | /// # Examples 940 | /// 941 | /// ```rust 942 | /// use extprim::i128::i128; 943 | /// 944 | /// assert_eq!(i128::new(-6).checked_mul(i128::new(11)), Some(i128::new(-66))); 945 | /// 946 | /// let a = i128::from_parts(3, 1); 947 | /// let b = i128::from_parts(-1, 3); 948 | /// assert_eq!(a.checked_mul(b), None); 949 | /// ``` 950 | impl Mul(mul, checked_mul, wrapping_mul, overflowing_mul) for i128 951 | } 952 | forward_assign!(MulAssign(mul_assign, mul) for i128); 953 | 954 | impl CheckedMul for i128 { 955 | fn checked_mul(&self, other: &Self) -> Option { 956 | Self::checked_mul(*self, *other) 957 | } 958 | } 959 | 960 | #[cfg(test)] 961 | mod mul_tests { 962 | use i128::{i128, ONE, MAX, MIN}; 963 | 964 | #[test] 965 | fn test_mul() { 966 | assert_eq!(i128::new(6263979403966582069) * i128::new(2263184174907185431), 967 | i128::from_parts(0xaaa4d56f5b2f577, 0x916fb81166049cc3)); 968 | assert_eq!(ONE * ONE, ONE); 969 | assert_eq!(ONE * MAX, MAX); 970 | assert_eq!(MIN * ONE, MIN); 971 | assert_eq!(i128::new(-4) * i128::new(-9), i128::new(36)); 972 | assert_eq!(i128::new(-7) * i128::new(3), i128::new(-21)); 973 | assert_eq!(i128::from_parts(1, 1) * i128::new(-9), i128::from_parts(-10, !8)); 974 | assert_eq!(i128::from_parts(0x4000_0000_0000_0000, 0) * i128::new(-2), MIN); 975 | } 976 | 977 | #[test] 978 | fn test_wrapping_overflowing_mul() { 979 | let a = i128::from_parts(-6140994497999405230, 2270645839074617067); 980 | let b = i128::from_parts(8696394550295834000, 13800979035109902541); 981 | let c = i128::from_parts(-6771355848177145191, 5110157532910617135); 982 | 983 | assert_eq!(a.wrapping_mul(b), c); 984 | assert_eq!(a.overflowing_mul(b), (c, true)); 985 | assert_eq!(a.checked_mul(b), None); 986 | assert_eq!(a.saturating_mul(b), MIN); 987 | 988 | assert_eq!(i128::new(-1).wrapping_mul(i128::new(-1)), ONE); 989 | assert_eq!(i128::new(-1).overflowing_mul(i128::new(-1)), (ONE, false)); 990 | assert_eq!(i128::new(-1).checked_mul(i128::new(-1)), Some(ONE)); 991 | assert_eq!(i128::new(-1).saturating_mul(i128::new(-1)), ONE); 992 | 993 | assert_eq!(MAX.wrapping_mul(i128::new(2)), i128::from_parts(-1, !1)); 994 | assert_eq!(MAX.overflowing_mul(i128::new(2)), (i128::from_parts(-1, !1), true)); 995 | assert_eq!(MAX.checked_mul(i128::new(2)), None); 996 | assert_eq!(MAX.saturating_mul(i128::new(2)), MAX); 997 | } 998 | } 999 | 1000 | //}}} 1001 | 1002 | //{{{ Div, Rem 1003 | 1004 | impl i128 { 1005 | /// Wrapping (modular) division. Computes `self / other`, wrapping around at the boundary of 1006 | /// the type. 1007 | /// 1008 | /// The only case where such wrapping can occur is when one divides `MIN / -1`; this is 1009 | /// equivalent to `-MIN`, a positive value that is too large to represent in the type. In such 1010 | /// a case, this function returns `MIN` itself. 1011 | /// 1012 | /// # Panics 1013 | /// 1014 | /// This function will panic if `other` is 0. 1015 | /// 1016 | /// # Examples 1017 | /// 1018 | /// ```rust 1019 | /// use extprim::i128::i128; 1020 | /// 1021 | /// assert_eq!(i128::new(100).wrapping_div(i128::new(-8)), i128::new(-12)); 1022 | /// assert_eq!(i128::min_value().wrapping_div(i128::new(-1)), i128::min_value()); 1023 | /// ``` 1024 | pub fn wrapping_div(self, other: i128) -> i128 { 1025 | let (sa, a) = sign_abs(self); 1026 | let (sb, b) = sign_abs(other); 1027 | let res = a.wrapping_div(b); 1028 | from_sign_abs(sa != sb, res) 1029 | } 1030 | 1031 | /// Wrapping (modular) remainder. Computes `self % other`, wrapping around at the boundary of 1032 | /// the type. 1033 | /// 1034 | /// Such wrap-around never actually occurs mathematically; implementation artifacts make 1035 | /// `x % y` invalid for `MIN / -1` on a signed type. In such a case, this function returns 0. 1036 | /// 1037 | /// # Panics 1038 | /// 1039 | /// This function will panic if `other` is 0. 1040 | /// 1041 | /// # Examples 1042 | /// 1043 | /// ```rust 1044 | /// use extprim::i128::i128; 1045 | /// 1046 | /// assert_eq!(i128::new(100).wrapping_rem(i128::new(-8)), i128::new(4)); 1047 | /// assert_eq!(i128::min_value().wrapping_rem(i128::new(-1)), i128::zero()); 1048 | /// ``` 1049 | pub fn wrapping_rem(self, other: i128) -> i128 { 1050 | let (sa, a) = sign_abs(self); 1051 | let (_, b) = sign_abs(other); 1052 | let res = a.wrapping_rem(b); 1053 | from_sign_abs(sa, res) 1054 | } 1055 | 1056 | /// Calculates the divisor when `self` is divided by `other`. 1057 | /// 1058 | /// Returns a tuple of the divisor along with a boolean indicating whether an arithmetic 1059 | /// overflow would occur. If an overflow would occur then self is returned. 1060 | /// 1061 | /// # Panics 1062 | /// 1063 | /// This function will panic if `other` is 0. 1064 | /// 1065 | /// # Examples 1066 | /// 1067 | /// ```rust 1068 | /// use extprim::i128::i128; 1069 | /// 1070 | /// assert_eq!(i128::new(100).overflowing_div(i128::new(-8)), (i128::new(-12), false)); 1071 | /// assert_eq!(i128::min_value().overflowing_div(i128::new(-1)), (i128::min_value(), true)); 1072 | /// ``` 1073 | pub fn overflowing_div(self, other: i128) -> (i128, bool) { 1074 | if self == MIN && other == -ONE { 1075 | (MIN, true) 1076 | } else { 1077 | (self.wrapping_div(other), false) 1078 | } 1079 | } 1080 | 1081 | /// Calculates the remainder when `self` is divided by `other`. 1082 | /// 1083 | /// Returns a tuple of the remainder after dividing along with a boolean indicating whether an 1084 | /// arithmetic overflow would occur. If an overflow would occur then 0 is returned. 1085 | /// 1086 | /// # Panics 1087 | /// 1088 | /// This function will panic if `other` is 0. 1089 | /// 1090 | /// # Examples 1091 | /// 1092 | /// ```rust 1093 | /// use extprim::i128::i128; 1094 | /// 1095 | /// assert_eq!(i128::new(100).overflowing_rem(i128::new(-8)), (i128::new(4), false)); 1096 | /// assert_eq!(i128::min_value().overflowing_rem(i128::new(-1)), (i128::zero(), true)); 1097 | /// ``` 1098 | pub fn overflowing_rem(self, other: i128) -> (i128, bool) { 1099 | if self == MIN && other == -ONE { 1100 | (ZERO, true) 1101 | } else { 1102 | (self.wrapping_rem(other), false) 1103 | } 1104 | } 1105 | 1106 | /// Checked integer division. Computes `self / other`, returning `None` if `other == 0` or the 1107 | /// operation results in underflow or overflow. 1108 | /// 1109 | /// # Examples 1110 | /// 1111 | /// ```rust 1112 | /// use extprim::i128::i128; 1113 | /// 1114 | /// assert_eq!(i128::new(100).checked_div(i128::new(-8)), Some(i128::new(-12))); 1115 | /// assert_eq!(i128::min_value().checked_div(i128::new(-1)), None); 1116 | /// assert_eq!(i128::new(3).checked_div(i128::zero()), None); 1117 | /// ``` 1118 | pub fn checked_div(self, other: i128) -> Option { 1119 | if other == ZERO || self == MIN && other == -ONE { 1120 | None 1121 | } else { 1122 | Some(self.wrapping_div(other)) 1123 | } 1124 | } 1125 | 1126 | /// Checked integer remainder. Computes `self % other`, returning `None` if `other == 0` or the 1127 | /// operation results in underflow or overflow. 1128 | /// 1129 | /// # Examples 1130 | /// 1131 | /// ```rust 1132 | /// use extprim::i128::i128; 1133 | /// 1134 | /// assert_eq!(i128::new(100).checked_rem(i128::new(-8)), Some(i128::new(4))); 1135 | /// assert_eq!(i128::min_value().checked_rem(i128::new(-1)), None); 1136 | /// assert_eq!(i128::new(3).checked_rem(i128::zero()), None); 1137 | /// ``` 1138 | pub fn checked_rem(self, other: i128) -> Option { 1139 | if other == ZERO || self == MIN && other == -ONE { 1140 | None 1141 | } else { 1142 | Some(self.wrapping_rem(other)) 1143 | } 1144 | } 1145 | } 1146 | 1147 | impl Div for i128 { 1148 | type Output = Self; 1149 | fn div(self, other: Self) -> Self { 1150 | self.wrapping_div(other) 1151 | } 1152 | } 1153 | 1154 | impl Rem for i128 { 1155 | type Output = Self; 1156 | fn rem(self, other: Self) -> Self { 1157 | self.wrapping_rem(other) 1158 | } 1159 | } 1160 | 1161 | impl Div for Wrapping { 1162 | type Output = Self; 1163 | fn div(self, other: Self) -> Self { 1164 | Wrapping(self.0.wrapping_div(other.0)) 1165 | } 1166 | } 1167 | 1168 | impl Rem for Wrapping { 1169 | type Output = Self; 1170 | fn rem(self, other: Self) -> Self { 1171 | Wrapping(self.0.wrapping_rem(other.0)) 1172 | } 1173 | } 1174 | 1175 | forward_assign!(DivAssign(div_assign, div) for i128); 1176 | forward_assign!(RemAssign(rem_assign, rem) for i128); 1177 | 1178 | impl CheckedDiv for i128 { 1179 | fn checked_div(&self, other: &Self) -> Option { 1180 | Self::checked_div(*self, *other) 1181 | } 1182 | } 1183 | 1184 | /// Computes the divisor and remainder simultaneously. Returns `(a/b, a%b)`. 1185 | /// 1186 | /// Unlike the primitive types, calling this is likely faster than calling `a/b` and `a%b` 1187 | /// separately. 1188 | /// 1189 | /// # Panics 1190 | /// 1191 | /// This function will panic if `denominator` is 0. If debug assertions is enabled, this function 1192 | /// will also panic on overflow (when computing `div_rem(MIN, -1)`). 1193 | /// 1194 | /// # Examples 1195 | /// 1196 | /// ```rust 1197 | /// use extprim::i128::{div_rem, i128}; 1198 | /// 1199 | /// assert_eq!(div_rem(i128::new(100), i128::new(-8)), (i128::new(-12), i128::new(4))); 1200 | /// ``` 1201 | pub fn div_rem(numerator: i128, denominator: i128) -> (i128, i128) { 1202 | if cfg!(debug_assertions) && numerator == MIN && denominator == -ONE { 1203 | panic!("arithmetic operation overflowed"); 1204 | } 1205 | let (sn, n) = sign_abs(numerator); 1206 | let (sd, d) = sign_abs(denominator); 1207 | let (div, rem) = ::u128::div_rem(n, d); 1208 | (from_sign_abs(sn != sd, div), from_sign_abs(sn, rem)) 1209 | } 1210 | 1211 | #[cfg(test)] 1212 | mod div_rem_tests { 1213 | use i128::{i128, ONE, div_rem}; 1214 | 1215 | #[test] 1216 | fn test_div() { 1217 | let nine = i128::new(9); 1218 | let four = i128::new(4); 1219 | let two = i128::new(2); 1220 | 1221 | assert_eq!(nine / four, two); 1222 | assert_eq!(nine / -four, -two); 1223 | assert_eq!((-nine) / four, -two); 1224 | assert_eq!((-nine) / -four, two); 1225 | assert_eq!(nine / two, four); 1226 | assert_eq!(nine / -two, -four); 1227 | assert_eq!((-nine) / two, -four); 1228 | assert_eq!((-nine) / -two, four); 1229 | 1230 | // Test case copied from https://github.com/rust-lang/rust/issues/41228 1231 | assert_eq!(i128::from_parts(-4746635337927214985, 8887618921150887885) / 1232 | i128::from_parts(4569140803224985180, 0), -ONE); 1233 | } 1234 | 1235 | #[test] 1236 | fn test_rem() { 1237 | let nine = i128::new(9); 1238 | let five = i128::new(5); 1239 | let four = i128::new(4); 1240 | 1241 | assert_eq!(nine % five, four); 1242 | assert_eq!(nine % -five, four); 1243 | assert_eq!((-nine) % five, -four); 1244 | assert_eq!((-nine) % -five, -four); 1245 | } 1246 | 1247 | #[test] 1248 | fn test_div_rem() { 1249 | let nine = i128::new(9); 1250 | let five = i128::new(5); 1251 | let four = i128::new(4); 1252 | 1253 | assert_eq!(div_rem(nine, five), (ONE, four)); 1254 | assert_eq!(div_rem(nine, -five), (-ONE, four)); 1255 | assert_eq!(div_rem(-nine, five), (-ONE, -four)); 1256 | assert_eq!(div_rem(-nine, -five), (ONE, -four)); 1257 | } 1258 | } 1259 | 1260 | //}}} 1261 | 1262 | //{{{ NumCast, ToPrimitive, FromPrimitive 1263 | 1264 | impl ToPrimitive for i128 { 1265 | fn to_i64(&self) -> Option { 1266 | let hi = self.high64(); 1267 | let lo = self.low64(); 1268 | 1269 | if hi == 0 && (lo >> 63) == 0 || hi == -1 && (lo >> 63) != 0 { 1270 | Some(lo as i64) 1271 | } else { 1272 | None 1273 | } 1274 | } 1275 | 1276 | fn to_u64(&self) -> Option { 1277 | if self.high64() != 0 { 1278 | None 1279 | } else { 1280 | Some(self.low64()) 1281 | } 1282 | } 1283 | 1284 | fn to_f64(&self) -> Option { 1285 | let (sign, abs) = sign_abs(*self); 1286 | let converted = abs.to_f64(); 1287 | if sign { 1288 | converted.map(|f| -f) 1289 | } else { 1290 | converted 1291 | } 1292 | } 1293 | 1294 | #[cfg(extprim_has_stable_i128)] 1295 | fn to_i128(&self) -> Option { 1296 | Some(self.as_built_in()) 1297 | } 1298 | 1299 | #[cfg(extprim_has_stable_i128)] 1300 | fn to_u128(&self) -> Option { 1301 | if self.high64() >= 0 { 1302 | Some(self.0.as_built_in()) 1303 | } else { 1304 | None 1305 | } 1306 | } 1307 | } 1308 | 1309 | impl FromPrimitive for i128 { 1310 | fn from_u64(n: u64) -> Option { 1311 | ToExtraPrimitive::to_i128(&n) 1312 | } 1313 | 1314 | fn from_i64(n: i64) -> Option { 1315 | ToExtraPrimitive::to_i128(&n) 1316 | } 1317 | 1318 | fn from_f64(n: f64) -> Option { 1319 | ToExtraPrimitive::to_i128(&n) 1320 | } 1321 | } 1322 | 1323 | impl ToExtraPrimitive for i128 { 1324 | fn to_u128(&self) -> Option { 1325 | if self.is_negative() { 1326 | None 1327 | } else { 1328 | Some(self.0) 1329 | } 1330 | } 1331 | 1332 | fn to_i128(&self) -> Option { 1333 | Some(*self) 1334 | } 1335 | } 1336 | 1337 | impl From for i128 { 1338 | fn from(arg: i8) -> Self { 1339 | i128::new(arg as i64) 1340 | } 1341 | } 1342 | 1343 | impl From for i128 { 1344 | fn from(arg: i16) -> Self { 1345 | i128::new(arg as i64) 1346 | } 1347 | } 1348 | 1349 | impl From for i128 { 1350 | fn from(arg: i32) -> Self { 1351 | i128::new(arg as i64) 1352 | } 1353 | } 1354 | 1355 | impl From for i128 { 1356 | fn from(arg: i64) -> Self { 1357 | i128::new(arg) 1358 | } 1359 | } 1360 | 1361 | #[cfg(extprim_has_stable_i128)] 1362 | impl From for i128 { 1363 | fn from(arg: I128) -> Self { 1364 | i128::from_built_in(arg) 1365 | } 1366 | } 1367 | 1368 | #[cfg(test)] 1369 | mod conv_tests { 1370 | use i128::{i128, MIN, MAX}; 1371 | use num_traits::ToPrimitive; 1372 | 1373 | #[test] 1374 | fn test_i128_to_f64() { 1375 | assert_eq!(i128::new(0).to_f64(), Some(0.0f64)); 1376 | assert_eq!(i128::new(1).to_f64(), Some(1.0f64)); 1377 | assert_eq!(i128::new(2).to_f64(), Some(2.0f64)); 1378 | assert_eq!(MAX.to_f64(), Some(170141183460469231731687303715884105727.0f64)); 1379 | assert_eq!(i128::new(-1).to_f64(), Some(-1.0f64)); 1380 | assert_eq!(i128::new(-2).to_f64(), Some(-2.0f64)); 1381 | assert_eq!(MIN.to_f64(), Some(-170141183460469231731687303715884105728.0f64)); 1382 | } 1383 | 1384 | #[test] 1385 | #[cfg(extprim_has_stable_i128)] 1386 | fn test_builtin_i128_to_i128() { 1387 | assert_eq!(i128::from_built_in(0x76571c252122c42e_8cdf8e3b4b75c4d0i128), i128::from_parts(0x76571c252122c42e, 0x8cdf8e3b4b75c4d0)); 1388 | assert_eq!(i128::from_built_in(-0x76571c252122c42e_8cdf8e3b4b75c4d0i128), i128::from_parts(-0x76571c252122c42f, 0x732071c4b48a3b30)); 1389 | assert_eq!(0x76571c252122c42e_8cdf8e3b4b75c4d0i128, i128::from_parts(0x76571c252122c42e, 0x8cdf8e3b4b75c4d0).as_built_in()); 1390 | assert_eq!(-0x76571c252122c42e_8cdf8e3b4b75c4d0i128, i128::from_parts(-0x76571c252122c42f, 0x732071c4b48a3b30).as_built_in()); 1391 | } 1392 | } 1393 | 1394 | //}}} 1395 | 1396 | //{{{ Constants 1397 | 1398 | impl i128 { 1399 | /// Returns the smallest signed 128-bit integer 1400 | /// (`-170_141_183_460_469_231_731_687_303_715_884_105_728`). 1401 | pub fn min_value() -> i128 { MIN } 1402 | 1403 | /// Returns the largest signed 128-bit integer 1404 | /// (`170_141_183_460_469_231_731_687_303_715_884_105_727`). 1405 | pub fn max_value() -> i128 { MAX } 1406 | 1407 | /// Returns the constant 0. 1408 | pub fn zero() -> i128 { ZERO } 1409 | 1410 | /// Returns the constant 1. 1411 | pub fn one() -> i128 { ONE } 1412 | } 1413 | 1414 | impl Bounded for i128 { 1415 | fn min_value() -> Self { MIN } 1416 | fn max_value() -> Self { MAX } 1417 | } 1418 | 1419 | impl Zero for i128 { 1420 | fn zero() -> Self { ZERO } 1421 | fn is_zero(&self) -> bool { *self == ZERO } 1422 | } 1423 | 1424 | impl One for i128 { 1425 | fn one() -> Self { ONE } 1426 | } 1427 | 1428 | //}}} 1429 | 1430 | //{{{ PrimInt 1431 | 1432 | impl i128 { 1433 | /// Returns the number of ones in the binary representation of `self`. 1434 | /// 1435 | /// # Examples 1436 | /// 1437 | /// ```rust 1438 | /// use extprim::i128::i128; 1439 | /// 1440 | /// assert_eq!(i128::new(-1000).count_ones(), 120); 1441 | /// ``` 1442 | pub fn count_ones(self) -> u32 { 1443 | self.0.count_ones() 1444 | } 1445 | 1446 | /// Returns the number of zeros in the binary representation of `self`. 1447 | /// 1448 | /// # Examples 1449 | /// 1450 | /// ```rust 1451 | /// use extprim::i128::i128; 1452 | /// 1453 | /// assert_eq!(i128::new(-1000).count_zeros(), 8); 1454 | /// ``` 1455 | pub fn count_zeros(self) -> u32 { 1456 | self.0.count_zeros() 1457 | } 1458 | 1459 | /// Returns the number of leading zeros in the binary representation of `self`. 1460 | /// 1461 | /// ```rust 1462 | /// use extprim::i128::i128; 1463 | /// 1464 | /// assert_eq!(i128::zero().leading_zeros(), 128); 1465 | /// assert_eq!(i128::one().leading_zeros(), 127); 1466 | /// assert_eq!(i128::new(-1).leading_zeros(), 0); 1467 | /// assert_eq!(i128::max_value().leading_zeros(), 1); 1468 | /// assert_eq!((i128::one() << 24u32).leading_zeros(), 103); 1469 | /// assert_eq!((i128::one() << 124u32).leading_zeros(), 3); 1470 | /// ``` 1471 | pub fn leading_zeros(self) -> u32 { 1472 | self.0.leading_zeros() 1473 | } 1474 | 1475 | /// Returns the number of trailing zeros in the binary representation of `self`. 1476 | /// 1477 | /// # Examples 1478 | /// 1479 | /// ```rust 1480 | /// use extprim::i128::i128; 1481 | /// 1482 | /// assert_eq!(i128::zero().trailing_zeros(), 128); 1483 | /// assert_eq!(i128::one().trailing_zeros(), 0); 1484 | /// assert_eq!(i128::min_value().trailing_zeros(), 127); 1485 | /// assert_eq!((i128::one() << 24u32).trailing_zeros(), 24); 1486 | /// assert_eq!((i128::one() << 124u32).trailing_zeros(), 124); 1487 | /// ``` 1488 | pub fn trailing_zeros(self) -> u32 { 1489 | self.0.trailing_zeros() 1490 | } 1491 | 1492 | /// Shifts the bits to the left by a specified amount, `shift`, wrapping the truncated bits to 1493 | /// the end of the resulting integer. 1494 | /// 1495 | /// # Examples 1496 | /// 1497 | /// ```rust 1498 | /// use extprim::i128::i128; 1499 | /// 1500 | /// let a = i128::from_str_radix("29c30f1029939b146664242d97d9f649", 16).unwrap(); 1501 | /// let b = i128::from_str_radix("-1e7877eb363275cccdede9341304db6c", 16).unwrap(); 1502 | /// assert_eq!(a.rotate_left(7), b); 1503 | /// ``` 1504 | pub fn rotate_left(self, shift: u32) -> i128 { 1505 | i128(self.0.rotate_left(shift)) 1506 | } 1507 | 1508 | /// Shifts the bits to the right by a specified amount, `shift`, wrapping the truncated bits to 1509 | /// the end of the resulting integer. 1510 | /// 1511 | /// # Examples 1512 | /// 1513 | /// ```rust 1514 | /// use extprim::i128::i128; 1515 | /// 1516 | /// let a = i128::from_str_radix("29c30f1029939b146664242d97d9f649", 16).unwrap(); 1517 | /// let b = i128::from_str_radix("-6dac79e1dfacd8c9d73337b7a4d04c14", 16).unwrap(); 1518 | /// assert_eq!(a.rotate_right(7), b); 1519 | /// ``` 1520 | pub fn rotate_right(self, shift: u32) -> i128 { 1521 | i128(self.0.rotate_right(shift)) 1522 | } 1523 | 1524 | /// Reverses the byte order of the integer. 1525 | /// 1526 | /// # Examples 1527 | /// 1528 | /// ```rust 1529 | /// use extprim::i128::i128; 1530 | /// 1531 | /// let a = i128::from_str_radix("11122233344455560123456789abcdef", 16).unwrap(); 1532 | /// let b = i128::from_str_radix("-1032547698badcfea9aabbcbccddedef", 16).unwrap(); 1533 | /// assert_eq!(a.swap_bytes(), b); 1534 | /// ``` 1535 | pub fn swap_bytes(self) -> i128 { 1536 | i128(self.0.swap_bytes()) 1537 | } 1538 | 1539 | /// Converts an integer from big endian to the target's endianness. 1540 | /// 1541 | /// On big endian this is a no-op. On little endian the bytes are swapped. 1542 | pub fn from_be(x: Self) -> Self { 1543 | if cfg!(target_endian="big") { 1544 | x 1545 | } else { 1546 | x.swap_bytes() 1547 | } 1548 | } 1549 | 1550 | /// Converts an integer from little endian to the target's endianness. 1551 | /// 1552 | /// On little endian this is a no-op. On big endian the bytes are swapped. 1553 | pub fn from_le(x: Self) -> Self { 1554 | if cfg!(target_endian="little") { 1555 | x 1556 | } else { 1557 | x.swap_bytes() 1558 | } 1559 | } 1560 | 1561 | /// Converts `self` to big endian from the target's endianness. 1562 | /// 1563 | /// On big endian this is a no-op. On little endian the bytes are swapped. 1564 | pub fn to_be(self) -> Self { 1565 | Self::from_be(self) 1566 | } 1567 | 1568 | /// Converts self to little endian from the target's endianness. 1569 | /// 1570 | /// On little endian this is a no-op. On big endian the bytes are swapped. 1571 | pub fn to_le(self) -> Self { 1572 | Self::from_le(self) 1573 | } 1574 | 1575 | /// Raises `self` to the power of `exp`, using exponentiation by squaring. 1576 | /// 1577 | /// # Examples 1578 | /// 1579 | /// ``` 1580 | /// use extprim::i128::i128; 1581 | /// use std::str::FromStr; 1582 | /// 1583 | /// assert_eq!(i128::new(-5).pow(29), i128::from_str("-186264514923095703125").unwrap()); 1584 | /// assert_eq!(i128::new(-5).pow(30), i128::from_str("931322574615478515625").unwrap()); 1585 | /// ``` 1586 | pub fn pow(self, exp: u32) -> Self { 1587 | pow(self, exp as usize) 1588 | } 1589 | } 1590 | 1591 | impl PrimInt for i128 { 1592 | fn count_ones(self) -> u32 { Self::count_ones(self) } 1593 | fn count_zeros(self) -> u32 { Self::count_zeros(self) } 1594 | fn leading_zeros(self) -> u32 { Self::leading_zeros(self) } 1595 | fn trailing_zeros(self) -> u32 { Self::trailing_zeros(self) } 1596 | fn rotate_left(self, shift: u32) -> Self { Self::rotate_left(self, shift) } 1597 | fn rotate_right(self, shift: u32) -> Self { Self::rotate_right(self, shift) } 1598 | fn swap_bytes(self) -> Self { Self::swap_bytes(self) } 1599 | fn from_be(x: Self) -> Self { Self::from_be(x) } 1600 | fn from_le(x: Self) -> Self { Self::from_le(x) } 1601 | fn to_be(self) -> Self { Self::to_be(self) } 1602 | fn to_le(self) -> Self { Self::to_le(self) } 1603 | fn pow(self, exp: u32) -> Self { Self::pow(self, exp) } 1604 | 1605 | fn signed_shl(self, shift: u32) -> Self { 1606 | self << (shift as usize) 1607 | } 1608 | 1609 | fn signed_shr(self, shift: u32) -> Self { 1610 | self >> (shift as usize) 1611 | } 1612 | 1613 | fn unsigned_shl(self, shift: u32) -> Self { 1614 | self << (shift as usize) 1615 | } 1616 | 1617 | fn unsigned_shr(self, shift: u32) -> Self { 1618 | i128(self.0 >> (shift as usize)) 1619 | } 1620 | } 1621 | 1622 | #[cfg(test)] 1623 | mod checked_tests { 1624 | use std::u64; 1625 | use std::i64; 1626 | use i128::{i128, ZERO, ONE, MAX, MIN}; 1627 | 1628 | #[test] 1629 | fn test_checked_add() { 1630 | assert_eq!(Some(ZERO), ONE.checked_add(-ONE)); 1631 | assert_eq!(Some(ZERO), (-ONE).checked_add(ONE)); 1632 | assert_eq!(Some(i128::new(-2)), (-ONE).checked_add(-ONE)); 1633 | assert_eq!(Some(i128::new(2)), ONE.checked_add(ONE)); 1634 | assert_eq!(Some(MAX), MAX.checked_add(ZERO)); 1635 | assert_eq!(Some(-ONE), MAX.checked_add(MIN)); 1636 | assert_eq!(None, MAX.checked_add(ONE)); 1637 | assert_eq!(None, MIN.checked_add(-ONE)); 1638 | assert_eq!(None, ONE.checked_add(MAX)); 1639 | assert_eq!(None, (-ONE).checked_add(MIN)); 1640 | assert_eq!(Some(ZERO), MAX.checked_add(-MAX)); 1641 | assert_eq!(None, MIN.checked_add(MIN)); 1642 | } 1643 | 1644 | #[test] 1645 | fn test_checked_sub() { 1646 | assert_eq!(Some(ZERO), ONE.checked_sub(ONE)); 1647 | assert_eq!(Some(ZERO), MAX.checked_sub(MAX)); 1648 | assert_eq!(Some(ZERO), MIN.checked_sub(MIN)); 1649 | assert_eq!(Some(-ONE), ZERO.checked_sub(ONE)); 1650 | assert_eq!(Some(MAX.wrapping_sub(ONE)), MAX.checked_sub(ONE)); 1651 | assert_eq!(Some(-MAX), ZERO.checked_sub(MAX)); 1652 | assert_eq!(None, ZERO.checked_sub(MIN)); 1653 | assert_eq!(None, MIN.checked_sub(ONE)); 1654 | assert_eq!(None, MAX.checked_sub(-ONE)); 1655 | assert_eq!(Some(MAX), MAX.checked_sub(ZERO)); 1656 | assert_eq!(Some(MIN), MIN.checked_sub(ZERO)); 1657 | assert_eq!(Some(-ONE), MIN.checked_sub(-MAX)); 1658 | assert_eq!(Some(i128::new(2)), ONE.checked_sub(-ONE)); 1659 | } 1660 | 1661 | #[test] 1662 | fn test_checked_mul() { 1663 | assert_eq!(Some(ONE), ONE.checked_mul(ONE)); 1664 | assert_eq!(Some(ZERO), MIN.checked_mul(ZERO)); 1665 | assert_eq!(Some(MIN), MIN.checked_mul(ONE)); 1666 | assert_eq!(None, MIN.checked_mul(i128::new(2))); 1667 | assert_eq!(Some(MAX), MAX.checked_mul(ONE)); 1668 | assert_eq!(None, i128::new(2).checked_mul(MAX)); 1669 | assert_eq!(None, i128::from_parts(1, 0).checked_mul(i128::from_parts(1, 0))); 1670 | assert_eq!(None, i128::from_parts(1, 0).checked_mul(i128::from_parts(0, u64::MAX))); 1671 | assert_eq!(Some(-MAX), MAX.checked_mul(-ONE)); 1672 | assert_eq!(None, MIN.checked_mul(-ONE)); 1673 | assert_eq!(None, i128::from_parts(-1, 0).checked_mul(i128::from_parts(0, u64::MAX))); 1674 | assert_eq!(Some(i128::from_parts(-i64::MAX, 0)), i128::from_parts(-1, 0).checked_mul(i128::new(i64::MAX))); 1675 | assert_eq!(None, i128::from_parts(-1, 0).checked_mul(i128::new(i64::MIN))); 1676 | } 1677 | 1678 | #[test] 1679 | fn test_checked_div() { 1680 | assert_eq!(Some(ONE), ONE.checked_div(ONE)); 1681 | assert_eq!(Some(ONE), (-ONE).checked_div(-ONE)); 1682 | assert_eq!(Some(MAX), MAX.checked_div(ONE)); 1683 | assert_eq!(Some(MIN), MIN.checked_div(ONE)); 1684 | assert_eq!(Some(ZERO), ONE.checked_div(MAX)); 1685 | assert_eq!(Some(ZERO), ZERO.checked_div(MAX)); 1686 | assert_eq!(Some(ZERO), ZERO.checked_div(MIN)); 1687 | assert_eq!(None, ONE.checked_div(ZERO)); 1688 | assert_eq!(None, MAX.checked_div(ZERO)); 1689 | assert_eq!(None, MIN.checked_div(ZERO)); 1690 | assert_eq!(Some(-MAX), MAX.checked_div(-ONE)); 1691 | assert_eq!(None, MIN.checked_div(-ONE)); 1692 | } 1693 | } 1694 | 1695 | //}}} 1696 | 1697 | //{{{ Signed 1698 | 1699 | impl i128 { 1700 | /// Computes the absolute value of `self`. 1701 | /// 1702 | /// # Overflow behavior 1703 | /// 1704 | /// The absolute value of `i128::MIN` cannot be represented as an `i128`, and attempting to 1705 | /// calculate it will cause an overflow. This means that code in debug mode will trigger a 1706 | /// panic on this case and optimized code will return `MIN` without a panic. 1707 | /// 1708 | /// # Examples 1709 | /// 1710 | /// ```rust 1711 | /// use extprim::i128::i128; 1712 | /// use std::i64; 1713 | /// 1714 | /// assert_eq!(i128::new(10).abs(), i128::new(10)); 1715 | /// assert_eq!(i128::new(-10).abs(), i128::new(10)); 1716 | /// assert_eq!(i128::new(i64::MIN).abs(), i128::from_parts(0, 0x80000000_00000000)); 1717 | /// ``` 1718 | pub fn abs(self) -> Self { 1719 | if self.is_negative() { 1720 | -self 1721 | } else { 1722 | self 1723 | } 1724 | } 1725 | 1726 | /// Returns a number representing sign of `self`. 1727 | /// 1728 | /// * `0` if the number is zero 1729 | /// * `1` if the number is positive 1730 | /// * `-1` if the number is negative 1731 | /// 1732 | /// # Examples 1733 | /// 1734 | /// ```rust 1735 | /// use extprim::i128::i128; 1736 | /// 1737 | /// assert_eq!(i128::max_value().signum(), i128::one()); 1738 | /// assert_eq!(i128::zero().signum(), i128::zero()); 1739 | /// assert_eq!(i128::min_value().signum(), -i128::one()); 1740 | /// ``` 1741 | pub fn signum(self) -> Self { 1742 | let hi = self.high64(); 1743 | let lo = self.low64(); 1744 | if hi < 0 { 1745 | -ONE 1746 | } else if hi > 0 || lo > 0 { 1747 | ONE 1748 | } else { 1749 | ZERO 1750 | } 1751 | } 1752 | 1753 | /// Returns `true` if `self` is positive and `false` if the number is zero or negative. 1754 | /// # Examples 1755 | /// 1756 | /// ```rust 1757 | /// use extprim::i128::i128; 1758 | /// 1759 | /// assert!( i128::max_value().is_positive()); 1760 | /// assert!(! i128::zero().is_positive()); 1761 | /// assert!(! i128::min_value().is_positive()); 1762 | /// ``` 1763 | pub fn is_positive(self) -> bool { 1764 | let hi = self.high64(); 1765 | let lo = self.low64(); 1766 | hi > 0 || hi == 0 && lo > 0 1767 | } 1768 | 1769 | /// Returns `true` if `self` is negative and `false` if the number is zero or positive. 1770 | /// # Examples 1771 | /// 1772 | /// ```rust 1773 | /// use extprim::i128::i128; 1774 | /// 1775 | /// assert!(! i128::max_value().is_negative()); 1776 | /// assert!(! i128::zero().is_negative()); 1777 | /// assert!( i128::min_value().is_negative()); 1778 | /// ``` 1779 | pub fn is_negative(self) -> bool { 1780 | self.high64() < 0 1781 | } 1782 | } 1783 | 1784 | impl Signed for i128 { 1785 | fn abs(&self) -> Self { Self::abs(*self) } 1786 | fn signum(&self) -> Self { Self::signum(*self) } 1787 | fn is_positive(&self) -> bool { Self::is_positive(*self) } 1788 | fn is_negative(&self) -> bool { Self::is_negative(*self) } 1789 | 1790 | fn abs_sub(&self, other: &Self) -> Self { 1791 | if *self <= *other { 1792 | ZERO 1793 | } else { 1794 | *self - *other 1795 | } 1796 | } 1797 | } 1798 | 1799 | //}}} 1800 | 1801 | //{{{ FromStr, FromStrRadix 1802 | 1803 | impl i128 { 1804 | /// Converts a string slice in a given base to an integer. 1805 | /// 1806 | /// Leading and trailing whitespace represent an error. 1807 | /// 1808 | /// # Examples 1809 | /// 1810 | /// ```rust 1811 | /// use extprim::i128::i128; 1812 | /// 1813 | /// assert_eq!(i128::from_str_radix("123456abcdef1234567890", 16), 1814 | /// Ok(i128::from_parts(0x123456, 0xabcdef1234567890))); 1815 | /// ``` 1816 | pub fn from_str_radix(src: &str, radix: u32) -> Result { 1817 | assert!(radix >= 2 && radix <= 36, 1818 | "from_str_radix_int: must lie in the range `[2, 36]` - found {}", 1819 | radix); 1820 | 1821 | let mut src_chars = src.chars(); 1822 | let (is_negative, src) = match src_chars.next() { 1823 | Some('-') => (true, src_chars.as_str()), 1824 | Some(_) => (false, src), 1825 | None => return Err(error::empty()), 1826 | }; 1827 | 1828 | match u128::from_str_radix(src, radix) { 1829 | Ok(res) => { 1830 | let res = from_sign_abs(is_negative, res); 1831 | if res != ZERO && res.is_negative() != is_negative { 1832 | Err(if is_negative { 1833 | error::underflow() 1834 | } else { 1835 | error::overflow() 1836 | }) 1837 | } else { 1838 | Ok(res) 1839 | } 1840 | }, 1841 | Err(e) => { 1842 | if is_negative && error::is_overflow(&e) { 1843 | Err(error::underflow()) 1844 | } else { 1845 | Err(e) 1846 | } 1847 | }, 1848 | } 1849 | } 1850 | } 1851 | 1852 | impl Num for i128 { 1853 | type FromStrRadixErr = ParseIntError; 1854 | 1855 | fn from_str_radix(src: &str, radix: u32) -> Result { 1856 | Self::from_str_radix(src, radix) 1857 | } 1858 | } 1859 | 1860 | impl FromStr for i128 { 1861 | type Err = ParseIntError; 1862 | 1863 | fn from_str(src: &str) -> Result { 1864 | Self::from_str_radix(src, 10) 1865 | } 1866 | } 1867 | 1868 | #[cfg(test)] 1869 | mod from_str_tests { 1870 | use i128::{i128, ZERO, ONE, MIN, MAX}; 1871 | use error; 1872 | 1873 | #[test] 1874 | fn test_from_str_radix() { 1875 | const NEG_TEST_RESULTS: &'static [&'static str] = &[ 1876 | "-1101001110000001100001110100110110011101000101000000010101010011111111110000011111001111010001011110010010111111100000110111000", 1877 | "-22120002200011001100011122212011101112220120010100201111102212122012112012001022", 1878 | "-1221300030032212303220220002222133332003321322023302113330012320", 1879 | "-2231231421040121443301142220330220044211010312230031421", 1880 | "-10132201224250532404323114055045240003123220242012", 1881 | "-1212403560410303232526313225350346610154225424", 1882 | "-1516014164663505002523776037172136227740670", 1883 | "-8502604040148764345816110644385565465038", 1884 | "-140569828839923299370138738435219767736", 1885 | "-460253358a63a84a62856346973015326a085", 1886 | "-24684544189b3b874708a686624448540308", 1887 | "-1b5619074137abcca07c1b789a5bb40143a", 1888 | "-218c480b6358d305699729902706a4db84", 1889 | "-33d141e10db8d70b6249ae5224b7c97ab", 1890 | "-69c0c3a6ce8a02a9ff83e7a2f25fc1b8", 1891 | "-102b311fc29a372ecb13e199baf8acfe", 1892 | "-31aaf9047ff3ec83haa539ab9419b68", 1893 | "-bb3a85b4194a20if536h6heha6i35b", 1894 | "-2c76aee5d2b9da7ae7fb3a2a63aj6g", 1895 | "-d7b08bdk5fk2de09j5ed0gcg27f5b", 1896 | "-3djbdj2fa4khdffaldl1b208ej2kg", 1897 | "-11172kdka2cf0gj0im640g8gi0mkd", 1898 | "-7enbdaajdc653dabmllnjll400i8", 1899 | "-2d7gm5k79nf6mc3fc0ob55gcf39b", 1900 | "-mlhn5khiebmai868llpeih4mnla", 1901 | "-8f2i4194hn4aeof39jdbnh5e518", 1902 | "-392krpg3g0r0d1001nj4jm5fkb4", 1903 | "-19kq0qaqlnf9c535470kddq5ida", 1904 | "-ghleobpr1dricb67pkro9ii1rq", 1905 | "-79hp9koffuiiscaoiouar0fgp0", 1906 | "-39o31qdjka0akvv0v7kbp5vgdo", 1907 | "-1hhh74vud8w72snbpj5teksfw5", 1908 | "-on7ixvje61183p5w49qovbwxe", 1909 | "-catrg80wne60wsi5f2y4nefab", 1910 | "-69e1equxg4kja5utg038kcgc8", 1911 | ]; 1912 | 1913 | let neg = i128::from_parts(-7620305690708017834, 34929685051752008); 1914 | for (base2, res) in NEG_TEST_RESULTS.iter().enumerate() { 1915 | let base = (base2 + 2) as u32; 1916 | assert_eq!(Ok(neg), i128::from_str_radix(*res, base)); 1917 | assert_eq!(Ok(-neg), i128::from_str_radix(&res[1..], base)); 1918 | } 1919 | 1920 | assert_eq!(Ok(ZERO), i128::from_str_radix("0", 2)); 1921 | assert_eq!(Ok(ZERO), i128::from_str_radix("-0", 2)); 1922 | assert_eq!(Ok(ZERO), i128::from_str_radix("0000000000000000000000000000000000", 36)); 1923 | assert_eq!(Err(error::invalid_digit()), i128::from_str_radix("123", 3)); 1924 | assert_eq!(Ok(-ONE), i128::from_str_radix("-1", 10)); 1925 | assert_eq!(Err(error::invalid_digit()), i128::from_str_radix("~1", 10)); 1926 | assert_eq!(Err(error::empty()), i128::from_str_radix("", 10)); 1927 | assert_eq!(Ok(MAX), i128::from_str_radix("7ksyyizzkutudzbv8aqztecjj", 36)); 1928 | assert_eq!(Ok(MIN), i128::from_str_radix("-7ksyyizzkutudzbv8aqztecjk", 36)); 1929 | assert_eq!(Err(error::overflow()), i128::from_str_radix("7ksyyizzkutudzbv8aqztecjk", 36)); 1930 | assert_eq!(Err(error::underflow()), i128::from_str_radix("-7ksyyizzkutudzbv8aqztecjl", 36)); 1931 | } 1932 | } 1933 | 1934 | //}}} 1935 | 1936 | //{{{ String, Binary, LowerHex, UpperHex, Octal, Show 1937 | 1938 | // In Rust, all signed numbers will be printed as unsigned in binary, octal 1939 | // and hex mode. 1940 | 1941 | impl fmt::Binary for i128 { 1942 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 1943 | self.0.fmt(formatter) 1944 | } 1945 | } 1946 | 1947 | impl fmt::LowerHex for i128 { 1948 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 1949 | self.0.fmt(formatter) 1950 | } 1951 | } 1952 | 1953 | impl fmt::UpperHex for i128 { 1954 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 1955 | self.0.fmt(formatter) 1956 | } 1957 | } 1958 | 1959 | impl fmt::Octal for i128 { 1960 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 1961 | self.0.fmt(formatter) 1962 | } 1963 | } 1964 | 1965 | impl fmt::Display for i128 { 1966 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 1967 | if !self.is_negative() { 1968 | self.0.fmt(formatter) 1969 | } else if *self == MIN { 1970 | formatter.pad_integral(false, "", "170141183460469231731687303715884105728") 1971 | } else { 1972 | let mut buffer = [0u8; 39]; 1973 | let mut buf = FormatBuffer::new(&mut buffer); 1974 | write!(&mut buf, "{}", self.0.wrapping_neg())?; 1975 | formatter.pad_integral(false, "", unsafe { buf.into_str() }) 1976 | } 1977 | } 1978 | } 1979 | 1980 | impl fmt::Debug for i128 { 1981 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 1982 | write!(formatter, "i128!({})", self) 1983 | } 1984 | } 1985 | 1986 | #[cfg(test)] 1987 | mod show_tests { 1988 | use i128::{i128, ZERO, ONE, MIN, MAX}; 1989 | 1990 | #[test] 1991 | fn test_show() { 1992 | assert_fmt_eq!("0", 1, "{}", ZERO); 1993 | assert_fmt_eq!("1", 1, "{}", ONE); 1994 | assert_fmt_eq!("-1", 2, "{}", -ONE); 1995 | assert_fmt_eq!("170141183460469231731687303715884105727", 40, "{}", MAX); 1996 | assert_fmt_eq!("-170141183460469231731687303715884105727", 40, "{}", -MAX); 1997 | assert_fmt_eq!("-170141183460469231731687303715884105728", 40, "{}", MIN); 1998 | assert_fmt_eq!("-41001515780870386888810710836203638388", 40, 1999 | "{}", i128::from_parts(-2222696624240918362, 11097545986877534604)); 2000 | assert_fmt_eq!("+00170141183460469231731687303715884105727", 42, "{:+042}", MAX); 2001 | assert_fmt_eq!("-00170141183460469231731687303715884105728", 42, "{:+042}", MIN); 2002 | 2003 | // Sanity test 2004 | assert_fmt_eq!("ff", 2, "{:x}", -1i8); 2005 | } 2006 | } 2007 | 2008 | //}}} 2009 | 2010 | //{{{ Sum, Product 2011 | 2012 | impl Sum for i128 { 2013 | fn sum(iter: I) -> Self 2014 | where I: Iterator 2015 | { 2016 | iter.fold(ZERO, Add::add) 2017 | } 2018 | } 2019 | 2020 | impl Product for i128 { 2021 | fn product(iter: I) -> Self 2022 | where I: Iterator 2023 | { 2024 | iter.fold(ONE, Mul::mul) 2025 | } 2026 | } 2027 | 2028 | impl<'a> Sum<&'a i128> for i128 { 2029 | fn sum(iter: I) -> Self 2030 | where I: Iterator 2031 | { 2032 | iter.fold(ZERO, |acc, elem| acc + *elem) 2033 | } 2034 | } 2035 | 2036 | impl<'a> Product<&'a i128> for i128 { 2037 | fn product(iter: I) -> Self 2038 | where I: Iterator 2039 | { 2040 | iter.fold(ONE, |acc, elem| acc * *elem) 2041 | } 2042 | } 2043 | 2044 | #[cfg(test)] 2045 | mod iter_tests { 2046 | use i128::{i128, ZERO, ONE, MIN, MAX}; 2047 | 2048 | #[test] 2049 | fn test_sum() { 2050 | // Sum 2051 | assert_eq!(ZERO, Vec::::new().into_iter().sum()); 2052 | assert_eq!(ZERO, vec![ZERO, ZERO, ZERO].into_iter().sum()); 2053 | assert_eq!(ZERO, vec![-ONE, ONE].into_iter().sum()); 2054 | assert_eq!(ONE, vec![ONE].into_iter().sum()); 2055 | assert_eq!(i128::from(3i64), vec![ONE, ONE, ONE].into_iter().sum()); 2056 | assert_eq!(-ONE, vec![MAX, MIN].into_iter().sum()); 2057 | assert_eq!(i128::from(2i64), vec![ 2058 | i128::from(-3i64), 2059 | i128::from(10i64), 2060 | MIN, 2061 | MAX - i128::from(4i64), 2062 | ].into_iter().sum()); 2063 | assert_eq!(MAX, vec![MAX].into_iter().sum()); 2064 | assert_eq!(MIN, vec![MIN].into_iter().sum()); 2065 | assert_eq!(i128::from_parts(7, 42), vec![i128::from_parts(7, 42)].into_iter().sum()); 2066 | 2067 | // Sum<&'a i128> 2068 | assert_eq!(ZERO, [].iter().sum()); 2069 | assert_eq!(ZERO, [ZERO, ZERO, ZERO].iter().sum()); 2070 | assert_eq!(ZERO, [-ONE, ONE].iter().sum()); 2071 | assert_eq!(ONE, [ONE].iter().sum()); 2072 | assert_eq!(i128::from(3i64), [ONE, ONE, ONE].iter().sum()); 2073 | assert_eq!(-ONE, [MAX, MIN].iter().sum()); 2074 | assert_eq!(i128::from(2i64), [ 2075 | i128::from(-3i64), 2076 | i128::from(10i64), 2077 | MIN, 2078 | MAX - i128::from(4i64), 2079 | ].iter().sum()); 2080 | assert_eq!(MAX, [MAX].iter().sum()); 2081 | assert_eq!(MIN, [MIN].iter().sum()); 2082 | assert_eq!(i128::from_parts(7, 42), [i128::from_parts(7, 42)].iter().sum()); 2083 | } 2084 | 2085 | #[test] 2086 | fn test_product() { 2087 | // Product 2088 | assert_eq!(ONE, Vec::::new().into_iter().product()); 2089 | assert_eq!(ONE, vec![ONE, ONE, ONE, ONE, ONE].into_iter().product()); 2090 | assert_eq!(ZERO, vec![MAX, ZERO, MIN, ONE].into_iter().product()); 2091 | assert_eq!(MAX, vec![MAX].into_iter().product()); 2092 | assert_eq!(MAX, vec![ONE, MAX].into_iter().product()); 2093 | assert_eq!(MIN, vec![MIN].into_iter().product()); 2094 | assert_eq!(MIN, vec![ONE, MIN].into_iter().product()); 2095 | assert_eq!(MIN, vec![ 2096 | i128::from(-0x1i64), 2097 | i128::from(0x2i64), 2098 | i128::from(0x4i64), 2099 | i128::from(0x10i64), 2100 | i128::from(0x100i64), 2101 | i128::from(0x10000i64), 2102 | i128::from(0x100000000i64), 2103 | i128::from_parts(0x1, 0x0), 2104 | ].into_iter().product()); 2105 | 2106 | // Product<&'a i128> 2107 | assert_eq!(ONE, [].iter().product()); 2108 | assert_eq!(ONE, [ONE, ONE, ONE, ONE, ONE].iter().product()); 2109 | assert_eq!(ZERO, [MAX, ZERO, MIN, ONE].iter().product()); 2110 | assert_eq!(MAX, [MAX].iter().product()); 2111 | assert_eq!(MAX, [ONE, MAX].iter().product()); 2112 | assert_eq!(MIN, [MIN].iter().product()); 2113 | assert_eq!(MIN, [ONE, MIN].iter().product()); 2114 | assert_eq!(MIN, [ 2115 | i128::from(-0x1i64), 2116 | i128::from(0x2i64), 2117 | i128::from(0x4i64), 2118 | i128::from(0x10i64), 2119 | i128::from(0x100i64), 2120 | i128::from(0x10000i64), 2121 | i128::from(0x100000000i64), 2122 | i128::from_parts(0x1, 0x0), 2123 | ].iter().product()); 2124 | } 2125 | } 2126 | 2127 | //}}} 2128 | 2129 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides some extra simple types. 2 | //! 3 | //! u128 and i128 4 | //! ============= 5 | //! 6 | //! Support signed and unsigned 128-bit integers. Also standard primitive operations are supported. 7 | //! 8 | //! These are mainly needed where explicit 128-bit integer types are required. If the purpose is to 9 | //! operate on "very large integers", the [bigint](https://crates.io/crates/num-bigint) library may 10 | //! be more suitable. 11 | //! 12 | //! ```rust 13 | //! #[macro_use] extern crate extprim_literals; 14 | //! extern crate extprim; 15 | //! 16 | //! use std::str::FromStr; 17 | //! use extprim::i128::i128; 18 | //! 19 | //! fn main() { 20 | //! let a = i128::from_str("100000000000000000000000000000000000000").unwrap(); 21 | //! // convert string to u128 or i128 22 | //! let b = i128::new(10).pow(38); 23 | //! // 64-bit integers can be directly new'ed 24 | //! assert_eq!(a, b); 25 | //! 26 | //! let c = i128::from_parts(5421010862427522170, 687399551400673280); 27 | //! // represent using the higher- and lower-64-bit parts 28 | //! let d = c - a; 29 | //! // standard operators like +, -, *, /, %, etc. work as expected. 30 | //! assert_eq!(d, i128::zero()); 31 | //! 32 | //! const e: i128 = i128!(100000000000000000000000000000000000000); 33 | //! // use the literal macros 34 | //! assert_eq!(a, e); 35 | //! } 36 | //! ``` 37 | //! 38 | //! Literal macros 39 | //! ============== 40 | //! 41 | //! The extra primitive types can be created via the literal macros using the `extprim_literals` procedural macro. 42 | //! Please check the [documentation of `extprim_literals`](../../extprim_literals/index.html) for details. 43 | //! 44 | //! ```ignore 45 | //! #![macro_use] 46 | //! extern crate extprim_literals; 47 | //! extern crate extprim; 48 | //! 49 | //! fn main() { 50 | //! let a = u128!(0xffeeddcc_bbaa9988_77665544_33221100); 51 | //! let b = u128!(73); 52 | //! let result = a / b; 53 | //! let expected = u128!(4_660_183_619_323_730_626_856_278_982_251_165_334); 54 | //! assert_eq!(a / b, expected); 55 | //! } 56 | //! ``` 57 | 58 | #![cfg_attr(extprim_channel="unstable", feature(llvm_asm, test, specialization, const_fn))] 59 | // feature requirement: 60 | // - llvm_asm: to provide a fast implementation of u64_long_mul in x86_64 61 | // - test: benchmarking 62 | // - specialization: to allow ToExtraPrimitive inherit from ToPrimitive, while ensuring conversion 63 | // between the 128-bit types remain correct 64 | // - const_fn: Create 128-bit constants 65 | 66 | #![cfg_attr(not(feature="use-std"), no_std)] 67 | 68 | #[cfg(extprim_channel="unstable")] extern crate test; 69 | 70 | #[cfg(feature = "serde")] 71 | #[macro_use] 72 | extern crate serde; 73 | 74 | #[cfg(feature="use-std")] extern crate core; 75 | #[cfg(not(feature="use-std"))] extern crate core as std; 76 | #[cfg(feature="rand")] extern crate rand; 77 | extern crate num_traits; 78 | 79 | #[macro_use] mod forward; 80 | #[cfg_attr(test, macro_use)] mod format_buffer; 81 | mod error; 82 | pub mod traits; 83 | pub mod u128; 84 | pub mod i128; 85 | mod compiler_rt; 86 | 87 | -------------------------------------------------------------------------------- /src/traits.rs: -------------------------------------------------------------------------------- 1 | //! Traits for conversion between the extra primitive types. 2 | 3 | use num_traits::{ToPrimitive, NumCast, One, Float}; 4 | #[cfg(feature="use-std")] use num_traits::Num; 5 | use u128::u128; 6 | use i128::i128; 7 | #[cfg(extprim_has_stable_i128)] use compiler_rt::builtins::{U128, I128}; 8 | use std::ops::MulAssign; 9 | 10 | /// Trait for converting itself into the extra primitive types. 11 | /// 12 | /// # Note 13 | /// 14 | /// Converting f32/f64 to u128/i128 will always succeed, even if they represent values outside of 15 | /// the u128/i128 ranges. They will just return `Some(0)` on overflow. This is similar to how 16 | /// `num_traits::ToPrimitive` treat the float conversions. 17 | /// 18 | /// ```rust 19 | /// use extprim::traits::ToExtraPrimitive; 20 | /// use extprim::u128::u128; 21 | /// use std::f64; 22 | /// 23 | /// assert_eq!(680.0f64.to_u128(), Some(u128::new(680))); 24 | /// assert_eq!(2.0f64.powi(64).to_u128(), Some(u128::from_parts(1, 0))); 25 | /// 26 | /// // The following examples overflow, but they all still convert to 0. 27 | /// assert_eq!(2.0f64.powi(128).to_u128(), Some(u128::zero())); 28 | /// assert_eq!(f64::MAX.to_u128(), Some(u128::zero())); 29 | /// assert_eq!(f64::INFINITY.to_u128(), Some(u128::zero())); 30 | /// assert_eq!(f64::NAN.to_u128(), Some(u128::zero())); 31 | /// ``` 32 | pub trait ToExtraPrimitive: ToPrimitive { 33 | /// Tries to convert itself into an unsigned 128-bit integer. 34 | fn to_u128(&self) -> Option; 35 | 36 | /// Tries to convert itself into a signed 128-bit integer. 37 | fn to_i128(&self) -> Option; 38 | } 39 | 40 | macro_rules! impl_to_extra_primitive_for_int { 41 | ($ty:ty) => { 42 | impl ToExtraPrimitive for $ty { 43 | fn to_u128(&self) -> Option { 44 | #[cfg(extprim_has_stable_i128)] { 45 | ToPrimitive::to_u128(self).map(u128::from_built_in) 46 | } 47 | #[cfg(not(extprim_has_stable_i128))] { 48 | self.to_u64().map(u128::new) 49 | } 50 | } 51 | 52 | fn to_i128(&self) -> Option { 53 | #[cfg(extprim_has_stable_i128)] { 54 | ToPrimitive::to_i128(self).map(i128::from_built_in) 55 | } 56 | #[cfg(not(extprim_has_stable_i128))] { 57 | match self.to_u64() { 58 | Some(v) => Some(i128(u128::new(v))), 59 | None => self.to_i64().map(i128::new), 60 | } 61 | } 62 | } 63 | } 64 | } 65 | } 66 | 67 | impl_to_extra_primitive_for_int!(u8); 68 | impl_to_extra_primitive_for_int!(i8); 69 | impl_to_extra_primitive_for_int!(u16); 70 | impl_to_extra_primitive_for_int!(i16); 71 | impl_to_extra_primitive_for_int!(u32); 72 | impl_to_extra_primitive_for_int!(i32); 73 | impl_to_extra_primitive_for_int!(u64); 74 | impl_to_extra_primitive_for_int!(i64); 75 | impl_to_extra_primitive_for_int!(usize); 76 | impl_to_extra_primitive_for_int!(isize); 77 | 78 | #[cfg(extprim_has_stable_i128)] 79 | impl_to_extra_primitive_for_int!(U128); 80 | #[cfg(extprim_has_stable_i128)] 81 | impl_to_extra_primitive_for_int!(I128); 82 | 83 | macro_rules! impl_to_extra_primitive_for_float { 84 | ($float:ty, $d:expr, $e:expr, $f:expr) => { 85 | // static_assert!($e == 127-$d); 86 | // static_assert!($f == 126-$d); 87 | // 88 | impl ToExtraPrimitive for $float { 89 | fn to_u128(&self) -> Option { 90 | let (mantissa, exp, sign) = Float::integer_decode(*self); 91 | Some(match exp { 92 | _ if sign < 0 => u128::zero(), 93 | -$d ... 0 => u128::new(mantissa >> -exp), 94 | 1 ... $e => u128::new(mantissa) << exp, 95 | _ => u128::zero(), 96 | }) 97 | } 98 | 99 | fn to_i128(&self) -> Option { 100 | let (mantissa, exp, sign) = Float::integer_decode(*self); 101 | let abs = match exp { 102 | -$d ... 0 => u128::new(mantissa >> -exp), 103 | 1 ... $f => u128::new(mantissa) << exp, 104 | $e if sign == -1 && mantissa == (1 << $d) => u128::from_parts(0x80000000_00000000, 0), 105 | _ => u128::zero(), 106 | }; 107 | Some(if sign >= 0 { 108 | abs.as_i128() 109 | } else { 110 | abs.wrapping_neg().as_i128() 111 | }) 112 | } 113 | } 114 | } 115 | } 116 | 117 | impl_to_extra_primitive_for_float!(f32, 23, 104, 103); 118 | impl_to_extra_primitive_for_float!(f64, 52, 75, 74); 119 | 120 | #[cfg(test)] 121 | mod float_to_128_tests { 122 | use u128::u128; 123 | use i128::i128; 124 | use traits::ToExtraPrimitive; 125 | use std::{u64, i64, f32, f64}; 126 | 127 | #[test] 128 | fn test_u64_to_u128() { 129 | assert_eq!(0u64.to_u128(), Some(u128::new(0))); 130 | assert_eq!(u64::MAX.to_u128(), Some(u128::new(u64::MAX))); 131 | } 132 | 133 | #[test] 134 | fn test_i64_to_u128() { 135 | assert_eq!(0i64.to_u128(), Some(u128::new(0))); 136 | assert_eq!(i64::MAX.to_u128(), Some(u128::new(0x7fffffff_ffffffff))); 137 | assert_eq!(i64::MIN.to_u128(), None); 138 | } 139 | 140 | #[test] 141 | fn test_u64_to_i128() { 142 | assert_eq!(0u64.to_i128(), Some(i128::new(0))); 143 | assert_eq!(u64::MAX.to_i128(), Some(i128::from_parts(0, u64::MAX))); 144 | } 145 | 146 | #[test] 147 | fn test_i64_to_i128() { 148 | assert_eq!(0i64.to_i128(), Some(i128::new(0))); 149 | assert_eq!(i64::MAX.to_i128(), Some(i128::new(i64::MAX))); 150 | assert_eq!(i64::MIN.to_i128(), Some(i128::new(i64::MIN))); 151 | } 152 | 153 | #[test] 154 | fn test_f64_to_u128() { 155 | assert_eq!(0.0f64.to_u128(), Some(u128::new(0))); 156 | assert_eq!(0.9f64.to_u128(), Some(u128::new(0))); 157 | assert_eq!(1.0f64.to_u128(), Some(u128::new(1))); 158 | assert_eq!(1.9f64.to_u128(), Some(u128::new(1))); 159 | assert_eq!(1.0e19f64.to_u128(), Some(u128::new(10000000000000000000))); 160 | assert_eq!(1.0e20f64.to_u128(), Some(u128::from_parts(5, 7766279631452241920))); 161 | assert_eq!(1.0e38f64.to_u128(), Some(u128::from_parts(5421010862427522048, 0))); 162 | assert_eq!(3.0e38f64.to_u128(), Some(u128::from_parts(16263032587282567168, 0))); 163 | assert_eq!(1.0e39f64.to_u128(), Some(u128::zero())); 164 | assert_eq!(340282366920938425684442744474606501888.0f64.to_u128(), Some(u128::from_parts(0xffffffff_fffff800, 0))); 165 | assert_eq!(340282366920938463463374607431768211456.0f64.to_u128(), Some(u128::zero())); 166 | assert_eq!((-0.0f64).to_u128(), Some(u128::zero())); 167 | assert_eq!((-1.0f64).to_u128(), Some(u128::zero())); 168 | assert_eq!((f64::NAN).to_u128(), Some(u128::zero())); 169 | assert_eq!((f64::MAX).to_u128(), Some(u128::zero())); 170 | assert_eq!((f64::MIN_POSITIVE).to_u128(), Some(u128::zero())); 171 | assert_eq!((f64::INFINITY).to_u128(), Some(u128::zero())); 172 | } 173 | 174 | #[test] 175 | fn test_f64_to_i128() { 176 | assert_eq!(0.0f64.to_i128(), Some(i128::new(0))); 177 | assert_eq!(0.9f64.to_i128(), Some(i128::new(0))); 178 | assert_eq!(1.0f64.to_i128(), Some(i128::new(1))); 179 | assert_eq!(1.9f64.to_i128(), Some(i128::new(1))); 180 | assert_eq!(1.0e19f64.to_i128(), Some(i128::from_parts(0, 10000000000000000000))); 181 | assert_eq!(1.0e20f64.to_i128(), Some(i128::from_parts(5, 7766279631452241920))); 182 | assert_eq!(1.0e38f64.to_i128(), Some(i128::from_parts(5421010862427522048, 0))); 183 | assert_eq!(3.0e38f64.to_i128(), Some(i128::zero())); 184 | assert_eq!(1.0e39f64.to_i128(), Some(i128::zero())); 185 | assert_eq!((-0.0f64).to_i128(), Some(i128::new(0))); 186 | assert_eq!((-0.9f64).to_i128(), Some(i128::new(0))); 187 | assert_eq!((-1.0f64).to_i128(), Some(i128::new(-1))); 188 | assert_eq!((-1.9f64).to_i128(), Some(i128::new(-1))); 189 | assert_eq!((-1.0e20f64).to_i128(), Some(i128::from_parts(-6, 10680464442257309696))); 190 | assert_eq!((-1.0e38f64).to_i128(), Some(i128::from_parts(-5421010862427522048, 0))); 191 | assert_eq!((-1.0e39f64).to_i128(), Some(i128::zero())); 192 | assert_eq!(170141183460469212842221372237303250944.0f64.to_i128(), Some(i128::from_parts(0x7fffffff_fffffc00, 0))); 193 | assert_eq!(170141183460469231731687303715884105728.0f64.to_i128(), Some(i128::zero())); 194 | assert_eq!((-170141183460469231731687303715884105728.0f64).to_i128(), Some(i128::min_value())); 195 | assert_eq!((-170141183460469269510619166673045815296.0f64).to_i128(), Some(i128::zero())); 196 | assert_eq!((f64::NAN).to_i128(), Some(i128::zero())); 197 | assert_eq!((f64::MAX).to_i128(), Some(i128::zero())); 198 | assert_eq!((f64::MIN_POSITIVE).to_i128(), Some(i128::zero())); 199 | assert_eq!((f64::INFINITY).to_i128(), Some(i128::zero())); 200 | } 201 | 202 | #[test] 203 | fn test_f32_to_u128() { 204 | assert_eq!(0.0f32.to_u128(), Some(u128::new(0))); 205 | assert_eq!(0.9f32.to_u128(), Some(u128::new(0))); 206 | assert_eq!(1.0f32.to_u128(), Some(u128::new(1))); 207 | assert_eq!(1.9f32.to_u128(), Some(u128::new(1))); 208 | assert_eq!(1.0e19f32.to_u128(), Some(u128::new(9999999980506447872))); 209 | assert_eq!(1.0e20f32.to_u128(), Some(u128::from_parts(5, 7766281635539976192))); 210 | assert_eq!(1.0e38f32.to_u128(), Some(u128::from_parts(5421010689110048768, 0))); 211 | assert_eq!(3.0e38f32.to_u128(), Some(u128::from_parts(16263032617085960192, 0))); 212 | assert_eq!((-0.0f32).to_u128(), Some(u128::zero())); 213 | assert_eq!((-1.0f32).to_u128(), Some(u128::zero())); 214 | assert_eq!((f32::NAN).to_u128(), Some(u128::zero())); 215 | assert_eq!((f32::MAX).to_u128(), Some(u128::from_parts(0xffffff0000000000, 0))); 216 | assert_eq!((f32::MIN_POSITIVE).to_u128(), Some(u128::zero())); 217 | assert_eq!((f32::INFINITY).to_u128(), Some(u128::zero())); 218 | } 219 | 220 | #[test] 221 | fn test_f32_to_i128() { 222 | assert_eq!(0.0f32.to_i128(), Some(i128::new(0))); 223 | assert_eq!(0.9f32.to_i128(), Some(i128::new(0))); 224 | assert_eq!(1.0f32.to_i128(), Some(i128::new(1))); 225 | assert_eq!(1.9f32.to_i128(), Some(i128::new(1))); 226 | assert_eq!(1.0e19f32.to_i128(), Some(i128::from_parts(0, 9999999980506447872))); 227 | assert_eq!(1.0e20f32.to_i128(), Some(i128::from_parts(5, 7766281635539976192))); 228 | assert_eq!(1.0e38f32.to_i128(), Some(i128::from_parts(5421010689110048768, 0))); 229 | assert_eq!(3.0e38f32.to_i128(), Some(i128::zero())); 230 | assert_eq!((-0.0f32).to_i128(), Some(i128::new(0))); 231 | assert_eq!((-0.9f32).to_i128(), Some(i128::new(0))); 232 | assert_eq!((-1.0f32).to_i128(), Some(i128::new(-1))); 233 | assert_eq!((-1.9f32).to_i128(), Some(i128::new(-1))); 234 | assert_eq!((-1.0e20f32).to_i128(), Some(i128::from_parts(-6, 10680462438169575424))); 235 | assert_eq!((-1.0e38f32).to_i128(), Some(i128::from_parts(-5421010689110048768, 0))); 236 | assert_eq!(170141173319264429905852091742258462720.0f32.to_i128(), Some(i128::from_parts(0x7fffff80_00000000, 0))); 237 | assert_eq!(170141183460469231731687303715884105728.0f32.to_i128(), Some(i128::zero())); 238 | assert_eq!((-170141183460469231731687303715884105728.0f32).to_i128(), Some(i128::min_value())); 239 | assert_eq!((-170141203742878835383357727663135391744.0f32).to_i128(), Some(i128::zero())); 240 | assert_eq!((f32::NAN).to_i128(), Some(i128::zero())); 241 | assert_eq!((f32::MAX).to_i128(), Some(i128::zero())); 242 | assert_eq!((f32::MIN_POSITIVE).to_i128(), Some(i128::zero())); 243 | assert_eq!((f32::INFINITY).to_i128(), Some(i128::zero())); 244 | } 245 | } 246 | 247 | #[cfg(extprim_channel = "unstable")] 248 | impl ToExtraPrimitive for T { 249 | default fn to_u128(&self) -> Option { 250 | ToPrimitive::to_u128(self).map(u128::from_built_in) 251 | } 252 | 253 | default fn to_i128(&self) -> Option { 254 | ToPrimitive::to_i128(self).map(i128::from_built_in) 255 | } 256 | } 257 | 258 | impl NumCast for u128 { 259 | fn from(n: T) -> Option { 260 | #[cfg(extprim_has_stable_i128)] { 261 | ToPrimitive::to_u128(&n).map(u128::from_built_in) 262 | } 263 | #[cfg(not(extprim_has_stable_i128))] { 264 | panic!("cannot use this before Rust 1.26.0"); 265 | } 266 | } 267 | } 268 | 269 | impl NumCast for i128 { 270 | fn from(n: T) -> Option { 271 | #[cfg(extprim_has_stable_i128)] { 272 | ToPrimitive::to_i128(&n).map(i128::from_built_in) 273 | } 274 | #[cfg(not(extprim_has_stable_i128))] { 275 | panic!("cannot use this before Rust 1.26.0"); 276 | } 277 | } 278 | } 279 | 280 | #[cfg(all(extprim_has_stable_i128, test))] 281 | mod num_cast_tests { 282 | use std::u64; 283 | use num_traits::NumCast; 284 | use u128::u128; 285 | use i128::i128; 286 | 287 | #[test] 288 | fn test_num_cast_for_u128() { 289 | assert_eq!(None::, NumCast::from(-1i8)); // sanity check. 290 | assert_eq!(None::, NumCast::from(-1i8)); 291 | assert_eq!(Some(u128::one()), NumCast::from(1i8)); 292 | assert_eq!(Some(u128::new(u64::MAX)), NumCast::from(u64::MAX)); 293 | assert_eq!(Some(u128::max_value()), NumCast::from(u128::max_value())); 294 | 295 | assert_eq!(Some(u128::one()), NumCast::from(i128::new(1))); 296 | assert_eq!(None::, NumCast::from(i128::new(-1))); 297 | } 298 | 299 | #[test] 300 | fn test_num_cast_for_i128() { 301 | assert_eq!(None::, NumCast::from(0x8000_0000_0000_0000u64)); // sanity check. 302 | assert_eq!(None::, NumCast::from(u128::max_value())); 303 | assert_eq!(Some(i128::one()), NumCast::from(1i8)); 304 | assert_eq!(Some(-i128::one()), NumCast::from(-1i8)); 305 | assert_eq!(Some(i128::from_parts(0, 0x8000_0000_0000_0000)), NumCast::from(0x8000_0000_0000_0000u64)); 306 | assert_eq!(Some(i128::max_value()), NumCast::from(i128::max_value())); 307 | assert_eq!(Some(i128::min_value()), NumCast::from(i128::min_value())); 308 | 309 | assert_eq!(Some(i128::one()), NumCast::from(i128::new(1))); 310 | assert_eq!(None::, NumCast::from(u128::from_parts(0x8000_0000_0000_0000, 0))); 311 | } 312 | } 313 | 314 | /// Wrapper for `u128` and `i128` to turn arithmetic operators to wrapping ones. 315 | /// 316 | /// Equivalent to `std::num::Wrapping`, but due to E0117 (orphan rule) we need to define it here to 317 | /// implement operators on it. 318 | #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default)] 319 | pub struct Wrapping(pub T); 320 | 321 | /// Raise `base` to the power of `exp`, using exponentiation by squaring. 322 | /// 323 | /// # Examples 324 | /// 325 | /// ```rust 326 | /// use extprim::traits::pow; 327 | /// 328 | /// assert_eq!(pow(10u64, 7), 10000000u64); 329 | /// ``` 330 | #[deprecated(since="1.1.1", note="please use `num_traits::pow` instead")] 331 | pub fn pow(mut base: T, mut exp: u32) -> T { 332 | let mut acc = T::one(); 333 | 334 | while exp > 1 { 335 | if (exp & 1) == 1 { 336 | acc *= base; 337 | } 338 | exp /= 2; 339 | base *= base; 340 | } 341 | 342 | if exp == 1 { 343 | acc *= base; 344 | } 345 | acc 346 | } 347 | 348 | /// Parses a Rust integer literal into an actual integral type. 349 | /// 350 | /// If `is_negative` is true, a negative sign will be added to the string before the conversion. 351 | /// 352 | /// # Examples 353 | /// 354 | /// ```rust 355 | /// use extprim::traits::parse_rust_int_lit; 356 | /// use extprim::u128::u128; 357 | /// use extprim::i128::i128; 358 | /// 359 | /// assert_eq!(parse_rust_int_lit::("100_000", false).unwrap(), u128::new(100_000)); 360 | /// assert_eq!(parse_rust_int_lit::("0xffffffff_ffffffff_22222222_22222222", false).unwrap(), 361 | /// u128::from_parts(0xffffffff_ffffffff, 0x22222222_22222222)); 362 | /// assert_eq!(parse_rust_int_lit::("0b111", true).unwrap(), i128::new(-0b111)); 363 | /// assert_eq!(parse_rust_int_lit::("0x80000000_00000000_00000000_00000000", true).unwrap(), 364 | /// i128::min_value()); 365 | /// ``` 366 | #[cfg(feature="use-std")] // TODO should be usable even without std. 367 | pub fn parse_rust_int_lit(s: &str, is_negative: bool) -> Result { 368 | let mut c = s.chars(); 369 | let (base, digits) = if c.next() != Some('0') { 370 | (10, s) 371 | } else { 372 | match c.next() { 373 | Some('b') | Some('B') => (2, c.as_str()), 374 | Some('o') | Some('O') => (8, c.as_str()), 375 | Some('x') | Some('X') => (16, c.as_str()), 376 | _ => (10, s), 377 | } 378 | }; 379 | 380 | let sign = if is_negative { "-" } else { "" }; 381 | let digits = format!("{}{}", sign, digits.replace("_", "")); 382 | T::from_str_radix(&digits, base) 383 | } 384 | 385 | --------------------------------------------------------------------------------