typenum-1.11.2/.gitignore010066400037200003720000000000341353070170400135030ustar0000000000000000target Cargo.lock *.bk *\~ typenum-1.11.2/.travis.yml010066400037200003720000000045351353070170400136360ustar0000000000000000language: rust cache: cargo sudo: false rust: - beta - nightly - 1.22.0 notifications: email: recipients: paho@paholg.com matrix: include: - rust: stable before_script: - rustup component add rustfmt-preview - rustup component add clippy script: | cargo fmt --all -- --check && cargo clippy -- -D warnings && cargo clippy --all-features -- -D warnings && cargo build --features "no_std strict" && cargo test --features "no_std strict" && cargo doc --features "no_std strict" after_success: - test $TRAVIS_PULL_REQUEST == "false" && test $TRAVIS_BRANCH == "master" && cargo publish --token ${CRATESIO_TOKEN} script: | cargo build --features "no_std strict" && cargo test --features "no_std strict" && cargo doc --features "no_std strict" env: global: # GitHub SSH stuff - COMMIT_AUTHOR_EMAIL: "paho@paholg.com" # GH_TOKEN - secure: "jEnVq9nswc2mm2A77SEI5C9ytubHrAGpMu9mqF+wr7GoaGee48LjA5OkawY3VHzreB+3djy3LO6h+JUTkKN699KRZt+RvyIBR+yY1C5O+5IwY3k5pZn/Bm4xJZfeGfRwnZ9UYl1iNEAy+yHverMcQC+Lv5wzCSRCmTa18FQpKBeYKsdXfPP1wa+PWbei3bBrO0tBxuiIA5BZUuK8QqYXluUPxKETvJxtdKgFOUbMbf4DDJ4igOrt9OZQQxKrTZWDy+5Hwv4wMh2cir3ExYuM/8dfBewxxGOty1dlZWAUAFsIJ6Ww/mhEAGtsPYjqh3tB5G5JEss2FSvLuYJcKpA9p/mf+K4tagRVF68AydjQISWVBjOarwln2+HzK9tcykfyO8fGIUNgf0ptuZETA95g3BxwKF3O0LvhGJG2QOas8Bjqpdrg3iDoT5QGy2j8DnQLL7HgM31oCvzu1BOqDn3EvRSjwWpmBpXFz/FeUoRdIX1fOZpgw3cYWTpsT/mqW+mUfO98wTHKn3QBOnskLwf9AteTmJwsdx9Kdc4e1a3BqJE/UGNZv16SnVNtun+zMQ3P84HplvCIXL5k2pUDAUpDQne9nxmZ5ADpQJQluDosA5ydtbl+Z6x2o+zGrBOlo1vxoL/x4uuAFYyiwh1DUGyNgN9x2m1A3WtqqzXX5H4XwZ0=" # CRATESIO_TOKEN - secure: "cchJKaN5hM2ceBpLqDokhUWFUyFubTlrUxj8d/5JjDXOxVvpZQWQuPxihnSyz0U+GSY4HwUh8C9+jRe2i8UBmhS6pPMG4Bl0Xo2T1HU9ilWb43vSqsbg77UgQ2SELNd+7g1xSI/UTsaFH0YlTOw7DsF6plruVduyOy8C44Ox1nAo4hIgN1ThRs9nhKTWydREr2zRQ/7n4c99RnPQz54ITnrHx/Ks2bvy3zgTOP7CeiQQJKh521U5tuH23r48eljje7776UA4Jbs2j1LsnMaBsraadIzNMopEwaSE1oNLOobfWG9YzvyTZ2i4yElDX4A7tscwo631Ig5AUH2+QbvN2k0q2EKETQJ9Mov5OSmK3aeMSW1GA3hQ44Uvz0F7SZru8D84sKgfSXNbfck1hTVfBPPOpmUIKDb+rSthulYq2SW2XG9cpVXrJmhYD2WTNKEuSmw7imVbTCPS03dbbMoLchpmOBkcgLtcMNDyC94xdZYSkyz9+RCG0bEfwIu9oG7o6gv+8a42pgVSP8mfOOq0+MELHntIqumlmTO0jGGH10Prs4Pgs8eVn6S84w+oz8yrbYroVaqrI2TZl73KnOmvAlnYZdCSIBGV5XsTukzochfwgaTKWI2h2iK1yt6k5I5ZgOoVlTUPB4ElwhIDfgYhc7fltHd53EO81GHGDPSI49M=" typenum-1.11.2/CHANGELOG.md010066400037200003720000000060771353070170400133410ustar0000000000000000# Changelog This project follows semantic versioning. The MSRV (Minimum Supported Rust Version) is 1.22.0, and typenum is tested against this Rust version. Much of typenum should work on as low a version as 1.20.0, but that is not guaranteed. ### Unreleased ### 1.11.2 (2019-08-26) - [fixed] Cross compilation from Linux to Windows. ### 1.11.1 (2019-08-25) - [fixed] Builds on earlier Rust builds again and added Rust 1.22.0 to Travis to prevent future breakage. ### 1.11.0 (2019-08-25) - [added] Integer `log2` to the `op!` macro. - [added] Integer binary logarithm operator `Logarithm2` with alias `Log2`. - [changed] Removed `feature(i128_type)` when running with the `i128` feature. Kept the feature flag. for typenum to maintain compatibility with old Rust versions. - [added] Integer `sqrt` to the `op!` macro. - [added] Integer square root operator `SquareRoot` with alias `Sqrt`. - [fixed] Bug with attempting to create U1024 type alias twice. ### 1.10.0 (2018-03-11) - [added] The `PowerOfTwo` marker trait. - [added] Associated constants for `Bit`, `Unsigned`, and `Integer`. ### 1.9.0 (2017-05-14) - [added] The `Abs` type operater and corresponding `AbsVal` alias. - [added] The feature `i128` that enables creating 128-bit integers from typenums. - [added] The `assert_type!` and `assert_type_eq!` macros. - [added] Operators to the `op!` macro, including those performed by `cmp!`. - [fixed] Bug in `op!` macro involving functions and convoluted expressions. - [deprecated] The `cmp!` macro. ### 1.8.0 (2017-04-12) - [added] The `op!` macro for conveniently performing type-level operations. - [added] The `cmp!` macro for conveniently performing type-level comparisons. - [added] Some comparison type-operators that are used by the `cmp!` macro. ### 1.7.0 (2017-03-24) - [added] Type operators `Min` and `Max` with accompanying aliases `Minimum` and `Maximum` ### 1.6.0 (2017-02-24) - [fixed] Bug in `Array` division. - [fixed] Bug where `Rem` would sometimes exit early with the wrong answer. - [added] `PartialDiv` operator that performs division as a partial function -- it's defined only when there is no remainder. ### 1.5.2 (2017-02-04) - [fixed] Bug between `Div` implementation and type system. ### 1.5.1 (2016-11-08) - [fixed] Expanded implementation of `Pow` for primitives. ### 1.5.0 (2016-11-03) - [added] Functions to the `Pow` and `Len` traits. This is *technically* a breaking change, but it would only break someone's code if they have a custom impl for `Pow`. I would be very surprised if that is anyone other than me. ### 1.4.0 (2016-10-29) - [added] Type-level arrays of type-level integers. (PR #66) - [added] The types in this crate are now instantiable. (Issue #67, PR #68) ### 1.3.1 (2016-03-31) - [fixed] Bug with recent nightlies. ### 1.3.0 (2016-02-07) - [changed] Removed dependency on libstd. (Issue #53, PR #55) - [changed] Reorganized module structure. (PR #57) ### 1.2.0 (2016-01-03) - [added] This change log! - [added] Convenience type aliases for operators. (Issue #48, PR #50) - [added] Types in this crate now derive all possible traits. (Issue #42, PR #51) typenum-1.11.2/Cargo.toml.orig010066400037200003720000000012571353070170400144120ustar0000000000000000[package] name = "typenum" build = "build/main.rs" version = "1.11.2" authors = [ "Paho Lurie-Gregg ", "Andre Bogus " ] documentation = "https://docs.rs/typenum" repository = "https://github.com/paholg/typenum" readme = "README.md" license = "MIT/Apache-2.0" description = "Typenum is a Rust library for type-level numbers evaluated at compile time. It currently supports bits, unsigned integers, and signed integers. It also provides a type-level array of type-level numbers, but its implementation is incomplete." categories = ["no-std"] [lib] name = "typenum" [features] no_std = [] i128 = [] strict = [] typenum-1.11.2/Cargo.toml0000644000000022240000000000000106540ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "typenum" version = "1.11.2" authors = ["Paho Lurie-Gregg ", "Andre Bogus "] build = "build/main.rs" description = "Typenum is a Rust library for type-level numbers evaluated at compile time. It currently supports bits, unsigned integers, and signed integers. It also provides a type-level array of type-level numbers, but its implementation is incomplete." documentation = "https://docs.rs/typenum" readme = "README.md" categories = ["no-std"] license = "MIT/Apache-2.0" repository = "https://github.com/paholg/typenum" [lib] name = "typenum" [features] i128 = [] no_std = [] strict = [] typenum-1.11.2/LICENSE010066400037200003720000000020731353070170400125250ustar0000000000000000The MIT License (MIT) Copyright (c) 2014 Paho Lurie-Gregg Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. typenum-1.11.2/README.md010066400037200003720000000027231353070170400130010ustar0000000000000000[![crates.io](https://img.shields.io/crates/v/typenum.svg)](https://crates.io/crates/typenum) [![Build Status](https://travis-ci.org/paholg/typenum.svg?branch=master)](https://travis-ci.org/paholg/typenum) Typenum ===== Typenum is a Rust library for type-level numbers evaluated at compile time. It currently supports bits, unsigned integers, and signed integers. Typenum depends only on libcore, and so is suitable for use on any platform! For the full documentation, go [here](https://docs.rs/typenum). ### Importing While `typenum` is divided into several modules, they are all re-exported through the crate root, so you can import anything contained herein with `use typenum::whatever;`, ignoring the crate structure. You may also find it useful to treat the `consts` module as a prelude, perfoming a glob import. ### Example Here is a trivial example of `typenum`'s use: ```rust use typenum::{Sum, Exp, Integer, N2, P3, P4}; type X = Sum; assert_eq!(::to_i32(), 7); type Y = Exp; assert_eq!(::to_i32(), -8); ``` For a non-trivial example of its use, see one of the crates that depends on it. The full list is [here](https://crates.io/crates/typenum/reverse_dependencies). Of note are [dimensioned](https://crates.io/crates/dimensioned/) which does compile-time type checking for arbitrary unit systems and [generic-array](https://crates.io/crates/generic-array/) which provides arrays whose length you can generically refer to. typenum-1.11.2/build/main.rs010066400037200003720000000105731353070170400141150ustar0000000000000000use std::env; use std::fmt; use std::fs::File; use std::io::Write; use std::path::Path; mod op; #[cfg(tests)] mod tests; pub enum UIntCode { Term, Zero(Box), One(Box), } pub enum IntCode { Zero, Pos(Box), Neg(Box), } impl fmt::Display for UIntCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { UIntCode::Term => write!(f, "UTerm"), UIntCode::Zero(ref inner) => write!(f, "UInt<{}, B0>", inner), UIntCode::One(ref inner) => write!(f, "UInt<{}, B1>", inner), } } } impl fmt::Display for IntCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { IntCode::Zero => write!(f, "Z0"), IntCode::Pos(ref inner) => write!(f, "PInt<{}>", inner), IntCode::Neg(ref inner) => write!(f, "NInt<{}>", inner), } } } pub fn gen_uint(u: u64) -> UIntCode { let mut result = UIntCode::Term; let mut x = 1u64 << 63; while x > u { x >>= 1 } while x > 0 { result = if x & u > 0 { UIntCode::One(Box::new(result)) } else { UIntCode::Zero(Box::new(result)) }; x >>= 1; } result } pub fn gen_int(i: i64) -> IntCode { if i > 0 { IntCode::Pos(Box::new(gen_uint(i as u64))) } else if i < 0 { IntCode::Neg(Box::new(gen_uint(i.abs() as u64))) } else { IntCode::Zero } } #[cfg_attr( feature = "no_std", deprecated( since = "1.3.0", note = "the `no_std` flag is no longer necessary and will be removed in the future" ) )] pub fn no_std() {} // fixme: get a warning when testing without this #[allow(dead_code)] fn main() { let highest: u64 = 1024; let first2: u32 = (highest as f64).log(2.0).round() as u32 + 1; let first10: u32 = (highest as f64).log(10.0) as u32 + 1; let uints = (0..(highest + 1)) .chain((first2..64).map(|i| 2u64.pow(i))) .chain((first10..20).map(|i| 10u64.pow(i))); let out_dir = env::var("OUT_DIR").unwrap(); let dest = Path::new(&out_dir).join("consts.rs"); println!("cargo:rustc-env=TYPENUM_BUILD_OP={}", dest.display()); let mut f = File::create(&dest).unwrap(); no_std(); // Header stuff here! write!( f, " /** Type aliases for many constants. This file is generated by typenum's build script. For unsigned integers, the format is `U` followed by the number. We define aliases for - Numbers 0 through {highest} - Powers of 2 below `u64::MAX` - Powers of 10 below `u64::MAX` These alias definitions look like this: ```rust use typenum::{{B0, B1, UInt, UTerm}}; # #[allow(dead_code)] type U6 = UInt, B1>, B0>; ``` For positive signed integers, the format is `P` followed by the number and for negative signed integers it is `N` followed by the number. For the signed integer zero, we use `Z0`. We define aliases for - Numbers -{highest} through {highest} - Powers of 2 between `i64::MIN` and `i64::MAX` - Powers of 10 between `i64::MIN` and `i64::MAX` These alias definitions look like this: ```rust use typenum::{{B0, B1, UInt, UTerm, PInt, NInt}}; # #[allow(dead_code)] type P6 = PInt, B1>, B0>>; # #[allow(dead_code)] type N6 = NInt, B1>, B0>>; ``` # Example ```rust # #[allow(unused_imports)] use typenum::{{U0, U1, U2, U3, U4, U5, U6}}; # #[allow(unused_imports)] use typenum::{{N3, N2, N1, Z0, P1, P2, P3}}; # #[allow(unused_imports)] use typenum::{{U774, N17, N10000, P1024, P4096}}; ``` We also define the aliases `False` and `True` for `B0` and `B1`, respectively. */ #[allow(missing_docs)] pub mod consts {{ use uint::{{UInt, UTerm}}; use int::{{PInt, NInt}}; pub use bit::{{B0, B1}}; pub use int::Z0; pub type True = B1; pub type False = B0; ", highest = highest ) .unwrap(); for u in uints { write!(f, " pub type U{} = {};\n", u, gen_uint(u)).unwrap(); if u <= ::std::i64::MAX as u64 && u != 0 { let i = u as i64; write!( f, " pub type P{i} = PInt; pub type N{i} = NInt;\n", i = i ) .unwrap(); } } write!(f, "}}").unwrap(); #[cfg(tests)] tests::build_tests().unwrap(); op::write_op_macro().unwrap(); } typenum-1.11.2/build/op.rs010066400037200003720000000354761353070170400136200ustar0000000000000000#[derive(Debug, Copy, Clone, Eq, PartialEq)] enum OpType { Operator, Function, } use self::OpType::*; struct Op { token: &'static str, operator: &'static str, example: (&'static str, &'static str), precedence: u8, n_args: u8, op_type: OpType, } pub fn write_op_macro() -> ::std::io::Result<()> { let out_dir = ::std::env::var("OUT_DIR").unwrap(); let dest = ::std::path::Path::new(&out_dir).join("op.rs"); println!("cargo:rustc-env=TYPENUM_BUILD_CONSTS={}", dest.display()); let mut f = ::std::fs::File::create(&dest).unwrap(); // Operator precedence is taken from // https://doc.rust-lang.org/reference.html#operator-precedence // // We choose 16 as the highest precedence (functions are set to 255 but it doesn't matter // for them). We also only use operators that are left associative so we don't have to worry // about that. let ops = &[ Op { token: "*", operator: "Prod", example: ("P2 * P3", "P6"), precedence: 16, n_args: 2, op_type: Operator, }, Op { token: "/", operator: "Quot", example: ("P6 / P2", "P3"), precedence: 16, n_args: 2, op_type: Operator, }, Op { token: "%", operator: "Mod", example: ("P5 % P3", "P2"), precedence: 16, n_args: 2, op_type: Operator, }, Op { token: "+", operator: "Sum", example: ("P2 + P3", "P5"), precedence: 15, n_args: 2, op_type: Operator, }, Op { token: "-", operator: "Diff", example: ("P2 - P3", "N1"), precedence: 15, n_args: 2, op_type: Operator, }, Op { token: "<<", operator: "Shleft", example: ("U1 << U5", "U32"), precedence: 14, n_args: 2, op_type: Operator, }, Op { token: ">>", operator: "Shright", example: ("U32 >> U5", "U1"), precedence: 14, n_args: 2, op_type: Operator, }, Op { token: "&", operator: "And", example: ("U5 & U3", "U1"), precedence: 13, n_args: 2, op_type: Operator, }, Op { token: "^", operator: "Xor", example: ("U5 ^ U3", "U6"), precedence: 12, n_args: 2, op_type: Operator, }, Op { token: "|", operator: "Or", example: ("U5 | U3", "U7"), precedence: 11, n_args: 2, op_type: Operator, }, Op { token: "==", operator: "Eq", example: ("P5 == P3 + P2", "True"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: "!=", operator: "NotEq", example: ("P5 != P3 + P2", "False"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: "<=", operator: "LeEq", example: ("P6 <= P3 + P2", "False"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: ">=", operator: "GrEq", example: ("P6 >= P3 + P2", "True"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: "<", operator: "Le", example: ("P4 < P3 + P2", "True"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: ">", operator: "Gr", example: ("P5 < P3 + P2", "False"), precedence: 10, n_args: 2, op_type: Operator, }, Op { token: "cmp", operator: "Compare", example: ("cmp(P2, P3)", "Less"), precedence: !0, n_args: 2, op_type: Function, }, Op { token: "sqr", operator: "Square", example: ("sqr(P2)", "P4"), precedence: !0, n_args: 1, op_type: Function, }, Op { token: "sqrt", operator: "Sqrt", example: ("sqrt(U9)", "U3"), precedence: !0, n_args: 1, op_type: Function, }, Op { token: "abs", operator: "AbsVal", example: ("abs(N2)", "P2"), precedence: !0, n_args: 1, op_type: Function, }, Op { token: "cube", operator: "Cube", example: ("cube(P2)", "P8"), precedence: !0, n_args: 1, op_type: Function, }, Op { token: "pow", operator: "Exp", example: ("pow(P2, P3)", "P8"), precedence: !0, n_args: 2, op_type: Function, }, Op { token: "min", operator: "Minimum", example: ("min(P2, P3)", "P2"), precedence: !0, n_args: 2, op_type: Function, }, Op { token: "max", operator: "Maximum", example: ("max(P2, P3)", "P3"), precedence: !0, n_args: 2, op_type: Function, }, Op { token: "log2", operator: "Log2", example: ("log2(U9)", "U3"), precedence: !0, n_args: 1, op_type: Function, }, ]; use std::io::Write; write!( f, " /** Convenient type operations. Any types representing values must be able to be expressed as `ident`s. That means they need to be in scope. For example, `P5` is okay, but `typenum::P5` is not. You may combine operators arbitrarily, although doing so excessively may require raising the recursion limit. # Example ```rust #![recursion_limit=\"128\"] #[macro_use] extern crate typenum; use typenum::consts::*; fn main() {{ assert_type!( op!(min((P1 - P2) * (N3 + N7), P5 * (P3 + P4)) == P10) ); }} ``` Operators are evaluated based on the operator precedence outlined [here](https://doc.rust-lang.org/reference.html#operator-precedence). The full list of supported operators and functions is as follows: {} They all expand to type aliases defined in the `operator_aliases` module. Here is an expanded list, including examples: ", ops.iter() .map(|op| format!("`{}`", op.token)) .collect::>() .join(", ") )?; //write!(f, "Token | Alias | Example\n ===|===|===\n")?; for op in ops.iter() { write!( f, "---\nOperator `{token}`. Expands to `{operator}`. ```rust # #[macro_use] extern crate typenum; # use typenum::*; # fn main() {{ assert_type_eq!(op!({ex0}), {ex1}); # }} ```\n ", token = op.token, operator = op.operator, ex0 = op.example.0, ex1 = op.example.1 )?; } write!( f, "*/ #[macro_export] macro_rules! op {{ ($($tail:tt)*) => ( __op_internal__!($($tail)*) ); }} #[doc(hidden)] #[macro_export] macro_rules! __op_internal__ {{ " )?; // We first us the shunting-yard algorithm to produce our tokens in Polish notation. // See: https://en.wikipedia.org/wiki/Shunting-yard_algorithm // Note: Due to macro asymmetry, "the top of the stack" refers to the first element, not the // last // ----------------------------------------------------------------------------------------- // Stage 1: There are tokens to be read: // ------- // Case 1: Token is a function => Push it onto the stack: for fun in ops.iter().filter(|f| f.op_type == Function) { write!( f, " (@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {f_token} $($tail:tt)*) => ( __op_internal__!(@stack[{f_op}, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) );", f_token = fun.token, f_op = fun.operator )?; } // ------- // Case 2: Token is a comma => Until the top of the stack is a LParen, // Pop operators from stack to queue // Base case: Top of stack is LParen, ditch comma and continue write!( f, " (@stack[LParen, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: , $($tail:tt)*) => ( __op_internal__!(@stack[LParen, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) );" )?; // Recursive case: Not LParen, pop from stack to queue write!( f, " (@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: , $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: , $($tail)*) );" )?; // ------- // Case 3: Token is an operator, o1: for o1 in ops.iter().filter(|op| op.op_type == Operator) { // If top of stack is operator o2 with o1.precedence <= o2.precedence, // Then pop o2 off stack onto queue: for o2 in ops .iter() .filter(|op| op.op_type == Operator) .filter(|o2| o1.precedence <= o2.precedence) { write!( f, " (@stack[{o2_op}, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {o1_token} $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[{o2_op}, $($queue,)*] @tail: {o1_token} $($tail)*) );", o2_op = o2.operator, o1_token = o1.token )?; } // Base case: push o1 onto stack write!( f, " (@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {o1_token} $($tail:tt)*) => ( __op_internal__!(@stack[{o1_op}, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) );", o1_op = o1.operator, o1_token = o1.token )?; } // ------- // Case 4: Token is "(": push it onto stack as "LParen". Also convert the ")" to "RParen" to // appease the macro gods: write!( f, " (@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: ( $($stuff:tt)* ) $($tail:tt)* ) => ( __op_internal__!(@stack[LParen, $($stack,)*] @queue[$($queue,)*] @tail: $($stuff)* RParen $($tail)*) );" )?; // ------- // Case 5: Token is "RParen": // 1. Pop from stack to queue until we see an "LParen", // 2. Kill the "LParen", // 3. If the top of the stack is a function, pop it onto the queue // 2. Base case: write!( f, " (@stack[LParen, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: RParen $($tail:tt)*) => ( __op_internal__!(@rp3 @stack[$($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) );" )?; // 1. Recursive case: write!( f, " (@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: RParen $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: RParen $($tail)*) );" )?; // 3. Check for function: for fun in ops.iter().filter(|f| f.op_type == Function) { write!( f, " (@rp3 @stack[{fun_op}, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[{fun_op}, $($queue,)*] @tail: $($tail)*) );", fun_op = fun.operator )?; } // 3. If no function found: write!( f, " (@rp3 @stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[$($queue,)*] @tail: $($tail)*) );" )?; // ------- // Case 6: Token is a number: Push it onto the queue write!( f, " (@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $num:ident $($tail:tt)*) => ( __op_internal__!(@stack[$($stack,)*] @queue[$num, $($queue,)*] @tail: $($tail)*) );" )?; // ------- // Case 7: Out of tokens: // Base case: Stack empty: Start evaluating write!( f, " (@stack[] @queue[$($queue:ident,)*] @tail: ) => ( __op_internal__!(@reverse[] @input: $($queue,)*) );" )?; // Recursive case: Pop stack to queue write!( f, " (@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail:) => ( __op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: ) );" )?; // ----------------------------------------------------------------------------------------- // Stage 2: Reverse so we have RPN write!( f, " (@reverse[$($revved:ident,)*] @input: $head:ident, $($tail:ident,)* ) => ( __op_internal__!(@reverse[$head, $($revved,)*] @input: $($tail,)*) );" )?; write!( f, " (@reverse[$($revved:ident,)*] @input: ) => ( __op_internal__!(@eval @stack[] @input[$($revved,)*]) );" )?; // ----------------------------------------------------------------------------------------- // Stage 3: Evaluate in Reverse Polish Notation // Operators / Operators with 2 args: for op in ops.iter().filter(|op| op.n_args == 2) { // Note: We have to switch $a and $b here, otherwise non-commutative functions are backwards write!( f, " (@eval @stack[$a:ty, $b:ty, $($stack:ty,)*] @input[{op}, $($tail:ident,)*]) => ( __op_internal__!(@eval @stack[$crate::{op}<$b, $a>, $($stack,)*] @input[$($tail,)*]) );", op = op.operator )?; } // Operators with 1 arg: for op in ops.iter().filter(|op| op.n_args == 1) { write!( f, " (@eval @stack[$a:ty, $($stack:ty,)*] @input[{op}, $($tail:ident,)*]) => ( __op_internal__!(@eval @stack[$crate::{op}<$a>, $($stack,)*] @input[$($tail,)*]) );", op = op.operator )?; } // Wasn't a function or operator, so must be a value => push onto stack write!( f, " (@eval @stack[$($stack:ty,)*] @input[$head:ident, $($tail:ident,)*]) => ( __op_internal__!(@eval @stack[$head, $($stack,)*] @input[$($tail,)*]) );" )?; // No input left: write!( f, " (@eval @stack[$stack:ty,] @input[]) => ( $stack );" )?; // ----------------------------------------------------------------------------------------- // Stage 0: Get it started write!( f, " ($($tail:tt)* ) => ( __op_internal__!(@stack[] @queue[] @tail: $($tail)*) );" )?; write!( f, " }}" )?; Ok(()) } typenum-1.11.2/build/tests.rs010066400037200003720000000201251353070170400143250ustar0000000000000000use std::{env, fmt, fs, io, path}; use super::{gen_int, gen_uint}; fn sign(i: i64) -> char { if i > 0 { 'P' } else if i < 0 { 'N' } else { '_' } } struct UIntTest { a: u64, op: &'static str, b: Option, r: u64, } impl fmt::Display for UIntTest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.b { Some(b) => write!( f, " #[test] #[allow(non_snake_case)] fn test_{a}_{op}_{b}() {{ type A = {gen_a}; type B = {gen_b}; type U{r} = {result}; #[allow(non_camel_case_types)] type U{a}{op}U{b} = <>::Output as Same>::Output; assert_eq!(::to_u64(), ::to_u64()); }}", gen_a = gen_uint(self.a), gen_b = gen_uint(b), r = self.r, result = gen_uint(self.r), a = self.a, b = b, op = self.op ), None => write!( f, " #[test] #[allow(non_snake_case)] fn test_{a}_{op}() {{ type A = {gen_a}; type U{r} = {result}; #[allow(non_camel_case_types)] type {op}U{a} = <::Output as Same>::Output; assert_eq!(<{op}U{a} as Unsigned>::to_u64(), ::to_u64()); }}", gen_a = gen_uint(self.a), r = self.r, result = gen_uint(self.r), a = self.a, op = self.op ), } } } fn uint_binary_test(a: u64, op: &'static str, b: u64, result: u64) -> UIntTest { UIntTest { a: a, op: op, b: Option::Some(b), r: result, } } // fn uint_unary_test(op: &'static str, a: u64, result: u64) -> UIntTest { // UIntTest { a: a, op: op, b: Option::None, r: result } // } struct IntBinaryTest { a: i64, op: &'static str, b: i64, r: i64, } impl fmt::Display for IntBinaryTest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, " #[test] #[allow(non_snake_case)] fn test_{sa}{a}_{op}_{sb}{b}() {{ type A = {gen_a}; type B = {gen_b}; type {sr}{r} = {result}; #[allow(non_camel_case_types)] type {sa}{a}{op}{sb}{b} = <>::Output as Same<{sr}{r}>>::Output; assert_eq!(<{sa}{a}{op}{sb}{b} as Integer>::to_i64(), <{sr}{r} as Integer>::to_i64()); }}", gen_a = gen_int(self.a), gen_b = gen_int(self.b), r = self.r.abs(), sr = sign(self.r), result = gen_int(self.r), a = self.a.abs(), b = self.b.abs(), sa = sign(self.a), sb = sign(self.b), op = self.op ) } } fn int_binary_test(a: i64, op: &'static str, b: i64, result: i64) -> IntBinaryTest { IntBinaryTest { a: a, op: op, b: b, r: result, } } struct IntUnaryTest { op: &'static str, a: i64, r: i64, } impl fmt::Display for IntUnaryTest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, " #[test] #[allow(non_snake_case)] fn test_{sa}{a}_{op}() {{ type A = {gen_a}; type {sr}{r} = {result}; #[allow(non_camel_case_types)] type {op}{sa}{a} = <::Output as Same<{sr}{r}>>::Output; assert_eq!(<{op}{sa}{a} as Integer>::to_i64(), <{sr}{r} as Integer>::to_i64()); }}", gen_a = gen_int(self.a), r = self.r.abs(), sr = sign(self.r), result = gen_int(self.r), a = self.a.abs(), sa = sign(self.a), op = self.op ) } } fn int_unary_test(op: &'static str, a: i64, result: i64) -> IntUnaryTest { IntUnaryTest { op: op, a: a, r: result, } } fn uint_cmp_test(a: u64, b: u64) -> String { format!( " #[test] #[allow(non_snake_case)] fn test_{a}_cmp_{b}() {{ type A = {gen_a}; type B = {gen_b}; #[allow(non_camel_case_types)] type U{a}CmpU{b} = >::Output; assert_eq!(::to_ordering(), Ordering::{result:?}); }}", a = a, b = b, gen_a = gen_uint(a), gen_b = gen_uint(b), result = a.cmp(&b) ) } fn int_cmp_test(a: i64, b: i64) -> String { format!( " #[test] #[allow(non_snake_case)] fn test_{sa}{a}_cmp_{sb}{b}() {{ type A = {gen_a}; type B = {gen_b}; #[allow(non_camel_case_types)] type {sa}{a}Cmp{sb}{b} = >::Output; assert_eq!(<{sa}{a}Cmp{sb}{b} as Ord>::to_ordering(), Ordering::{result:?}); }}", a = a.abs(), b = b.abs(), sa = sign(a), sb = sign(b), gen_a = gen_int(a), gen_b = gen_int(b), result = a.cmp(&b) ) } pub fn build_tests() -> Result<(), Box<::std::error::Error>> { // will test all permutations of number pairs up to this (and down to its opposite for ints) let high: i64 = 5; let uints = (0u64..high as u64 + 1).flat_map(|a| (a..a + 1).cycle().zip(0..high as u64 + 1)); let ints = (-high..high + 1).flat_map(|a| (a..a + 1).cycle().zip(-high..high + 1)); let out_dir = env::var("OUT_DIR")?; let dest = path::Path::new(&out_dir).join("tests.rs"); let f = fs::File::create(&dest)?; let mut writer = io::BufWriter::new(&f); use std::io::Write; writer.write( b" extern crate typenum; use std::ops::*; use std::cmp::Ordering; use typenum::*; ", )?; use std::cmp; // uint operators: for (a, b) in uints { write!(writer, "{}", uint_binary_test(a, "BitAnd", b, a & b))?; write!(writer, "{}", uint_binary_test(a, "BitOr", b, a | b))?; write!(writer, "{}", uint_binary_test(a, "BitXor", b, a ^ b))?; write!(writer, "{}", uint_binary_test(a, "Shl", b, a << b))?; write!(writer, "{}", uint_binary_test(a, "Shr", b, a >> b))?; write!(writer, "{}", uint_binary_test(a, "Add", b, a + b))?; write!(writer, "{}", uint_binary_test(a, "Min", b, cmp::min(a, b)))?; write!(writer, "{}", uint_binary_test(a, "Max", b, cmp::max(a, b)))?; if a >= b { write!(writer, "{}", uint_binary_test(a, "Sub", b, a - b))?; } write!(writer, "{}", uint_binary_test(a, "Mul", b, a * b))?; if b != 0 { write!(writer, "{}", uint_binary_test(a, "Div", b, a / b))?; write!(writer, "{}", uint_binary_test(a, "Rem", b, a % b))?; if a % b == 0 { write!(writer, "{}", uint_binary_test(a, "PartialDiv", b, a / b))?; } } write!(writer, "{}", uint_binary_test(a, "Pow", b, a.pow(b as u32)))?; write!(writer, "{}", uint_cmp_test(a, b))?; } // int operators: for (a, b) in ints { write!(writer, "{}", int_binary_test(a, "Add", b, a + b))?; write!(writer, "{}", int_binary_test(a, "Sub", b, a - b))?; write!(writer, "{}", int_binary_test(a, "Mul", b, a * b))?; write!(writer, "{}", int_binary_test(a, "Min", b, cmp::min(a, b)))?; write!(writer, "{}", int_binary_test(a, "Max", b, cmp::max(a, b)))?; if b != 0 { write!(writer, "{}", int_binary_test(a, "Div", b, a / b))?; write!(writer, "{}", int_binary_test(a, "Rem", b, a % b))?; if a % b == 0 { write!(writer, "{}", int_binary_test(a, "PartialDiv", b, a / b))?; } } if b >= 0 || a.abs() == 1 { let result = if b < 0 { if a == 1 { a } else if a == -1 { a.pow((-b) as u32) } else { unreachable!() } } else { a.pow(b as u32) }; write!(writer, "{}", int_binary_test(a, "Pow", b, result))?; } write!(writer, "{}", int_cmp_test(a, b))?; } // int unary operators: for n in -high..high + 1 { write!(writer, "{}", int_unary_test("Neg", n, -n))?; write!(writer, "{}", int_unary_test("Abs", n, n.abs()))?; } writer.flush()?; Ok(()) } typenum-1.11.2/clippy.toml010066400037200003720000000000421353070170400137070ustar0000000000000000cognitive-complexity-threshold=35 typenum-1.11.2/src/array.rs010066400037200003720000000152461353070170400140010ustar0000000000000000//! A type-level array of type-level numbers. //! //! It is not very featureful right now, and should be considered a work in progress. use core::marker::PhantomData; use core::ops::{Add, Div, Mul, Sub}; use super::*; /// The terminating type for type arrays. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)] pub struct ATerm; impl TypeArray for ATerm {} /// `TArr` is a type that acts as an array of types. It is defined similarly to `UInt`, only its /// values can be more than bits, and it is designed to act as an array. So you can only add two if /// they have the same number of elements, for example. /// /// This array is only really designed to contain `Integer` types. If you use it with others, you /// may find it lacking functionality. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug)] pub struct TArr { _marker: PhantomData<(V, A)>, } impl TypeArray for TArr {} /// Create a new type-level arrray. Only usable on Rust 1.13.0 or newer. /// /// There's not a whole lot you can do with it right now. /// /// # Example /// ```rust /// #[macro_use] /// extern crate typenum; /// use typenum::consts::*; /// /// type Array = tarr![P3, N4, Z0, P38]; /// # fn main() { let _: Array; } #[macro_export] macro_rules! tarr { () => ( $crate::ATerm ); ($n:ty) => ( $crate::TArr<$n, $crate::ATerm> ); ($n:ty,) => ( $crate::TArr<$n, $crate::ATerm> ); ($n:ty, $($tail:ty),+) => ( $crate::TArr<$n, tarr![$($tail),+]> ); ($n:ty, $($tail:ty),+,) => ( $crate::TArr<$n, tarr![$($tail),+]> ); } // --------------------------------------------------------------------------------------- // Length /// Length of `ATerm` by itself is 0 impl Len for ATerm { type Output = U0; fn len(&self) -> Self::Output { UTerm } } /// Size of a `TypeArray` impl Len for TArr where A: Len, Length: Add, Sum, B1>: Unsigned, { type Output = Add1>; fn len(&self) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } // --------------------------------------------------------------------------------------- // Add arrays // Note that two arrays are only addable if they are the same length. impl Add for ATerm { type Output = ATerm; fn add(self, _: ATerm) -> Self::Output { ATerm } } impl Add> for TArr where Al: Add, Vl: Add, { type Output = TArr, Sum>; fn add(self, _: TArr) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } // --------------------------------------------------------------------------------------- // Subtract arrays // Note that two arrays are only subtractable if they are the same length. impl Sub for ATerm { type Output = ATerm; fn sub(self, _: ATerm) -> Self::Output { ATerm } } impl Sub> for TArr where Vl: Sub, Al: Sub, { type Output = TArr, Diff>; fn sub(self, _: TArr) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } // --------------------------------------------------------------------------------------- // Multiply an array by a scalar impl Mul for ATerm { type Output = ATerm; fn mul(self, _: Rhs) -> Self::Output { ATerm } } impl Mul for TArr where V: Mul, A: Mul, { type Output = TArr, Prod>; fn mul(self, _: Rhs) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } impl Mul for Z0 { type Output = ATerm; fn mul(self, _: ATerm) -> Self::Output { ATerm } } impl Mul for PInt where U: Unsigned + NonZero, { type Output = ATerm; fn mul(self, _: ATerm) -> Self::Output { ATerm } } impl Mul for NInt where U: Unsigned + NonZero, { type Output = ATerm; fn mul(self, _: ATerm) -> Self::Output { ATerm } } impl Mul> for Z0 where Z0: Mul, { type Output = TArr>; fn mul(self, _: TArr) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } impl Mul> for PInt where U: Unsigned + NonZero, PInt: Mul + Mul, { type Output = TArr, V>, Prod, A>>; fn mul(self, _: TArr) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } impl Mul> for NInt where U: Unsigned + NonZero, NInt: Mul + Mul, { type Output = TArr, V>, Prod, A>>; fn mul(self, _: TArr) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } // --------------------------------------------------------------------------------------- // Divide an array by a scalar impl Div for ATerm { type Output = ATerm; fn div(self, _: Rhs) -> Self::Output { ATerm } } impl Div for TArr where V: Div, A: Div, { type Output = TArr, Quot>; fn div(self, _: Rhs) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } // --------------------------------------------------------------------------------------- // Partial Divide an array by a scalar impl PartialDiv for ATerm { type Output = ATerm; fn partial_div(self, _: Rhs) -> Self::Output { ATerm } } impl PartialDiv for TArr where V: PartialDiv, A: PartialDiv, { type Output = TArr, PartialQuot>; fn partial_div(self, _: Rhs) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } // --------------------------------------------------------------------------------------- // Modulo an array by a scalar use core::ops::Rem; impl Rem for ATerm { type Output = ATerm; fn rem(self, _: Rhs) -> Self::Output { ATerm } } impl Rem for TArr where V: Rem, A: Rem, { type Output = TArr, Mod>; fn rem(self, _: Rhs) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } // --------------------------------------------------------------------------------------- // Negate an array use core::ops::Neg; impl Neg for ATerm { type Output = ATerm; fn neg(self) -> Self::Output { ATerm } } impl Neg for TArr where V: Neg, A: Neg, { type Output = TArr, Negate>; fn neg(self) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } typenum-1.11.2/src/bit.rs010066400037200003720000000122231353070170400134310ustar0000000000000000//! Type-level bits. //! //! These are rather simple and are used as the building blocks of the //! other number types in this crate. //! //! //! **Type operators** implemented: //! //! - From `core::ops`: `BitAnd`, `BitOr`, `BitXor`, and `Not`. //! - From `typenum`: `Same` and `Cmp`. //! use core::ops::{BitAnd, BitOr, BitXor, Not}; use {Cmp, Equal, Greater, Less, NonZero, PowerOfTwo}; pub use marker_traits::Bit; /// The type-level bit 0. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] pub struct B0; impl B0 { /// Instantiates a singleton representing this bit. #[inline] pub fn new() -> B0 { B0 } } /// The type-level bit 1. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] pub struct B1; impl B1 { /// Instantiates a singleton representing this bit. #[inline] pub fn new() -> B1 { B1 } } impl Bit for B0 { const U8: u8 = 0; const BOOL: bool = false; #[inline] fn to_u8() -> u8 { 0 } #[inline] fn to_bool() -> bool { false } } impl Bit for B1 { const U8: u8 = 1; const BOOL: bool = true; #[inline] fn to_u8() -> u8 { 1 } #[inline] fn to_bool() -> bool { true } } impl NonZero for B1 {} impl PowerOfTwo for B1 {} /// Not of 0 (!0 = 1) impl Not for B0 { type Output = B1; fn not(self) -> Self::Output { B1 } } /// Not of 1 (!1 = 0) impl Not for B1 { type Output = B0; fn not(self) -> Self::Output { B0 } } /// And with 0 ( 0 & B = 0) impl BitAnd for B0 { type Output = B0; fn bitand(self, _: Rhs) -> Self::Output { B0 } } /// And with 1 ( 1 & 0 = 0) impl BitAnd for B1 { type Output = B0; fn bitand(self, _: B0) -> Self::Output { B0 } } /// And with 1 ( 1 & 1 = 1) impl BitAnd for B1 { type Output = B1; fn bitand(self, _: B1) -> Self::Output { B1 } } /// Or with 0 ( 0 | 0 = 0) impl BitOr for B0 { type Output = B0; fn bitor(self, _: B0) -> Self::Output { B0 } } /// Or with 0 ( 0 | 1 = 1) impl BitOr for B0 { type Output = B1; fn bitor(self, _: B1) -> Self::Output { B1 } } /// Or with 1 ( 1 | B = 1) impl BitOr for B1 { type Output = B1; fn bitor(self, _: Rhs) -> Self::Output { B1 } } /// Xor between 0 and 0 ( 0 ^ 0 = 0) impl BitXor for B0 { type Output = B0; fn bitxor(self, _: B0) -> Self::Output { B0 } } /// Xor between 1 and 0 ( 1 ^ 0 = 1) impl BitXor for B1 { type Output = B1; fn bitxor(self, _: B0) -> Self::Output { B1 } } /// Xor between 0 and 1 ( 0 ^ 1 = 1) impl BitXor for B0 { type Output = B1; fn bitxor(self, _: B1) -> Self::Output { B1 } } /// Xor between 1 and 1 ( 1 ^ 1 = 0) impl BitXor for B1 { type Output = B0; fn bitxor(self, _: B1) -> Self::Output { B0 } } #[cfg(tests)] mod tests { // macro for testing operation results. Uses `Same` to ensure the types are equal and // not just the values they evaluate to. macro_rules! test_bit_op { ($op:ident $Lhs:ident = $Answer:ident) => {{ type Test = <<$Lhs as $op>::Output as ::Same<$Answer>>::Output; assert_eq!(<$Answer as Bit>::to_u8(), ::to_u8()); }}; ($Lhs:ident $op:ident $Rhs:ident = $Answer:ident) => {{ type Test = <<$Lhs as $op<$Rhs>>::Output as ::Same<$Answer>>::Output; assert_eq!(<$Answer as Bit>::to_u8(), ::to_u8()); }}; } #[test] fn bit_operations() { test_bit_op!(Not B0 = B1); test_bit_op!(Not B1 = B0); test_bit_op!(B0 BitAnd B0 = B0); test_bit_op!(B0 BitAnd B1 = B0); test_bit_op!(B1 BitAnd B0 = B0); test_bit_op!(B1 BitAnd B1 = B1); test_bit_op!(B0 BitOr B0 = B0); test_bit_op!(B0 BitOr B1 = B1); test_bit_op!(B1 BitOr B0 = B1); test_bit_op!(B1 BitOr B1 = B1); test_bit_op!(B0 BitXor B0 = B0); test_bit_op!(B0 BitXor B1 = B1); test_bit_op!(B1 BitXor B0 = B1); test_bit_op!(B1 BitXor B1 = B0); } } impl Cmp for B0 { type Output = Equal; } impl Cmp for B0 { type Output = Less; } impl Cmp for B1 { type Output = Greater; } impl Cmp for B1 { type Output = Equal; } use Min; impl Min for B0 { type Output = B0; fn min(self, _: B0) -> B0 { self } } impl Min for B0 { type Output = B0; fn min(self, _: B1) -> B0 { self } } impl Min for B1 { type Output = B0; fn min(self, rhs: B0) -> B0 { rhs } } impl Min for B1 { type Output = B1; fn min(self, _: B1) -> B1 { self } } use Max; impl Max for B0 { type Output = B0; fn max(self, _: B0) -> B0 { self } } impl Max for B0 { type Output = B1; fn max(self, rhs: B1) -> B1 { rhs } } impl Max for B1 { type Output = B1; fn max(self, _: B0) -> B1 { self } } impl Max for B1 { type Output = B1; fn max(self, _: B1) -> B1 { self } } typenum-1.11.2/src/int.rs010066400037200003720000000550621353070170400134550ustar0000000000000000//! Type-level signed integers. //! //! //! Type **operators** implemented: //! //! From `core::ops`: `Add`, `Sub`, `Mul`, `Div`, and `Rem`. //! From `typenum`: `Same`, `Cmp`, and `Pow`. //! //! Rather than directly using the structs defined in this module, it is recommended that //! you import and use the relevant aliases from the [consts](../consts/index.html) module. //! //! Note that operators that work on the underlying structure of the number are //! intentionally not implemented. This is because this implementation of signed integers //! does *not* use twos-complement, and implementing them would require making arbitrary //! choices, causing the results of such operators to be difficult to reason about. //! //! # Example //! ```rust //! use std::ops::{Add, Sub, Mul, Div, Rem}; //! use typenum::{Integer, N3, P2}; //! //! assert_eq!(>::Output::to_i32(), -1); //! assert_eq!(>::Output::to_i32(), -5); //! assert_eq!(>::Output::to_i32(), -6); //! assert_eq!(>::Output::to_i32(), -1); //! assert_eq!(>::Output::to_i32(), -1); //! ``` //! use core::marker::PhantomData; use core::ops::{Add, Div, Mul, Neg, Rem, Sub}; use bit::{Bit, B0, B1}; use consts::{N1, P1, U0, U1}; use private::{PrivateDivInt, PrivateIntegerAdd, PrivateRem}; use uint::{UInt, Unsigned}; use {Cmp, Equal, Greater, Less, NonZero, Pow, PowerOfTwo}; pub use marker_traits::Integer; /// Type-level signed integers with positive sign. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] pub struct PInt { _marker: PhantomData, } /// Type-level signed integers with negative sign. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] pub struct NInt { _marker: PhantomData, } impl PInt { /// Instantiates a singleton representing this strictly positive integer. #[inline] pub fn new() -> PInt { PInt { _marker: PhantomData, } } } impl NInt { /// Instantiates a singleton representing this strictly negative integer. #[inline] pub fn new() -> NInt { NInt { _marker: PhantomData, } } } /// The type-level signed integer 0. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] pub struct Z0; impl Z0 { /// Instantiates a singleton representing the integer 0. #[inline] pub fn new() -> Z0 { Z0 } } impl NonZero for PInt {} impl NonZero for NInt {} impl PowerOfTwo for PInt {} impl Integer for Z0 { const I8: i8 = 0; const I16: i16 = 0; const I32: i32 = 0; const I64: i64 = 0; #[cfg(feature = "i128")] const I128: i128 = 0; const ISIZE: isize = 0; #[inline] fn to_i8() -> i8 { 0 } #[inline] fn to_i16() -> i16 { 0 } #[inline] fn to_i32() -> i32 { 0 } #[inline] fn to_i64() -> i64 { 0 } #[cfg(feature = "i128")] #[inline] fn to_i128() -> i128 { 0 } #[inline] fn to_isize() -> isize { 0 } } impl Integer for PInt { const I8: i8 = U::I8; const I16: i16 = U::I16; const I32: i32 = U::I32; const I64: i64 = U::I64; #[cfg(feature = "i128")] const I128: i128 = U::I128; const ISIZE: isize = U::ISIZE; #[inline] fn to_i8() -> i8 { ::to_i8() } #[inline] fn to_i16() -> i16 { ::to_i16() } #[inline] fn to_i32() -> i32 { ::to_i32() } #[inline] fn to_i64() -> i64 { ::to_i64() } #[cfg(feature = "i128")] #[inline] fn to_i128() -> i128 { ::to_i128() } #[inline] fn to_isize() -> isize { ::to_isize() } } // Simply negating the result of e.g. `U::I8` will result in overflow for `std::i8::MIN`. Instead, // we use the fact that `U: NonZero` by subtracting one from the `U::U8` before negating. impl Integer for NInt { const I8: i8 = -((U::U8 - 1) as i8) - 1; const I16: i16 = -((U::U16 - 1) as i16) - 1; const I32: i32 = -((U::U32 - 1) as i32) - 1; const I64: i64 = -((U::U64 - 1) as i64) - 1; #[cfg(feature = "i128")] const I128: i128 = -((U::U128 - 1) as i128) - 1; const ISIZE: isize = -((U::USIZE - 1) as isize) - 1; #[inline] fn to_i8() -> i8 { Self::I8 } #[inline] fn to_i16() -> i16 { Self::I16 } #[inline] fn to_i32() -> i32 { Self::I32 } #[inline] fn to_i64() -> i64 { Self::I64 } #[cfg(feature = "i128")] #[inline] fn to_i128() -> i128 { Self::I128 } #[inline] fn to_isize() -> isize { Self::ISIZE } } // --------------------------------------------------------------------------------------- // Neg /// `-Z0 = Z0` impl Neg for Z0 { type Output = Z0; fn neg(self) -> Self::Output { Z0 } } /// `-PInt = NInt` impl Neg for PInt { type Output = NInt; fn neg(self) -> Self::Output { NInt::new() } } /// `-NInt = PInt` impl Neg for NInt { type Output = PInt; fn neg(self) -> Self::Output { PInt::new() } } // --------------------------------------------------------------------------------------- // Add /// `Z0 + I = I` impl Add for Z0 { type Output = I; fn add(self, _: I) -> Self::Output { unsafe { ::core::mem::uninitialized() } } } /// `PInt + Z0 = PInt` impl Add for PInt { type Output = PInt; fn add(self, _: Z0) -> Self::Output { PInt::new() } } /// `NInt + Z0 = NInt` impl Add for NInt { type Output = NInt; fn add(self, _: Z0) -> Self::Output { NInt::new() } } /// `P(Ul) + P(Ur) = P(Ul + Ur)` impl Add> for PInt