├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches ├── monotone.rs ├── uniform.rs └── unimodal.rs ├── mayda_codec ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT └── src │ └── lib.rs ├── mayda_macros ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT └── src │ └── lib.rs ├── rust-toolchain ├── src ├── error.rs ├── lib.rs ├── monotone.rs ├── uniform.rs ├── unimodal.rs └── utility.rs └── tests ├── monotone.rs ├── quickcheck.rs ├── uniform.rs └── unimodal.rs /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | 3 | # Directory containing rust sources to help with macro development. Refer to 4 | # mayda_macros/Cargo.toml for further details. 5 | compiler 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: nightly-2017-09-10 3 | 4 | env: 5 | global: 6 | secure: Wm+onWNc1435JNLIePvpADZ7gQEa9iY0wuyLm1bnqhO6Mk9EcwOan0WwZXB7OqtOQMpgfO8PxJAT5S1aMeRZ9cI0hn0OpdKkGBPkSK559rSnFgl7LhrWQzp1ROVF7IR5z5GQRuWyqSQekTMj9zYoYTJmBG0K0ZcNqmF+CfaXVZB2MJCDriZVCy4eMER2pywBMg4oOG9R5B2n9dY3AIJYztHIZMf0ZjMntaU8y1HCxqcCBbhzBkqWE7fJhMZHxlGP9VwFaa6p///ryZxiYdhzoVtk4oEhXkwATiUCI3OFSNe3cgmnZAi5ezGsiFqSUmjdBcJX2/t9W2czhljnRuBkoorM30WYGHpI1+2b5H9devCOQxrJcP6ATCsbIRZVxwKI4n3fvHhtyAZi15+tP411+K1ft+rAxkebH2UR7EuPXhE+dBX+Hqha9l/Mu1ofus+9pAQQY+Zk0j7h9NtLpKrBhXprziUad6G2ZD8q9qokD+vcFNA+ttXnfpfGL8tvf9RfhUi7ih/Vzpc6W2SRKJA/W1qpAEuFERt4ZHDQbhYGi/IM1Ay7GV9GaL8pNpm0w38xN9ikKpm3ca99n9VSkc0LcLeYdmR0tdA+euZOymPNGsXSw4IUJo52nV5vjAffdPsMt8XUUevd+wz7gcZbTCTRv4yEvRE2EV14VdR/VjOOCqg= 7 | 8 | after_success: | 9 | [ $TRAVIS_BRANCH = master ] && 10 | [ $TRAVIS_PULL_REQUEST = false ] && 11 | cargo doc && 12 | echo "" > target/doc/index.html && 13 | sudo pip install ghp-import && 14 | ghp-import -n target/doc && 15 | git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages 16 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mayda" 3 | version = "0.2.5" 4 | authors = ["Jeremy Mason "] 5 | license = "MIT/Apache-2.0" 6 | description = "Compression of integer arrays, favoring decompression speed." 7 | homepage = "https://github.com/fralalonde/mayda" 8 | repository = "https://github.com/fralalonde/mayda" 9 | documentation = "https://docs.rs/crate/mayda" 10 | readme = "README.md" 11 | keywords = ["mayda", "compression"] 12 | 13 | [badges] 14 | travis-ci = { repository = "fralalonde/mayda", branch = "master" } 15 | 16 | [lib] 17 | name = "mayda" 18 | 19 | [dependencies] 20 | mayda_codec = { path = "mayda_codec", version = "0.1" } 21 | 22 | [features] 23 | bench = [] 24 | 25 | [dev-dependencies] 26 | num = "0.1" 27 | quickcheck = "0.6" 28 | quickcheck_macros = "0.6" 29 | rand = "0.4" 30 | bencher = "0.1.4" 31 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright 2016 Jeremy Mason 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ANCIENT CODE WARNING 2 | 3 | This project requires a specific **VERY VERY OLD RUST NIGHTLY VERSION** as it relies on pre-stable procmacros. 4 | The design went around old Rust limitations that have since been addressed (const generics, stable SIMD). 5 | Hence it doesn't make sense to try and port it to new Rust since modern alternatives now exist: 6 | 7 | - [bitpacking](https://github.com/quickwit-oss/bitpacking) 8 | - [fastpfor-rs](https://github.com/fast-pack/FastPFOR-rs) 9 | 10 | # mayda 11 | 12 | `mayda` is a Rust library to compress integer arrays (all primitive integer 13 | types are supported). The design favors decompression speed and the ability to 14 | index the compressed array over the compression ratio, on the principle that 15 | the runtime penalty for using compressed arrays should be as small as possible. 16 | 17 | This crate provides three variations on a single compression algorithm. The 18 | [`Uniform`] type can decompress around six billion `u32`s per second, or 24 19 | GiB/s of decompressed integers, on a 2.6 GHz Intel Core i7-6700HQ processor 20 | (see below for specifics). The [`Monotone`] and [`Unimodal`] types decompress 21 | at a little less than half the speed, but can have much better compression 22 | ratios depending on the distribution of the integers. Overall performance is 23 | comparable to the fastest (known) libraries in any language. 24 | 25 | Compiling `mayda` requires a **nightly** compiler and CPU support for the SSE2 26 | instruction set (any Intel or AMD processor manufactured after 2003). The 27 | compiler version is further specified in `./rust-toolchain` for reproducibility. 28 | The basic approach is described in [Zukowski2006] and [Lemire2015]. 29 | 30 | ### Documentation 31 | 32 | The [module documentation][docs] provides further examples and some more 33 | detailed descriptions of the algorithms involved. 34 | 35 | ### Usage 36 | 37 | Add this to your `Cargo.toml`: 38 | 39 | ```toml 40 | [dependencies] 41 | mayda = "0.2" 42 | ``` 43 | 44 | and this to your crate root: 45 | 46 | ```rust 47 | extern crate mayda; 48 | ``` 49 | 50 | ### Example: encoding and decoding 51 | 52 | The `Uniform` struct is recommended for general purpose integer compression. 53 | Use the `Encode` trait to encode and decode the array. 54 | 55 | ```rust 56 | extern crate mayda; 57 | 58 | use mayda::{Uniform, Encode}; 59 | 60 | fn main() { 61 | // Integers in some interval of length 255, require one byte per integer 62 | let input: Vec = (0..128).map(|x| (x * 73) % 181 + 307).collect(); 63 | 64 | let mut uniform = Uniform::new(); 65 | uniform.encode(&input).unwrap(); 66 | 67 | let i_bytes = std::mem::size_of_val(input.as_slice()); 68 | let u_bytes = std::mem::size_of_val(uniform.storage()); 69 | 70 | // 128 bytes for encoded entries, 12 bytes of overhead 71 | assert_eq!(i_bytes, 512); 72 | assert_eq!(u_bytes, 140); 73 | 74 | let output: Vec = uniform.decode(); 75 | assert_eq!(input, output); 76 | } 77 | ``` 78 | 79 | ### Example: indexing 80 | 81 | Use the `Access` and `AccessInto` traits to index the compressed array. This is 82 | similar to `Index`, but returns a vector instead of a slice. 83 | 84 | ```rust 85 | extern crate mayda; 86 | 87 | use mayda::{Uniform, Encode, Access}; 88 | 89 | fn main() { 90 | // All primitive integer types supported 91 | let input: Vec = (-64..64).collect(); 92 | 93 | let mut uniform = Uniform::new(); 94 | uniform.encode(&input).unwrap(); 95 | 96 | let val: isize = uniform.access(64); 97 | assert_eq!(val, 0); 98 | 99 | // Vector is returned to give ownership to the caller 100 | let range: Vec = uniform.access(..10); 101 | assert_eq!(range, (-64..-54).collect::>()); 102 | } 103 | ``` 104 | 105 | ### Performance 106 | 107 | Consider the following three vectors: 108 | ```rust 109 | extern crate rand; 110 | 111 | use rand::distributions::{IndependentSample, Range, Normal}; 112 | 113 | let mut rng = rand::thread_rng(); 114 | let length: usize = 1024; 115 | 116 | // `input1` contains random integers 117 | let mut input1: Vec = Vec::with_capacity(length); 118 | let range = Range::new(0, 1024); 119 | for _ in 0..length { 120 | input1.push(range.ind_sample(&mut rng)); 121 | } 122 | 123 | // `input2` contains monotone increasing integers 124 | let mut input2: Vec = input1.clone(); 125 | input2.sort(); 126 | 127 | // `input3` contains Gaussian distributed integers with outliers 128 | let mut input3: Vec = Vec::with_capacity(length); 129 | let gaussian = Normal::new(4086., 128.); 130 | for _ in 0..length { 131 | input3.push(gaussian.ind_sample(&mut rng) as u32); 132 | } 133 | let index = Range::new(0, length); 134 | let outliers = Range::new(0, std::u32::MAX); 135 | for _ in 0..(length / 16) { 136 | input3[index.ind_sample(&mut rng)] = outliers.ind_sample(&mut rng); 137 | } 138 | ``` 139 | 140 | The performance of the [`Uniform`], [`Monotone`] and [`Unimodal`] types for 141 | these three vectors on a 2.6 GHz Intel Core i7-6700HQ processor is given below. 142 | Encoding and decoding speeds using `decode_into` are reported in billions of 143 | integers per second, time required to index the last entry is reported in 144 | nanoseconds, and compression is reported as bits per integer. Native encoding 145 | and decoding speed measurements perform a memcpy. The Shannon entropy is a 146 | reasonable target for the bits per integer. 147 | 148 | For `input1` the Shannon entropy is 10.00. `Uniform` is preferrable in every 149 | respect for the general case. 150 | 151 | | | Encode (BInt/s) | Decode (BInt/s) | Index (ns) | Bits/Int | 152 | |----------|-----------------|-----------------|------------|----------| 153 | | Uniform | 1.28 | 5.75 | 26 | 10.63 | 154 | | Monotone | 1.34 | 2.49 | 63 | 32.63 | 155 | | Unimodal | 0.21 | 2.01 | 59 | 11.16 | 156 | | Native | 26.26 | 26.26 | 0 | 32 | 157 | 158 | For `input2` the Shannon entropy is 10.00, but the additional structure is used 159 | by `Monotone` to improve compression. 160 | 161 | | | Encode (BInt/s) | Decode (BInt/s) | Index (ns) | Bits/Int | 162 | |----------|-----------------|-----------------|------------|----------| 163 | | Uniform | 1.23 | 5.88 | 26 | 8.00 | 164 | | Monotone | 1.42 | 2.42 | 69 | 3.63 | 165 | | Unimodal | 0.24 | 2.07 | 27 | 8.19 | 166 | | Native | 26.26 | 26.26 | 0 | 32 | 167 | 168 | For `input3` the Shannon entropy is 12.46, but compression is difficult due to 169 | the presence of outliers. `Unimodal` gives the most robust compression. 170 | 171 | | | Encode (BInt/s) | Decode (BInt/s) | Index (ns) | Bits/Int | 172 | |----------|-----------------|-----------------|------------|----------| 173 | | Uniform | 1.26 | 6.10 | 26 | 32.63 | 174 | | Monotone | 1.35 | 2.49 | 65 | 32.63 | 175 | | Unimodal | 0.18 | 1.67 | 61 | 12.50 | 176 | | Native | 26.26 | 26.26 | 0 | 32 | 177 | 178 | ## License 179 | 180 | `mayda` is licensed under either of 181 | 182 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) 183 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT) 184 | 185 | at your option. 186 | 187 | ### Contribution 188 | 189 | Unless you explicitly state otherwise, any contribution intentionally submitted 190 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 191 | be dual licensed as above, without any additional terms or conditions. 192 | 193 | ### Contributors 194 | 195 | [Jeremy Mason](https://github.com/harharkh) - original author 196 | [Francis Lalonde](https://github.com/fralalonde) - last maintainer 197 | 198 | [//]: # 199 | [`Uniform`]: 200 | [`Monotone`]: 201 | [`Unimodal`]: 202 | [Zukowski2006]: 203 | [Lemire2015]: 204 | [docs]: 205 | [Apache-2.0]: 206 | [MIT]: 207 | -------------------------------------------------------------------------------- /benches/monotone.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | #![feature(test)] 9 | #![allow(non_snake_case)] 10 | 11 | extern crate mayda; 12 | extern crate rand; 13 | extern crate test; 14 | 15 | use mayda::{Access, AccessInto, Encode, Monotone}; 16 | use rand::distributions::{IndependentSample, Range}; 17 | use std::{i16, i32, i64, i8, u16, u32, u64, u8}; 18 | use test::Bencher; 19 | 20 | fn rand_increasing(min: T, max: T, length: usize) -> Vec 21 | where 22 | T: Ord + rand::distributions::range::SampleRange, 23 | { 24 | let mut output: Vec = Vec::with_capacity(length); 25 | let val = Range::new(min, max); 26 | let mut rng = rand::thread_rng(); 27 | for _ in 0..length { 28 | output.push(val.ind_sample(&mut rng)); 29 | } 30 | output.sort(); 31 | output 32 | } 33 | 34 | macro_rules! encode_bench { 35 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 36 | #[bench] 37 | fn $name(b: &mut Bencher) { 38 | let mut bin = Monotone::new(); 39 | let input: Vec<$t> = rand_increasing($min, $max, $length); 40 | b.iter(|| { 41 | bin.encode(&input).unwrap(); 42 | }); 43 | let output = bin.decode(); 44 | assert_eq!(input, output); 45 | } 46 | )*) 47 | } 48 | 49 | encode_bench!{ 50 | (u32: 0, u32::MAX, 15, en_u32_0_MAX_15) 51 | (u32: 0, u32::MAX, 16, en_u32_0_MAX_16) 52 | (u32: 0, u32::MAX, 31, en_u32_0_MAX_31) 53 | (u32: 0, u32::MAX, 32, en_u32_0_MAX_32) 54 | (u32: 0, u32::MAX, 127, en_u32_0_MAX_127) 55 | (u32: 0, u32::MAX, 128, en_u32_0_MAX_128) 56 | (u8: 0, u8::MAX, 32768, en_u8_0_MAX_32768) 57 | (u16: 0, u16::MAX, 32768, en_u16_0_MAX_32768) 58 | (u32: 0, u32::MAX, 32768, en_u32_0_MAX_32768) 59 | (u64: 0, u64::MAX, 32768, en_u64_0_MAX_32768) 60 | (i32: i32::MIN, i32::MAX, 15, en_i32_MIN_MAX_15) 61 | (i32: i32::MIN, i32::MAX, 16, en_i32_MIN_MAX_16) 62 | (i32: i32::MIN, i32::MAX, 31, en_i32_MIN_MAX_31) 63 | (i32: i32::MIN, i32::MAX, 32, en_i32_MIN_MAX_32) 64 | (i32: i32::MIN, i32::MAX, 127, en_i32_MIN_MAX_127) 65 | (i32: i32::MIN, i32::MAX, 128, en_i32_MIN_MAX_128) 66 | (i8: i8::MIN, i8::MAX, 32768, en_i8_MIN_MAX_32768) 67 | (i16: i16::MIN, i16::MAX, 32768, en_i16_MIN_MAX_32768) 68 | (i32: i32::MIN, i32::MAX, 32768, en_i32_MIN_MAX_32768) 69 | (i64: i64::MIN, i64::MAX, 32768, en_i64_MIN_MAX_32768) 70 | } 71 | 72 | macro_rules! decode_bench { 73 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 74 | #[bench] 75 | fn $name(b: &mut Bencher) { 76 | let mut bin = Monotone::new(); 77 | let input: Vec<$t> = rand_increasing($min, $max, $length); 78 | bin.encode(&input).unwrap(); 79 | let mut output = vec![0; $length]; 80 | b.iter(|| { 81 | bin.decode_into(&mut *output); 82 | }); 83 | assert_eq!(input, output); 84 | } 85 | )*) 86 | } 87 | 88 | decode_bench!{ 89 | (u32: 0, u32::MAX, 15, de_u32_0_MAX_15) 90 | (u32: 0, u32::MAX, 16, de_u32_0_MAX_16) 91 | (u32: 0, u32::MAX, 31, de_u32_0_MAX_31) 92 | (u32: 0, u32::MAX, 32, de_u32_0_MAX_32) 93 | (u32: 0, u32::MAX, 127, de_u32_0_MAX_127) 94 | (u32: 0, u32::MAX, 128, de_u32_0_MAX_128) 95 | (u8: 0, u8::MAX, 32768, de_u8_0_MAX_32768) 96 | (u16: 0, u16::MAX, 32768, de_u16_0_MAX_32768) 97 | (u32: 0, u32::MAX, 32768, de_u32_0_MAX_32768) 98 | (u64: 0, u64::MAX, 32768, de_u64_0_MAX_32768) 99 | (i32: i32::MIN, i32::MAX, 15, de_i32_MIN_MAX_15) 100 | (i32: i32::MIN, i32::MAX, 16, de_i32_MIN_MAX_16) 101 | (i32: i32::MIN, i32::MAX, 31, de_i32_MIN_MAX_31) 102 | (i32: i32::MIN, i32::MAX, 32, de_i32_MIN_MAX_32) 103 | (i32: i32::MIN, i32::MAX, 127, de_i32_MIN_MAX_127) 104 | (i32: i32::MIN, i32::MAX, 128, de_i32_MIN_MAX_128) 105 | (i8: i8::MIN, i8::MAX, 32768, de_i8_MIN_MAX_32768) 106 | (i16: i16::MIN, i16::MAX, 32768, de_i16_MIN_MAX_32768) 107 | (i32: i32::MIN, i32::MAX, 32768, de_i32_MIN_MAX_32768) 108 | (i64: i64::MIN, i64::MAX, 32768, de_i64_MIN_MAX_32768) 109 | } 110 | 111 | macro_rules! indexing_bench { 112 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $idx: expr, $name: ident))*) => ($( 113 | #[bench] 114 | fn $name(b: &mut Bencher) { 115 | let mut bin = Monotone::new(); 116 | let input: Vec<$t> = rand_increasing($min, $max, $length); 117 | bin.encode(&input).unwrap(); 118 | let mut v: $t = 0; 119 | b.iter(|| { 120 | v = bin.access($idx); 121 | }); 122 | assert_eq!(input[$idx], v); 123 | } 124 | )*) 125 | } 126 | 127 | indexing_bench!{ 128 | (u8: 0, u8::MAX, 32768, 128, idx_u8_0_MAX_32768_128) 129 | (u16: 0, u16::MAX, 32768, 128, idx_u16_0_MAX_32768_128) 130 | (u32: 0, u32::MAX, 32768, 128, idx_u32_0_MAX_32768_128) 131 | (u64: 0, u64::MAX, 32768, 128, idx_u64_0_MAX_32768_128) 132 | (u8: 0, u8::MAX, 32768, 32767, idx_u8_0_MAX_32768_32767) 133 | (u16: 0, u16::MAX, 32768, 32767, idx_u16_0_MAX_32768_32767) 134 | (u32: 0, u32::MAX, 32768, 32767, idx_u32_0_MAX_32768_32767) 135 | (u64: 0, u64::MAX, 32768, 32767, idx_u64_0_MAX_32768_32767) 136 | } 137 | 138 | macro_rules! range_bench { 139 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $lwr: expr, $upr: expr, $name: ident))*) => ($( 140 | #[bench] 141 | fn $name(b: &mut Bencher) { 142 | let mut bin = Monotone::new(); 143 | let input: Vec<$t> = rand_increasing($min, $max, $length); 144 | bin.encode(&input).unwrap(); 145 | let mut output = vec![0; $upr - $lwr]; 146 | b.iter(|| { 147 | bin.access_into($lwr..$upr, &mut *output); 148 | }); 149 | assert_eq!(&input[$lwr..$upr], &output[..]); 150 | } 151 | )*) 152 | } 153 | 154 | range_bench!{ 155 | (u8: 0, u8::MAX, 1024, 892, 900, r_u8_0_MAX_1024_892_900) 156 | (u16: 0, u16::MAX, 1024, 892, 900, r_u16_0_MAX_1024_892_900) 157 | (u32: 0, u32::MAX, 1024, 892, 900, r_u32_0_MAX_1024_892_900) 158 | (u64: 0, u64::MAX, 1024, 892, 900, r_u64_0_MAX_1024_892_900) 159 | (i8: i8::MIN, i8::MAX, 1024, 892, 900, r_i8_MIN_MAX_1024_892_900) 160 | (i16: i16::MIN, i16::MAX, 1024, 892, 900, r_i16_MIN_MAX_1024_892_900) 161 | (i32: i32::MIN, i32::MAX, 1024, 892, 900, r_i32_MIN_MAX_1024_892_900) 162 | (i64: i64::MIN, i64::MAX, 1024, 892, 900, r_i64_MIN_MAX_1024_892_900) 163 | } 164 | -------------------------------------------------------------------------------- /benches/uniform.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | #![feature(test)] 9 | #![allow(non_snake_case)] 10 | 11 | extern crate mayda; 12 | extern crate rand; 13 | extern crate test; 14 | 15 | use mayda::{Access, AccessInto, Encode, Uniform}; 16 | use rand::distributions::{IndependentSample, Range}; 17 | use std::{i16, i32, i64, i8, u16, u32, u64, u8}; 18 | use test::Bencher; 19 | 20 | fn rand_uniform(min: T, max: T, length: usize) -> Vec 21 | where 22 | T: PartialOrd + rand::distributions::range::SampleRange, 23 | { 24 | let mut output: Vec = Vec::with_capacity(length); 25 | let val = Range::new(min, max); 26 | let mut rng = rand::thread_rng(); 27 | for _ in 0..length { 28 | output.push(val.ind_sample(&mut rng)); 29 | } 30 | output 31 | } 32 | 33 | macro_rules! encode_bench { 34 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 35 | #[bench] 36 | fn $name(b: &mut Bencher) { 37 | let mut bin = Uniform::new(); 38 | let input: Vec<$t> = rand_uniform($min, $max, $length); 39 | b.iter(|| { 40 | bin.encode(&input).unwrap(); 41 | }); 42 | let output = bin.decode(); 43 | assert_eq!(input, output); 44 | } 45 | )*) 46 | } 47 | 48 | encode_bench!{ 49 | (u32: 0, u32::MAX, 15, en_u32_0_MAX_15) 50 | (u32: 0, u32::MAX, 16, en_u32_0_MAX_16) 51 | (u32: 0, u32::MAX, 31, en_u32_0_MAX_31) 52 | (u32: 0, u32::MAX, 32, en_u32_0_MAX_32) 53 | (u32: 0, u32::MAX, 127, en_u32_0_MAX_127) 54 | (u32: 0, u32::MAX, 128, en_u32_0_MAX_128) 55 | (u8: 0, u8::MAX, 32768, en_u8_0_MAX_32768) 56 | (u16: 0, u16::MAX, 32768, en_u16_0_MAX_32768) 57 | (u32: 0, u32::MAX, 32768, en_u32_0_MAX_32768) 58 | (u64: 0, u64::MAX, 32768, en_u64_0_MAX_32768) 59 | (i32: i32::MIN, i32::MAX, 15, en_i32_MIN_MAX_15) 60 | (i32: i32::MIN, i32::MAX, 16, en_i32_MIN_MAX_16) 61 | (i32: i32::MIN, i32::MAX, 31, en_i32_MIN_MAX_31) 62 | (i32: i32::MIN, i32::MAX, 32, en_i32_MIN_MAX_32) 63 | (i32: i32::MIN, i32::MAX, 127, en_i32_MIN_MAX_127) 64 | (i32: i32::MIN, i32::MAX, 128, en_i32_MIN_MAX_128) 65 | (i8: i8::MIN, i8::MAX, 32768, en_i8_MIN_MAX_32768) 66 | (i16: i16::MIN, i16::MAX, 32768, en_i16_MIN_MAX_32768) 67 | (i32: i32::MIN, i32::MAX, 32768, en_i32_MIN_MAX_32768) 68 | (i64: i64::MIN, i64::MAX, 32768, en_i64_MIN_MAX_32768) 69 | } 70 | 71 | macro_rules! decode_bench { 72 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 73 | #[bench] 74 | fn $name(b: &mut Bencher) { 75 | let mut bin = Uniform::new(); 76 | let input: Vec<$t> = rand_uniform($min, $max, $length); 77 | bin.encode(&input).unwrap(); 78 | let mut output = vec![0; $length]; 79 | b.iter(|| { 80 | bin.decode_into(&mut *output); 81 | }); 82 | assert_eq!(input, output); 83 | } 84 | )*) 85 | } 86 | 87 | decode_bench!{ 88 | (u32: 0, u32::MAX, 15, de_u32_0_MAX_15) 89 | (u32: 0, u32::MAX, 16, de_u32_0_MAX_16) 90 | (u32: 0, u32::MAX, 31, de_u32_0_MAX_31) 91 | (u32: 0, u32::MAX, 32, de_u32_0_MAX_32) 92 | (u32: 0, u32::MAX, 127, de_u32_0_MAX_127) 93 | (u32: 0, u32::MAX, 128, de_u32_0_MAX_128) 94 | (u8: 0, u8::MAX, 32768, de_u8_0_MAX_32768) 95 | (u16: 0, u16::MAX, 32768, de_u16_0_MAX_32768) 96 | (u32: 0, u32::MAX, 32768, de_u32_0_MAX_32768) 97 | (u64: 0, u64::MAX, 32768, de_u64_0_MAX_32768) 98 | (i32: i32::MIN, i32::MAX, 15, de_i32_MIN_MAX_15) 99 | (i32: i32::MIN, i32::MAX, 16, de_i32_MIN_MAX_16) 100 | (i32: i32::MIN, i32::MAX, 31, de_i32_MIN_MAX_31) 101 | (i32: i32::MIN, i32::MAX, 32, de_i32_MIN_MAX_32) 102 | (i32: i32::MIN, i32::MAX, 127, de_i32_MIN_MAX_127) 103 | (i32: i32::MIN, i32::MAX, 128, de_i32_MIN_MAX_128) 104 | (i8: i8::MIN, i8::MAX, 32768, de_i8_MIN_MAX_32768) 105 | (i16: i16::MIN, i16::MAX, 32768, de_i16_MIN_MAX_32768) 106 | (i32: i32::MIN, i32::MAX, 32768, de_i32_MIN_MAX_32768) 107 | (i64: i64::MIN, i64::MAX, 32768, de_i64_MIN_MAX_32768) 108 | } 109 | 110 | macro_rules! indexing_bench { 111 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $idx: expr, $name: ident))*) => ($( 112 | #[bench] 113 | fn $name(b: &mut Bencher) { 114 | let mut bin = Uniform::new(); 115 | let input: Vec<$t> = rand_uniform($min, $max, $length); 116 | bin.encode(&input).unwrap(); 117 | let mut v: $t = 0; 118 | b.iter(|| { 119 | v = bin.access($idx); 120 | }); 121 | assert_eq!(input[$idx], v); 122 | } 123 | )*) 124 | } 125 | 126 | indexing_bench!{ 127 | (u8: 0, u8::MAX, 32768, 128, idx_u8_0_MAX_32768_128) 128 | (u16: 0, u16::MAX, 32768, 128, idx_u16_0_MAX_32768_128) 129 | (u32: 0, u32::MAX, 32768, 128, idx_u32_0_MAX_32768_128) 130 | (u64: 0, u64::MAX, 32768, 128, idx_u64_0_MAX_32768_128) 131 | (u8: 0, u8::MAX, 32768, 32767, idx_u8_0_MAX_32768_32767) 132 | (u16: 0, u16::MAX, 32768, 32767, idx_u16_0_MAX_32768_32767) 133 | (u32: 0, u32::MAX, 32768, 32767, idx_u32_0_MAX_32768_32767) 134 | (u64: 0, u64::MAX, 32768, 32767, idx_u64_0_MAX_32768_32767) 135 | } 136 | 137 | macro_rules! range_bench { 138 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $lwr: expr, $upr: expr, $name: ident))*) => ($( 139 | #[bench] 140 | fn $name(b: &mut Bencher) { 141 | let mut bin = Uniform::new(); 142 | let input: Vec<$t> = rand_uniform($min, $max, $length); 143 | bin.encode(&input).unwrap(); 144 | let mut output = vec![0; $upr - $lwr]; 145 | b.iter(|| { 146 | bin.access_into($lwr..$upr, &mut *output); 147 | }); 148 | assert_eq!(&input[$lwr..$upr], &output[..]); 149 | } 150 | )*) 151 | } 152 | 153 | range_bench!{ 154 | (u8: 0, u8::MAX, 1024, 892, 900, r_u8_0_MAX_1024_892_900) 155 | (u16: 0, u16::MAX, 1024, 892, 900, r_u16_0_MAX_1024_892_900) 156 | (u32: 0, u32::MAX, 1024, 892, 900, r_u32_0_MAX_1024_892_900) 157 | (u64: 0, u64::MAX, 1024, 892, 900, r_u64_0_MAX_1024_892_900) 158 | (i8: i8::MIN, i8::MAX, 1024, 892, 900, r_i8_MIN_MAX_1024_892_900) 159 | (i16: i16::MIN, i16::MAX, 1024, 892, 900, r_i16_MIN_MAX_1024_892_900) 160 | (i32: i32::MIN, i32::MAX, 1024, 892, 900, r_i32_MIN_MAX_1024_892_900) 161 | (i64: i64::MIN, i64::MAX, 1024, 892, 900, r_i64_MIN_MAX_1024_892_900) 162 | } 163 | -------------------------------------------------------------------------------- /benches/unimodal.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | #![feature(test)] 9 | 10 | extern crate mayda; 11 | extern crate num; 12 | extern crate rand; 13 | extern crate test; 14 | 15 | use mayda::{Access, AccessInto, Encode, Unimodal}; 16 | use num::{Bounded, FromPrimitive, ToPrimitive}; 17 | use rand::distributions::{IndependentSample, Normal, Range}; 18 | use test::Bencher; 19 | 20 | fn rand_outliers(mean: T, std_dev: T, length: usize) -> Vec 21 | where 22 | T: PartialOrd + Bounded + FromPrimitive + ToPrimitive + rand::distributions::range::SampleRange, 23 | { 24 | let mut output: Vec = Vec::with_capacity(length); 25 | if length > 0 { 26 | let val = Normal::new(mean.to_f64().unwrap(), std_dev.to_f64().unwrap()); 27 | let mut rng = rand::thread_rng(); 28 | for _ in 0..length { 29 | output.push(FromPrimitive::from_f64(val.ind_sample(&mut rng)).unwrap()); 30 | } 31 | let idx = Range::new(0, length); 32 | let val = Range::new(Bounded::min_value(), Bounded::max_value()); 33 | for _ in 0..(length / 16) { 34 | output[idx.ind_sample(&mut rng)] = val.ind_sample(&mut rng); 35 | } 36 | } 37 | output 38 | } 39 | 40 | macro_rules! encode_bench { 41 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($( 42 | #[bench] 43 | fn $name(b: &mut Bencher) { 44 | let mut bin = Unimodal::new(); 45 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 46 | b.iter(|| { 47 | bin.encode(&input).unwrap(); 48 | }); 49 | let output = bin.decode(); 50 | assert_eq!(input, output); 51 | } 52 | )*) 53 | } 54 | 55 | encode_bench!{ 56 | (u32: 1024, 32, 15, en_u32_1024_32_15) 57 | (u32: 1024, 32, 16, en_u32_1024_32_16) 58 | (u32: 1024, 32, 31, en_u32_1024_32_31) 59 | (u32: 1024, 32, 32, en_u32_1024_32_32) 60 | (u32: 1024, 32, 127, en_u32_1024_32_127) 61 | (u32: 1024, 32, 128, en_u32_1024_32_128) 62 | (u8: 128, 16, 32768, en_u8_128_16_32768) 63 | (u16: 1024, 32, 32768, en_u16_1024_32_32768) 64 | (u32: 1024, 32, 32768, en_u32_1024_32_32768) 65 | (u64: 1024, 32, 32768, en_u64_1024_32_32768) 66 | (i32: 0, 32, 15, en_i32_0_32_15) 67 | (i32: 0, 32, 16, en_i32_0_32_16) 68 | (i32: 0, 32, 31, en_i32_0_32_31) 69 | (i32: 0, 32, 32, en_i32_0_32_32) 70 | (i32: 0, 32, 127, en_i32_0_32_127) 71 | (i32: 0, 32, 128, en_i32_0_32_128) 72 | (i8: 0, 16, 32768, en_i8_0_16_32768) 73 | (i16: 0, 32, 32768, en_i16_0_32_32768) 74 | (i32: 0, 32, 32768, en_i32_0_32_32768) 75 | (i64: 0, 32, 32768, en_i64_0_32_32768) 76 | } 77 | 78 | macro_rules! decode_bench { 79 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($( 80 | #[bench] 81 | fn $name(b: &mut Bencher) { 82 | let mut bin = Unimodal::new(); 83 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 84 | bin.encode(&input).unwrap(); 85 | let mut output = vec![0; $length]; 86 | b.iter(|| { 87 | bin.decode_into(&mut *output); 88 | }); 89 | assert_eq!(input, output); 90 | } 91 | )*) 92 | } 93 | 94 | decode_bench!{ 95 | (u32: 1024, 32, 15, de_u32_1024_32_15) 96 | (u32: 1024, 32, 16, de_u32_1024_32_16) 97 | (u32: 1024, 32, 31, de_u32_1024_32_31) 98 | (u32: 1024, 32, 32, de_u32_1024_32_32) 99 | (u32: 1024, 32, 127, de_u32_1024_32_127) 100 | (u32: 1024, 32, 128, de_u32_1024_32_128) 101 | (u8: 128, 16, 32768, de_u8_128_16_32768) 102 | (u16: 1024, 32, 32768, de_u16_1024_32_32768) 103 | (u32: 1024, 32, 32768, de_u32_1024_32_32768) 104 | (u64: 1024, 32, 32768, de_u64_1024_32_32768) 105 | (i32: 0, 32, 15, de_i32_0_32_15) 106 | (i32: 0, 32, 16, de_i32_0_32_16) 107 | (i32: 0, 32, 31, de_i32_0_32_31) 108 | (i32: 0, 32, 32, de_i32_0_32_32) 109 | (i32: 0, 32, 127, de_i32_0_32_127) 110 | (i32: 0, 32, 128, de_i32_0_32_128) 111 | (i8: 0, 16, 32768, de_i8_0_16_32768) 112 | (i16: 0, 32, 32768, de_i16_0_32_32768) 113 | (i32: 0, 32, 32768, de_i32_0_32_32768) 114 | (i64: 0, 32, 32768, de_i64_0_32_32768) 115 | } 116 | 117 | macro_rules! indexing_bench { 118 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $idx: expr, $name: ident))*) => ($( 119 | #[bench] 120 | fn $name(b: &mut Bencher) { 121 | let mut bin = Unimodal::new(); 122 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 123 | bin.encode(&input).unwrap(); 124 | let mut v: $t = 0; 125 | b.iter(|| { 126 | v = bin.access($idx); 127 | }); 128 | assert_eq!(input[$idx], v); 129 | } 130 | )*) 131 | } 132 | 133 | indexing_bench!{ 134 | (u8: 128, 16, 32768, 128, idx_u8_128_16_32768_128) 135 | (u16: 1024, 32, 32768, 128, idx_u16_1024_32_32768_128) 136 | (u32: 1024, 32, 32768, 128, idx_u32_1024_32_32768_128) 137 | (u64: 1024, 32, 32768, 128, idx_u64_1024_32_32768_128) 138 | (u8: 128, 16, 32768, 32767, idx_u8_128_16_32768_32767) 139 | (u16: 1024, 32, 32768, 32767, idx_u16_1024_32_32768_32767) 140 | (u32: 1024, 32, 32768, 32767, idx_u32_1024_32_32768_32767) 141 | (u64: 1024, 32, 32768, 32767, idx_u64_1024_32_32768_32767) 142 | } 143 | 144 | macro_rules! range_bench { 145 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, 146 | $lwr: expr, $upr: expr, $name: ident))*) => ($( 147 | #[bench] 148 | fn $name(b: &mut Bencher) { 149 | let mut bin = Unimodal::new(); 150 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 151 | bin.encode(&input).unwrap(); 152 | let mut output = vec![0; $upr - $lwr]; 153 | b.iter(|| { 154 | bin.access_into($lwr..$upr, &mut *output); 155 | }); 156 | assert_eq!(&input[$lwr..$upr], &output[..]); 157 | } 158 | )*) 159 | } 160 | 161 | range_bench!{ 162 | (u8: 128, 16, 1024, 892, 900, r_u8_128_16_1024_892_900) 163 | (u16: 1024, 32, 1024, 892, 900, r_u16_1024_32_1024_892_900) 164 | (u32: 1024, 32, 1024, 892, 900, r_u32_1024_32_1024_892_900) 165 | (u64: 1024, 32, 1024, 892, 900, r_u64_1024_32_1024_892_900) 166 | (i8: 0, 16, 1024, 892, 900, r_i8_0_16_1024_892_900) 167 | (i16: 0, 32, 1024, 892, 900, r_i16_0_32_1024_892_900) 168 | (i32: 0, 32, 1024, 892, 900, r_i32_0_32_1024_892_900) 169 | (i64: 0, 32, 1024, 892, 900, r_i64_0_32_1024_892_900) 170 | } 171 | -------------------------------------------------------------------------------- /mayda_codec/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mayda_codec" 3 | version = "0.1.5" 4 | authors = ["Jeremy Mason "] 5 | license = "MIT/Apache-2.0" 6 | description = "Separate compilation unit for functions generated by mayda_macros" 7 | homepage = "https://github.com/harharkh/mayda" 8 | repository = "https://github.com/harharkh/mayda" 9 | documentation = "https://harharkh.github.io/mayda" 10 | keywords = ["mayda", "compression"] 11 | 12 | [lib] 13 | name = "mayda_codec" 14 | 15 | [dependencies] 16 | mayda_macros = { path = "../mayda_macros", version = "0.1" } 17 | -------------------------------------------------------------------------------- /mayda_codec/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /mayda_codec/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Jeremy Mason 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /mayda_codec/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! The purpose of this crate is to relegate the functions generated by the 9 | //! `encode!`, `decode!`, `encode_simd!`, `decode_simd!` and `encode_util!` 10 | //! syntax extensions of `mayda_macros` to a separate compilation unit. More 11 | //! extensive documentation is provided in the `mayda_macros` crate. 12 | 13 | #![feature(plugin, stdsimd)] 14 | #![plugin(mayda_macros)] 15 | 16 | #![allow(unused_mut)] 17 | 18 | use std::simd; 19 | 20 | macro_rules! codec { 21 | ($width: expr, $step: expr, $simd: path) => ( 22 | encode!($width, $step); 23 | decode!($width, $step); 24 | encode_simd!($width, $simd); 25 | decode_simd!($width, $simd); 26 | encode_util!($width, $simd); 27 | ) 28 | } 29 | 30 | codec!(8, 8, simd); 31 | codec!(16, 8, simd); 32 | codec!(32, 8, simd); 33 | codec!(64, 8, simd); 34 | 35 | -------------------------------------------------------------------------------- /mayda_macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mayda_macros" 3 | version = "0.1.5" 4 | authors = ["Jeremy Mason "] 5 | license = "MIT/Apache-2.0" 6 | description = "Macros to generate basic encoding and decoding functions used by mayda" 7 | homepage = "https://github.com/harharkh/mayda" 8 | repository = "https://github.com/harharkh/mayda" 9 | documentation = "https://harharkh.github.io/mayda" 10 | keywords = ["mayda", "compression"] 11 | 12 | [lib] 13 | name = "mayda_macros" 14 | plugin = true 15 | 16 | # Trick to help with dev-time exploration of rust internals from 17 | # https://maikklein.github.io/post/rust-compiler/ 18 | # 19 | # Clone the rust sources to the .gitignored "compiler" subfolder 20 | # ``` 21 | # git clone git@github.com:rust-lang/rust.git "compiler" 22 | # ``` 23 | # and checkout the rust revision that most closely matches the one in the 24 | # rust-toolchain file 25 | # ``` 26 | # cat rust-toolchain 27 | # >> "nightly-2017-06-13" 28 | # cd "compiler" 29 | # git checkout 'master@{2017-06-13 03:00:00} 30 | # ``` 31 | # 32 | # UNCOMMENT THE DEPS BELOW FOR DEV 33 | # 34 | # [target.'cfg(IGNORE_DEV_SOURCE_PATH_ONLY)'.dependencies] 35 | # rustc = {path = "../compiler/src/librustc/"} 36 | # rustc_plugin = {path = "../compiler/src/librustc_plugin/"} 37 | # syntax = {path = "../compiler/src/libsyntax/"} 38 | # syntax_pos = {path = "../compiler/src/libsyntax_pos/"} 39 | -------------------------------------------------------------------------------- /mayda_macros/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /mayda_macros/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Jeremy Mason 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /mayda_macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! Compiler plugins to generate basic encoding and decoding functions. The 9 | //! functions generated by the `encode!` and `decode!` syntax extensions follow 10 | //! the convention `encode_T_a_b`. The functions generated by the 11 | //! `encode_simd!` and `decode_simd!` syntax extensions follow the convention 12 | //! `encode_simd_T_a`. The functions generated by the `encode_util!` syntax 13 | //! extention follow the conventions `encode_delta_T` and `encode_zz_shift_T`. 14 | //! `T` is one of the unsigned integer types, `a` is the number of bits per 15 | //! integer, and `b` is the number of integers encoded. 16 | //! 17 | //! `encode!` and `decode!` take as arguments the unsigned integer type width 18 | //! in bits and a step for the number of integers (a divisor of 32). Functions 19 | //! are generated for numbers of bits in the interval `0...max_bits`, and for 20 | //! numbers of integers in multiples of the step up to 32. `encode_simd!` and 21 | //! `decode_simd!` take as arguments the unsigned integer type width in bits 22 | //! and a path to the relevant simd module. Functions are generated for numbers 23 | //! of bits in the interval `0...max_bits`, and for exactly 128 integers. 24 | //! `encode_util!` takes as arguments the unsigned integer type width in bits 25 | //! and a path to the relevant simd module. Functions are generated for the 26 | //! type width and for an arbitrary number of integers. 27 | //! 28 | //! Pointers to the functions generated by `encode!` and `decode!` are 29 | //! available in `ENCODE_T` and `DECODE_T`, respectively, with the pointer for 30 | //! `encode_T_a_b` at `ENCODE_T[a][b / c - 1]` where `c` is the step. 31 | //! Pointers to the functions generated by `encode_simd!` and `decode_simd!` 32 | //! are availabe in `ENCODE_SIMD_T` and `DECODE_SIMD_T`, respectively, with the 33 | //! pointer for `encode_simd_T_a` at `ENCODE_SIMD_T[a]`. The functions 34 | //! generated by `encode_util!` are public. All arrays are public and constant. 35 | //! 36 | //! # Safety 37 | //! 38 | //! The functions generated by this crate use wildly unsafe pointer operations. 39 | //! You must verify that enough memory is already allocated after the pointers 40 | //! that the offsets are valid. They are not intended to be used outside the 41 | //! `mayda` crate. 42 | //! 43 | //! # Examples 44 | //! 45 | //! The syntax extensions defined in this crate can be invoked as 46 | //! 47 | //! ``` 48 | //! encode!(u32, 32, 8); 49 | //! decode!(u32, 32, 8); 50 | //! ``` 51 | //! 52 | //! This is replaced by 128 functions that encode u32 integers and 128 53 | //! functions that decode u32 integers. For example, the functions that encode 54 | //! and decode the 24 least significant bits of 8 u32 integers are 55 | //! 56 | //! ``` 57 | //! unsafe fn encode_u32_24_8(mut i_ptr: *const u32, mut s_ptr: *mut u32) { 58 | //! let mut out = *i_ptr as u32; 59 | //! i_ptr = i_ptr.offset(1); 60 | //! out |= (*i_ptr as u32) << 24usize; 61 | //! *s_ptr = out; 62 | //! s_ptr = s_ptr.offset(1); 63 | //! out = (*i_ptr >> 8usize) as u32; 64 | //! i_ptr = i_ptr.offset(1); 65 | //! out |= (*i_ptr as u32) << 16usize; 66 | //! *s_ptr = out; 67 | //! s_ptr = s_ptr.offset(1); 68 | //! out = (*i_ptr >> 16usize) as u32; 69 | //! i_ptr = i_ptr.offset(1); 70 | //! out |= (*i_ptr as u32) << 8usize; 71 | //! i_ptr = i_ptr.offset(1); 72 | //! *s_ptr = out; 73 | //! s_ptr = s_ptr.offset(1); 74 | //! out = *i_ptr as u32; 75 | //! i_ptr = i_ptr.offset(1); 76 | //! out |= (*i_ptr as u32) << 24usize; 77 | //! *s_ptr = out; 78 | //! s_ptr = s_ptr.offset(1); 79 | //! out = (*i_ptr >> 8usize) as u32; 80 | //! i_ptr = i_ptr.offset(1); 81 | //! out |= (*i_ptr as u32) << 16usize; 82 | //! *s_ptr = out; 83 | //! s_ptr = s_ptr.offset(1); 84 | //! out = (*i_ptr >> 16usize) as u32; 85 | //! i_ptr = i_ptr.offset(1); 86 | //! out |= (*i_ptr as u32) << 8usize; 87 | //! *s_ptr = out; 88 | //! } 89 | //! 90 | //! unsafe fn decode_u32_24_8(mut s_ptr: *const u32, mut o_ptr: *mut u32) { 91 | //! let mask: u32 = !0 >> 8usize; 92 | //! let mut out; 93 | //! out = *s_ptr as u32; 94 | //! *o_ptr = out & mask; 95 | //! o_ptr = o_ptr.offset(1); 96 | //! out = (*s_ptr >> 24usize) as u32; 97 | //! s_ptr = s_ptr.offset(1); 98 | //! out |= (*s_ptr as u32) << 8usize; 99 | //! *o_ptr = out & mask; 100 | //! o_ptr = o_ptr.offset(1); 101 | //! out = (*s_ptr >> 16usize) as u32; 102 | //! s_ptr = s_ptr.offset(1); 103 | //! out |= (*s_ptr as u32) << 16usize; 104 | //! *o_ptr = out & mask; 105 | //! o_ptr = o_ptr.offset(1); 106 | //! out = (*s_ptr >> 8usize) as u32; 107 | //! *o_ptr = out & mask; 108 | //! o_ptr = o_ptr.offset(1); 109 | //! s_ptr = s_ptr.offset(1); 110 | //! out = *s_ptr as u32; 111 | //! *o_ptr = out & mask; 112 | //! o_ptr = o_ptr.offset(1); 113 | //! out = (*s_ptr >> 24usize) as u32; 114 | //! s_ptr = s_ptr.offset(1); 115 | //! out |= (*s_ptr as u32) << 8usize; 116 | //! *o_ptr = out & mask; 117 | //! o_ptr = o_ptr.offset(1); 118 | //! out = (*s_ptr >> 16usize) as u32; 119 | //! s_ptr = s_ptr.offset(1); 120 | //! out |= (*s_ptr as u32) << 16usize; 121 | //! *o_ptr = out & mask; 122 | //! o_ptr = o_ptr.offset(1); 123 | //! out = (*s_ptr >> 8usize) as u32; 124 | //! *o_ptr = out & mask; 125 | //! } 126 | //! ``` 127 | 128 | #![crate_type="dylib"] 129 | #![feature(plugin_registrar, rustc_private, quote)] 130 | #![feature(inclusive_range_syntax, step_by,iterator_step_by)] 131 | 132 | // Unused import in quote_tokens! macro 133 | #![allow(unused_imports)] 134 | 135 | extern crate syntax; 136 | extern crate rustc; 137 | extern crate rustc_plugin; 138 | 139 | use syntax::tokenstream::TokenTree; 140 | use syntax::ext::build::AstBuilder; // A trait for expr_usize. 141 | use syntax::ext::quote::rt::Span; 142 | use rustc::hir; 143 | 144 | use rustc_plugin::Registry; 145 | use syntax::ast::{self, Ident}; 146 | use syntax::codemap; 147 | use syntax::ext::base::{DummyResult, ExtCtxt, MacResult, MacEager}; 148 | use syntax::fold::Folder; 149 | use syntax::parse::{self, token}; 150 | use syntax::print::pprust; 151 | use syntax::tokenstream; 152 | use syntax::util::small_vector; 153 | 154 | /// Registers the encode and decode syntax expansions. 155 | #[plugin_registrar] 156 | pub fn plugin_registrar(reg: &mut Registry) { 157 | reg.register_macro("encode", encode_expand); 158 | reg.register_macro("decode", decode_expand); 159 | reg.register_macro("encode_simd", encode_simd_expand); 160 | reg.register_macro("decode_simd", decode_simd_expand); 161 | reg.register_macro("encode_util", encode_util_expand); 162 | } 163 | 164 | /// Generates `ENCODE_T` containing function pointers, with the pointer for 165 | /// `encode_T_a_b` at `ENCODE_T[a - 1][b / c - 1]`. 166 | fn encode_expand(cx: &mut ExtCtxt, 167 | sp: codemap::Span, 168 | tts: &[tokenstream::TokenTree]) -> Box { 169 | // Arguments to the macro invocation 170 | let (width, step) = { 171 | match parse(cx, sp, tts) { 172 | Some(x) => x, 173 | None => return DummyResult::expr(sp) 174 | } 175 | }; 176 | let ut = Ident::from_str(&*format!("u{}", width)); 177 | assert_eq!(32 % step, 0); 178 | let lengths: Vec = (step..33).step_by(step).collect(); 179 | 180 | // idents: tokens used to define the ENCODE_T 181 | // items: definitions of the functions 182 | let mut idents = vec![token::OpenDelim(token::Bracket)]; 183 | let mut items = Vec::new(); 184 | for wd in 0..(width + 1) { 185 | idents.push(token::OpenDelim(token::Bracket)); 186 | for &ln in &lengths { 187 | // Name for the function interned 188 | let name = format!("encode_{}_{}_{}", ut, wd, ln); 189 | let ident = Ident::from_str(&*name); 190 | idents.push(token::Ident(ident)); 191 | idents.push(token::Comma); 192 | 193 | // Nothing to write 194 | if wd == 0 { 195 | items.push( 196 | quote_item!(cx, 197 | unsafe fn $ident(_: *const $ut, _: *mut u32) { } 198 | ).unwrap() 199 | ); 200 | continue 201 | } 202 | 203 | // Function definition constructed here 204 | let mut tokens = quote_tokens!(cx, 205 | let mut out = 206 | ); 207 | 208 | // For every integer to be encoded... 209 | let mut i_bits: usize; 210 | let mut s_bits: usize = 32; 211 | for a in 0..ln { 212 | i_bits = wd; 213 | 214 | // Encode in the available space 215 | let lsft = 32 - s_bits; 216 | if lsft == 0 { 217 | tokens = quote_tokens!(cx, $tokens 218 | *i_ptr as u32; 219 | ); 220 | } else { 221 | tokens = quote_tokens!(cx, $tokens 222 | (*i_ptr as u32) << $lsft; 223 | ); 224 | } 225 | 226 | // While the available space is not enough... 227 | while s_bits < i_bits { 228 | i_bits -= s_bits; 229 | let rsft = wd - i_bits; 230 | tokens = quote_tokens!(cx, $tokens 231 | *s_ptr = out; 232 | s_ptr = s_ptr.offset(1); 233 | out = (*i_ptr >> $rsft) as u32; 234 | ); 235 | s_bits = 32; 236 | } 237 | s_bits -= i_bits; 238 | 239 | 240 | // Prepare for following iteration 241 | if a < ln - 1 { 242 | tokens = quote_tokens!(cx, $tokens 243 | i_ptr = i_ptr.offset(1); 244 | ); 245 | if s_bits == 0 { 246 | tokens = quote_tokens!(cx, $tokens 247 | *s_ptr = out; 248 | s_ptr = s_ptr.offset(1); 249 | out = 250 | ); 251 | s_bits = 32; 252 | } else { 253 | tokens = quote_tokens!(cx, $tokens 254 | out |= 255 | ); 256 | } 257 | } else { 258 | tokens = quote_tokens!(cx, $tokens 259 | *s_ptr = out; 260 | ); 261 | } 262 | } 263 | 264 | // Function definition pushed to items 265 | items.push( 266 | quote_item!(cx, 267 | unsafe fn $ident(mut i_ptr: *const $ut, mut s_ptr: *mut u32) { 268 | $tokens 269 | } 270 | ).unwrap() 271 | ); 272 | } 273 | idents.push(token::CloseDelim(token::Bracket)); 274 | idents.push(token::Comma); 275 | } 276 | idents.push(token::CloseDelim(token::Bracket)); 277 | 278 | // idents converted from tokens to TokenTree 279 | let ttree: Vec = idents 280 | .into_iter() 281 | .map(|token| tokenstream::TokenTree::Token(codemap::DUMMY_SP, token)) 282 | .collect(); 283 | 284 | // ENCODE_T definition pushed to items 285 | let name = format!("encode_{}", ut).to_uppercase(); 286 | let ident = Ident::from_str(&*name); 287 | let len1 = lengths.len(); 288 | let len2 = width + 1; 289 | items.push( 290 | quote_item!(cx, 291 | pub const $ident: [[unsafe fn(*const $ut, *mut u32); $len1]; $len2] = $ttree; 292 | ).unwrap() 293 | ); 294 | 295 | // DEBUGGING 296 | // for item in &items { println!("{}", pprust::item_to_string(item)); } 297 | 298 | MacEager::items(small_vector::SmallVector::many(items)) 299 | } 300 | 301 | /// Generates `DECODE_T` containing function pointers, with the pointer for 302 | /// `decode_T_a_b` at `DECODE_T[a - 1][b / c - 1]`. 303 | fn decode_expand(cx: &mut ExtCtxt, 304 | sp: codemap::Span, 305 | tts: &[tokenstream::TokenTree]) -> Box { 306 | // Arguments to the macro invocation 307 | let (width, step) = { 308 | match parse(cx, sp, tts) { 309 | Some(x) => x, 310 | None => return DummyResult::expr(sp) 311 | } 312 | }; 313 | let ut = Ident::from_str(&*format!("u{}", width)); 314 | assert_eq!(32 % step, 0); 315 | let lengths: Vec = (step..33).step_by(step).collect(); 316 | 317 | // idents: tokens used to define the const DECODE_T 318 | // items: definitions of the functions 319 | let mut idents = vec![token::OpenDelim(token::Bracket)]; 320 | let mut items = Vec::new(); 321 | for wd in 0..(width + 1) { 322 | idents.push(token::OpenDelim(token::Bracket)); 323 | for &ln in &lengths { 324 | // Name for the function interned 325 | let name = format!("decode_{}_{}_{}", ut, wd, ln); 326 | let ident = Ident::from_str(&*name); 327 | idents.push(token::Ident(ident)); 328 | idents.push(token::Comma); 329 | 330 | // Nothing to read 331 | if wd == 0 { 332 | items.push( 333 | quote_item!(cx, 334 | unsafe fn $ident(_: *const u32, o_ptr: *mut $ut) { 335 | std::ptr::write_bytes(o_ptr, 0u8, $ln); 336 | } 337 | ).unwrap() 338 | ); 339 | continue 340 | } 341 | 342 | // Function definition constructed here 343 | let mask_sft = width - wd; 344 | let mut tokens = { 345 | if mask_sft > 0 && wd != 32 { 346 | quote_tokens!(cx, 347 | let mask: $ut = !0 >> $mask_sft; 348 | let mut out; 349 | ) 350 | } else { 351 | quote_tokens!(cx, 352 | let mut out; 353 | ) 354 | } 355 | }; 356 | 357 | // For every integer to be decoded... 358 | let mut s_bits: usize = 32; 359 | let mut o_bits: usize; 360 | for a in 0..ln { 361 | o_bits = wd; 362 | tokens = quote_tokens!(cx, $tokens 363 | out = 364 | ); 365 | 366 | // Decode anything in the available space 367 | let rsft = 32 - s_bits; 368 | tokens = { 369 | if rsft == 0 { 370 | quote_tokens!(cx, $tokens 371 | *s_ptr as $ut; 372 | ) 373 | } else { 374 | quote_tokens!(cx, $tokens 375 | (*s_ptr >> $rsft) as $ut; 376 | ) 377 | } 378 | }; 379 | 380 | // While the available space is not enough... 381 | while o_bits > s_bits { 382 | o_bits -= s_bits; 383 | let lsft = wd - o_bits; 384 | tokens = quote_tokens!(cx, $tokens 385 | s_ptr = s_ptr.offset(1); 386 | out |= (*s_ptr as $ut) << $lsft; 387 | ); 388 | s_bits = 32; 389 | } 390 | s_bits -= o_bits; 391 | 392 | // Move decoded value to o_ptr 393 | tokens = { 394 | if mask_sft > 0 && wd != 32 { 395 | quote_tokens!(cx, $tokens 396 | *o_ptr = out & mask; 397 | ) 398 | } else { 399 | quote_tokens!(cx, $tokens 400 | *o_ptr = out; 401 | ) 402 | } 403 | }; 404 | 405 | // Prepare for the following iteration 406 | if a < ln - 1 { 407 | tokens = quote_tokens!(cx, $tokens 408 | o_ptr = o_ptr.offset(1); 409 | ); 410 | if s_bits == 0 { 411 | tokens = quote_tokens!(cx, $tokens 412 | s_ptr = s_ptr.offset(1); 413 | ); 414 | s_bits = 32; 415 | } 416 | } 417 | } 418 | 419 | // Function definition pushed to items 420 | items.push( 421 | quote_item!(cx, 422 | unsafe fn $ident(mut s_ptr: *const u32, mut o_ptr: *mut $ut) { 423 | $tokens 424 | } 425 | ).unwrap() 426 | ); 427 | } 428 | idents.push(token::CloseDelim(token::Bracket)); 429 | idents.push(token::Comma); 430 | } 431 | idents.push(token::CloseDelim(token::Bracket)); 432 | 433 | // idents converted from tokens to TokenTree 434 | let ttree: Vec = idents 435 | .into_iter() 436 | .map(|token| tokenstream::TokenTree::Token(codemap::DUMMY_SP, token)) 437 | .collect(); 438 | 439 | // DECODE_T definition pushed to items 440 | let name = format!("decode_{}", ut).to_uppercase(); 441 | let ident = Ident::from_str(&*name); 442 | let len1 = lengths.len(); 443 | let len2 = width + 1; 444 | items.push( 445 | quote_item!(cx, 446 | pub const $ident: [[unsafe fn(*const u32, *mut $ut); $len1]; $len2] = $ttree; 447 | ).unwrap() 448 | ); 449 | 450 | // DEBUGGING 451 | // for item in &items { println!("{}", pprust::item_to_string(item)); } 452 | 453 | MacEager::items(small_vector::SmallVector::many(items)) 454 | } 455 | 456 | /// Generates `ENCODE_SIMD_T` containing function pointers, with the pointer 457 | /// for `encode_simd_T_a` at `ENCODE_SIMD_T[a - 1]`. 458 | fn encode_simd_expand(cx: &mut ExtCtxt, 459 | sp: codemap::Span, 460 | tts: &[tokenstream::TokenTree]) -> Box { 461 | // Arguments to the macro invocation 462 | let (width, simd) = { 463 | match parse_simd(cx, sp, tts) { 464 | Some(x) => x, 465 | None => return DummyResult::expr(sp) 466 | } 467 | }; 468 | let ut = Ident::from_str(&*format!("u{}", width)); 469 | let lanes = 128 / width; 470 | 471 | // Construct full path to simd 472 | let mut simd = simd; 473 | simd.segments.push( 474 | ast::PathSegment { 475 | identifier: Ident::from_str(&*format!("u{}x{}", width, lanes)), 476 | parameters: None, 477 | span: Span::default(), 478 | } 479 | ); 480 | 481 | // Construct code to read into register 482 | let mut load = simd.clone(); 483 | load.segments.push( 484 | ast::PathSegment { 485 | identifier: Ident::from_str("load"), 486 | parameters: None, 487 | span: Span::default(), 488 | } 489 | ); 490 | 491 | // idents: tokens used to define the ENCODE_SIMD_T 492 | // items: definitions of the functions 493 | let mut idents = vec![token::OpenDelim(token::Bracket)]; 494 | let mut items = Vec::new(); 495 | for wd in 0..(width + 1) { 496 | // Name for the function interned 497 | let name = format!("encode_simd_{}_{}", ut, wd); 498 | let ident = Ident::from_str(&*name); 499 | idents.push(token::Ident(ident)); 500 | idents.push(token::Comma); 501 | 502 | // Nothing to write 503 | if wd == 0 { 504 | items.push( 505 | quote_item!(cx, 506 | unsafe fn $ident(_: *const $ut, _: *mut u32) { } 507 | ).unwrap() 508 | ); 509 | continue 510 | } 511 | 512 | // Function definition constructed here 513 | let s_len: usize = 128 * wd / width; 514 | let mut tokens = quote_tokens!(cx, 515 | let i_slice = std::slice::from_raw_parts(i_ptr, 128); 516 | let s_slice = std::slice::from_raw_parts_mut(s_ptr as *mut $ut, $s_len); 517 | ); 518 | 519 | let mut i_ind: usize = 0; 520 | let mut s_ind: usize = 0; 521 | tokens = quote_tokens!(cx, $tokens 522 | let rhs = $load(i_slice, $i_ind); 523 | let mut lhs = 524 | ); 525 | i_ind += lanes; 526 | 527 | // For every integer to be encoded... 528 | let mut i_bits: usize; 529 | let mut s_bits: usize = width; 530 | for a in 0..width { 531 | i_bits = wd; 532 | 533 | // Encode in the available space 534 | let lsft = width - s_bits; 535 | if lsft == 0 { 536 | tokens = quote_tokens!(cx, $tokens 537 | rhs; 538 | ); 539 | } else { 540 | tokens = quote_tokens!(cx, $tokens 541 | rhs << $lsft; 542 | ); 543 | } 544 | 545 | // If the available space is not enough 546 | if s_bits < i_bits { 547 | i_bits -= s_bits; 548 | tokens = quote_tokens!(cx, $tokens 549 | lhs.store(s_slice, $s_ind); 550 | lhs = rhs >> $s_bits; 551 | ); 552 | s_bits = width; 553 | s_ind += lanes; 554 | } 555 | s_bits -= i_bits; 556 | 557 | // Prepare for the following iteration 558 | if a < width - 1 { 559 | tokens = quote_tokens!(cx, $tokens 560 | let rhs = $load(i_slice, $i_ind); 561 | ); 562 | i_ind += lanes; 563 | if s_bits == 0 { 564 | tokens = quote_tokens!(cx, $tokens 565 | lhs.store(s_slice, $s_ind); 566 | lhs = 567 | ); 568 | s_bits = width; 569 | s_ind += lanes; 570 | } else { 571 | tokens = quote_tokens!(cx, $tokens 572 | lhs = lhs | 573 | ); 574 | } 575 | } else { 576 | tokens = quote_tokens!(cx, $tokens 577 | lhs.store(s_slice, $s_ind); 578 | ); 579 | } 580 | } 581 | 582 | // Function definition pushed to items 583 | items.push( 584 | quote_item!(cx, 585 | unsafe fn $ident(i_ptr: *const $ut, s_ptr: *mut u32) { 586 | $tokens 587 | } 588 | ).unwrap() 589 | ); 590 | } 591 | idents.push(token::CloseDelim(token::Bracket)); 592 | 593 | // idents converted from tokens to TokenTree 594 | let ttree: Vec = idents 595 | .into_iter() 596 | .map(|token| tokenstream::TokenTree::Token(codemap::DUMMY_SP, token)) 597 | .collect(); 598 | 599 | // ENCODE_SIMD_T definition pushed to items 600 | let name = format!("encode_simd_{}", ut).to_uppercase(); 601 | let ident = Ident::from_str(&*name); 602 | let len1 = width + 1; 603 | items.push( 604 | quote_item!(cx, 605 | pub const $ident: [unsafe fn(*const $ut, *mut u32); $len1] = $ttree; 606 | ).unwrap() 607 | ); 608 | 609 | // DEBUGGING 610 | // for item in &items { println!("{}", pprust::item_to_string(item)); } 611 | 612 | MacEager::items(small_vector::SmallVector::many(items)) 613 | } 614 | 615 | /// Generates `DECODE_SIMD_T` containing function pointers, with the pointer 616 | /// for `decode_simd_T_a` at `DECODE_SIMD_T[a - 1]`. 617 | fn decode_simd_expand(cx: &mut ExtCtxt, 618 | sp: codemap::Span, 619 | tts: &[tokenstream::TokenTree]) -> Box { 620 | // Arguments to the macro invocation 621 | let (width, simd) = { 622 | match parse_simd(cx, sp, tts) { 623 | Some(x) => x, 624 | None => return DummyResult::expr(sp) 625 | } 626 | }; 627 | let ut = Ident::from_str(&*format!("u{}", width)); 628 | let lanes = 128 / width; 629 | 630 | // Construct full path to simd 631 | let mut simd = simd; 632 | simd.segments.push( 633 | ast::PathSegment { 634 | identifier: Ident::from_str(&*format!("u{}x{}", width, lanes)), 635 | parameters: None, 636 | span: Span::default(), 637 | } 638 | ); 639 | 640 | // Construct path for splat 641 | let mut splat = simd.clone(); 642 | splat.segments.push( 643 | ast::PathSegment { 644 | identifier: Ident::from_str("splat"), 645 | parameters: None, 646 | span: Span::default(), 647 | } 648 | ); 649 | 650 | // Construct code to read into register 651 | let mut load = simd.clone(); 652 | load.segments.push( 653 | ast::PathSegment { 654 | identifier: Ident::from_str("load"), 655 | parameters: None, 656 | span: Span::default(), 657 | } 658 | ); 659 | 660 | // idents: tokens used to define the const DECODE_SIMD_T 661 | // items: definitions of the functions 662 | let mut idents = vec![token::OpenDelim(token::Bracket)]; 663 | let mut items = Vec::new(); 664 | for wd in 0..(width + 1) { 665 | // Name for the function interned 666 | let name = format!("decode_simd_{}_{}", ut, wd); 667 | let ident = Ident::from_str(&*name); 668 | idents.push(token::Ident(ident)); 669 | idents.push(token::Comma); 670 | 671 | // Nothing to read 672 | if wd == 0 { 673 | items.push( 674 | quote_item!(cx, 675 | unsafe fn $ident(_: *const u32, o_ptr: *mut $ut) { 676 | std::ptr::write_bytes(o_ptr, 0u8, 128); 677 | } 678 | ).unwrap() 679 | ); 680 | continue 681 | } 682 | 683 | // Function definition constructed here 684 | let s_len: usize = 128 * wd / width; 685 | let mut tokens = quote_tokens!(cx, 686 | let s_slice = std::slice::from_raw_parts(s_ptr as *const $ut, $s_len); 687 | let o_slice = std::slice::from_raw_parts_mut(o_ptr, 128); 688 | ); 689 | 690 | // Handes unused variable warning 691 | let mask_sft = width - wd; 692 | if mask_sft > 0 && wd != width { 693 | tokens = quote_tokens!(cx, $tokens 694 | let mask = $splat(!0) >> $mask_sft; 695 | ); 696 | } 697 | 698 | let mut o_ind: usize = 0; 699 | let mut s_ind: usize = 0; 700 | tokens = quote_tokens!(cx, $tokens 701 | let rhs = $load(s_slice, $s_ind); 702 | let mut lhs; 703 | ); 704 | s_ind += lanes; 705 | 706 | // For every integer to be decoded... 707 | let mut s_bits: usize = width; 708 | let mut o_bits: usize; 709 | for a in 0..width { 710 | o_bits = wd; 711 | tokens = quote_tokens!(cx, $tokens 712 | lhs = 713 | ); 714 | 715 | // Decode anything in the available space 716 | let rsft = width - s_bits; 717 | tokens = { 718 | if rsft == 0 { 719 | quote_tokens!(cx, $tokens 720 | rhs; 721 | ) 722 | } else { 723 | quote_tokens!(cx, $tokens 724 | rhs >> $rsft; 725 | ) 726 | } 727 | }; 728 | 729 | // If the available space is not enough... 730 | if o_bits > s_bits { 731 | o_bits -= s_bits; 732 | tokens = quote_tokens!(cx, $tokens 733 | let rhs = $load(s_slice, $s_ind); 734 | lhs = lhs | rhs << $s_bits; 735 | ); 736 | s_bits = width; 737 | s_ind += lanes; 738 | } 739 | s_bits -= o_bits; 740 | 741 | // Move decoded value to o_ptr 742 | if mask_sft > 0 && wd != width { 743 | tokens = quote_tokens!(cx, $tokens 744 | lhs = lhs & mask; 745 | ); 746 | } 747 | tokens = quote_tokens!(cx, $tokens 748 | lhs.store(o_slice, $o_ind); 749 | ); 750 | o_ind += lanes; 751 | 752 | // Prepare for the following iteration 753 | if (a < width - 1) && s_bits == 0 { 754 | tokens = quote_tokens!(cx, $tokens 755 | let rhs = $load(s_slice, $s_ind); 756 | ); 757 | s_bits = width; 758 | s_ind += lanes; 759 | } 760 | } 761 | 762 | // Function definition pushed to items 763 | items.push( 764 | quote_item!(cx, 765 | unsafe fn $ident(s_ptr: *const u32, o_ptr: *mut $ut) { 766 | $tokens 767 | } 768 | ).unwrap() 769 | ); 770 | } 771 | idents.push(token::CloseDelim(token::Bracket)); 772 | 773 | // idents converted from tokens to TokenTree 774 | let ttree: Vec = idents 775 | .into_iter() 776 | .map(|token| tokenstream::TokenTree::Token(codemap::DUMMY_SP, token)) 777 | .collect(); 778 | 779 | // DECODE_SIMD_T definition pushed to items 780 | let name = format!("decode_simd_{}", ut).to_uppercase(); 781 | let ident = Ident::from_str(&*name); 782 | let len1 = width + 1; 783 | items.push( 784 | quote_item!(cx, 785 | pub const $ident: [unsafe fn(*const u32, *mut $ut); $len1] = $ttree; 786 | ).unwrap() 787 | ); 788 | 789 | // DEBUGGING 790 | // for item in &items { println!("{}", pprust::item_to_string(item)); } 791 | 792 | MacEager::items(small_vector::SmallVector::many(items)) 793 | } 794 | 795 | /// Generates the `encode_delta_T` and `encode_zz_shift_T` functions. 796 | fn encode_util_expand(cx: &mut ExtCtxt, 797 | sp: codemap::Span, 798 | tts: &[tokenstream::TokenTree]) -> Box { 799 | // Arguments to the macro invocation 800 | let (width, simd) = { 801 | match parse_simd(cx, sp, tts) { 802 | Some(x) => x, 803 | None => return DummyResult::expr(sp) 804 | } 805 | }; 806 | let ut = Ident::from_str(&*format!("u{}", width)); 807 | let it = Ident::from_str(&*format!("i{}", width)); 808 | let lanes = 128 / width; 809 | let xsft = width - 1; 810 | 811 | // Construct full path to simd 812 | let mut simd = simd; 813 | simd.segments.push( 814 | ast::PathSegment { 815 | identifier: Ident::from_str(&*format!("i{}x{}", width, lanes)), 816 | parameters: None, 817 | span: Span::default(), 818 | } 819 | ); 820 | 821 | // Construct code to read into register 822 | let mut load = simd.clone(); 823 | load.segments.push( 824 | ast::PathSegment { 825 | identifier: Ident::from_str("load"), 826 | parameters: None, 827 | span: Span::default(), 828 | } 829 | ); 830 | 831 | // items: definitions of the functions 832 | let mut items = Vec::new(); 833 | 834 | // Name for the function interned 835 | let name = format!("encode_delta_{}", ut); 836 | let ident = Ident::from_str(&*name); 837 | 838 | // SIMD SLOWER FOR FEW LANES 839 | items.push( 840 | if lanes > 2 { 841 | quote_item!(cx, 842 | pub unsafe fn $ident(i_ptr: *mut $ut, length: usize) { 843 | let i_slice = std::slice::from_raw_parts_mut(i_ptr as *mut $it, length); 844 | 845 | let mut idx = length; 846 | for _ in 0..((idx - 1) / $lanes) { 847 | idx -= $lanes; 848 | let lhs = $load(i_slice, idx) - $load(i_slice, idx - 1); 849 | lhs.store(i_slice, idx); 850 | } 851 | 852 | for a in (1..(idx as isize)).rev() { 853 | let lwr = *i_ptr.offset(a - 1); 854 | *i_ptr.offset(a) = (*i_ptr.offset(a)).wrapping_sub(lwr); 855 | } 856 | } 857 | ).unwrap() 858 | } else { 859 | quote_item!(cx, 860 | pub unsafe fn $ident(i_ptr: *mut $ut, length: usize) { 861 | for a in (1..(length as isize)).rev() { 862 | let lwr = *i_ptr.offset(a - 1); 863 | *i_ptr.offset(a) = (*i_ptr.offset(a)).wrapping_sub(lwr); 864 | } 865 | } 866 | ).unwrap() 867 | } 868 | ); 869 | 870 | // Name for the function interned 871 | let name = format!("encode_zz_shift_{}", ut); 872 | let ident = Ident::from_str(&*name); 873 | 874 | // SIMD HAS NO MEASURABLE EFFECT 875 | items.push( 876 | quote_item!(cx, 877 | pub unsafe fn $ident(i_ptr: *mut $ut, length: usize, shift: $ut) { 878 | let i_ptr: *mut $it = i_ptr as *mut $it; 879 | let shift: $it = shift as $it; 880 | 881 | for a in 0..(length as isize) { 882 | let rhs = (*i_ptr.offset(a)).wrapping_sub(shift); 883 | *i_ptr.offset(a) = (rhs << 1) ^ (rhs >> $xsft); 884 | } 885 | } 886 | ).unwrap() 887 | ); 888 | 889 | // DEBUGGING 890 | // for item in &items { println!("{}", pprust::item_to_string(item)); } 891 | 892 | MacEager::items(small_vector::SmallVector::many(items)) 893 | } 894 | 895 | /// Parse the two arguments to the encode and decode syntax extensions. 896 | fn parse(cx: &mut ExtCtxt, 897 | sp: codemap::Span, 898 | tts: &[tokenstream::TokenTree]) -> Option<(usize, usize)> { 899 | let mut parser = cx.new_parser_from_tts(tts); 900 | 901 | let entry = cx.expander().fold_expr(parser.parse_expr().unwrap()); 902 | let width = { 903 | match entry.node { 904 | ast::ExprKind::Lit(ref lit) => { 905 | match lit.node { 906 | ast::LitKind::Int(n, _) => n, 907 | _ => { 908 | cx.span_err(entry.span, &format!( 909 | "expected integer literal but got '{}'", 910 | pprust::lit_to_string(&**lit))); 911 | return None 912 | } 913 | } 914 | } 915 | _ => { 916 | cx.span_err(entry.span, &format!( 917 | "expected integer literal but got '{}'", 918 | pprust::expr_to_string(&*entry))); 919 | return None 920 | } 921 | } 922 | }; 923 | parser.eat(&token::Comma); 924 | 925 | let entry = cx.expander().fold_expr(parser.parse_expr().unwrap()); 926 | let step = { 927 | match entry.node { 928 | ast::ExprKind::Lit(ref lit) => { 929 | match lit.node { 930 | ast::LitKind::Int(n, _) => n, 931 | _ => { 932 | cx.span_err(entry.span, &format!( 933 | "expected integer literal but got '{}'", 934 | pprust::lit_to_string(&**lit))); 935 | return None 936 | } 937 | } 938 | } 939 | _ => { 940 | cx.span_err(entry.span, &format!( 941 | "expected integer literal but got '{}'", 942 | pprust::expr_to_string(&*entry))); 943 | return None 944 | } 945 | } 946 | }; 947 | parser.eat(&token::Comma); 948 | 949 | if parser.token != token::Eof { 950 | cx.span_err(sp, "expected exactly two arguments"); 951 | return None 952 | } 953 | 954 | Some((width as usize, step as usize)) 955 | } 956 | 957 | /// Parse the two arguments to the `encode_simd`, `decode_simd`, `encode_util` 958 | /// syntax extensions. 959 | fn parse_simd(cx: &mut ExtCtxt, 960 | sp: codemap::Span, 961 | tts: &[tokenstream::TokenTree]) -> Option<(usize, ast::Path)> { 962 | let mut parser = cx.new_parser_from_tts(tts); 963 | 964 | let entry = cx.expander().fold_expr(parser.parse_expr().unwrap()); 965 | let width = { 966 | match entry.node { 967 | ast::ExprKind::Lit(ref lit) => { 968 | match lit.node { 969 | ast::LitKind::Int(n, _) => n, 970 | _ => { 971 | cx.span_err(entry.span, &format!( 972 | "expected integer literal but got '{}'", 973 | pprust::lit_to_string(&**lit))); 974 | return None 975 | } 976 | } 977 | } 978 | _ => { cx.span_err(entry.span, &format!( 979 | "expected integer literal but got '{}'", 980 | pprust::expr_to_string(&*entry))); 981 | return None 982 | } 983 | } 984 | }; 985 | parser.eat(&token::Comma); 986 | 987 | let entry = cx.expander().fold_expr(parser.parse_expr().unwrap()); 988 | let simd = { 989 | match entry.node { 990 | ast::ExprKind::Path(_, ref p) => p.clone(), 991 | _ => { 992 | cx.span_err(entry.span, &format!( 993 | "expected path but got '{}'", 994 | pprust::expr_to_string(&*entry))); 995 | return None 996 | } 997 | } 998 | }; 999 | 1000 | parser.eat(&token::Comma); 1001 | if parser.token != token::Eof { 1002 | cx.span_err(sp, "expected exactly two arguments"); 1003 | return None 1004 | } 1005 | 1006 | Some((width as usize, simd)) 1007 | } 1008 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly-2018-03-07 2 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! Defines the `mayda::Error` type. Currently only used for the return types of 9 | //! functions defined in the `Encode` trait, but intended to allow for more 10 | //! complex error handling in the future. 11 | 12 | use std::error; 13 | use std::fmt; 14 | 15 | /// The `mayda::Error` type. 16 | #[derive(Debug)] 17 | pub struct Error { 18 | message: String, 19 | } 20 | 21 | impl Error { 22 | /// Creates an empty Error object. 23 | pub fn new(s: &str) -> Error { 24 | Error { 25 | message: s.to_string(), 26 | } 27 | } 28 | } 29 | 30 | impl error::Error for Error { 31 | fn description(&self) -> &str { 32 | &self.message 33 | } 34 | } 35 | 36 | impl fmt::Display for Error { 37 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 38 | write!(f, "{}", self.message) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! `mayda` is a library to compress integer arrays (all primitive integer 9 | //! types are supported). The design favors decompression speed and the ability 10 | //! to index the compressed array over the compression ratio, on the principle 11 | //! that the runtime penalty for using compressed arrays should be as small as 12 | //! possible. 13 | //! 14 | //! This crate provides three variations on a single compression algorithm. The 15 | //! `Uniform` type can decompress around six billion `u32`s per second, or 24 16 | //! GiB/s of decompressed integers, on a 2.6 GHz Intel Core i7-6700HQ processor 17 | //! (see below for specifics). The `Monotone` and `Unimodal` types decompress 18 | //! at a little less than half the speed, but can have much better compression 19 | //! ratios depending on the distribution of the integers. Overall performance is 20 | //! comparable to the fastest (known) libraries in any language. 21 | //! 22 | //! # Usage 23 | //! 24 | //! Add this to your `Cargo.toml`: 25 | //! 26 | //! ```toml 27 | //! [dependencies] 28 | //! mayda = "^0.2" 29 | //! ``` 30 | //! 31 | //! and this to your crate root: 32 | //! 33 | //! ```rust 34 | //! extern crate mayda; 35 | //! ``` 36 | //! 37 | //! # Example: encoding and decoding 38 | //! 39 | //! The `Uniform` struct is recommended for general purpose integer compression. 40 | //! Use the `Encode` trait to encode and decode the array. 41 | //! 42 | //! ```rust 43 | //! use std::mem; 44 | //! use mayda::{Uniform, Encode}; 45 | //! 46 | //! // Integers in some interval of length 255, require one byte per integer 47 | //! let input: Vec = (0..128).map(|x| (x * 73) % 181 + 307).collect(); 48 | //! 49 | //! let mut uniform = Uniform::new(); 50 | //! uniform.encode(&input).unwrap(); 51 | //! 52 | //! let i_bytes = std::mem::size_of_val(input.as_slice()); 53 | //! let u_bytes = std::mem::size_of_val(uniform.storage()); 54 | //! 55 | //! // 128 bytes for encoded entries, 12 bytes of overhead 56 | //! assert_eq!(i_bytes, 512); 57 | //! assert_eq!(u_bytes, 140); 58 | //! 59 | //! let output: Vec = uniform.decode(); 60 | //! assert_eq!(input, output); 61 | //! ``` 62 | //! 63 | //! # Example: indexing 64 | //! 65 | //! Use the `Access` or `AccessInto` traits to index the compressed array. This 66 | //! is similar to `Index`, but returns a vector instead of a slice. 67 | //! 68 | //! ```rust 69 | //! use mayda::{Uniform, Encode, Access}; 70 | //! 71 | //! // All primitive integer types supported 72 | //! let input: Vec = (-64..64).collect(); 73 | //! 74 | //! let mut uniform = Uniform::new(); 75 | //! uniform.encode(&input).unwrap(); 76 | //! 77 | //! let val: i16 = uniform.access(64); 78 | //! assert_eq!(val, 0); 79 | //! 80 | //! // Vector is returned to give ownership to the caller 81 | //! let range: Vec = uniform.access(..10); 82 | //! assert_eq!(range, (-64..-54).collect::>()); 83 | //! ``` 84 | //! 85 | //! # Algorithm 86 | //! 87 | //! The compression algorithm relies on the observation that for many integer 88 | //! arrays, the probability distribution of a block of 128 entries is not 89 | //! uniform over all values that can be represented by the integer type. For 90 | //! example, an array of indices into a second array with 256 entries has 91 | //! entries that are bounded below by 0 and above by 255. This requires only 92 | //! eight bits per entry, rather than the 32 or 64 generally set aside for a 93 | //! usize index. The basic idea of the compression algorithm is to represent 94 | //! all of the entries in a block with a single minimum necessary bit width. 95 | //! This allows SIMD operations and manual loop unrolling to avoid branches to 96 | //! be used to accelerate encoding and decoding. 97 | //! 98 | //! This approach does not perform well for probability distributions with 99 | //! outliers though, or for situations where the median value is nonzero. This 100 | //! crate provides three types that handle this situation by applying different 101 | //! initial transformations to the input integer array. 102 | //! 103 | //! The `Uniform` type targets encoding and decoding speed. The only 104 | //! transformation is to subtract the minimum value from the entries, with the 105 | //! result that the compression depends only on the difference between the 106 | //! largest and smallest entries. 107 | //! 108 | //! The `Monotone` type is specifically intended for arrays with monotone 109 | //! increasing entries. A blocks of entries is transformed into an offset and 110 | //! an array of differences of successive entries, and the array of differences 111 | //! is encoded by the approach above. The compression depends only on the 112 | //! largest entry in the difference array. 113 | //! 114 | //! The `Unimodal` type performs the most extensive transformations and offers 115 | //! the most robust compression. The median value is subtracted from the 116 | //! entries, the entries are mapped to the unsigned integers by the zig-zag 117 | //! encoding, and the most significant bits of any outliers are removed and 118 | //! stored separately. The result is that the compression effectively depends 119 | //! only on the standard deviation of the probability distribution of the block 120 | //! entries. 121 | //! 122 | //! # Indexing 123 | //! 124 | //! Indexing an object of the `Uniform`, `Monotone` or `Unimodal` types is not 125 | //! a simple pointer offset. Part of the header encodes the relative offsets to 126 | //! every block in a compressed form, with the result that random access via 127 | //! the `Access` trait is an `O(log(idx))` operation, where `idx` is the value 128 | //! of the index (not the length of the array). The overhead of this part of 129 | //! the header is around a tenth of a bit per encoded integer. 130 | //! 131 | //! If you need to access several nearby entries, consider accessing the range 132 | //! and indexing the returned vector for performance. 133 | //! 134 | //! # Safety 135 | //! 136 | //! As a general rule, you **should not** decode or access objects of the 137 | //! `Uniform`, `Monotone` or `Unimodal` types from untrusted sources. 138 | //! 139 | //! `mayda` performs wildly unsafe pointer operations during encoding and 140 | //! decoding. Changing the header information with `mut_storage` can cause data 141 | //! to be written to or read from arbitrary addresses in memory. 142 | //! 143 | //! That said, the situation is the same for any of the data structures in the 144 | //! standard library (consider the `set_len` method of a `Vec`). 145 | 146 | #![feature(inclusive_range)] 147 | #![feature(inclusive_range_syntax)] 148 | #![feature(specialization)] 149 | 150 | extern crate mayda_codec; 151 | 152 | pub mod error; 153 | pub mod monotone; 154 | pub mod uniform; 155 | pub mod unimodal; 156 | pub mod utility; 157 | 158 | pub use self::error::Error; 159 | pub use self::monotone::Monotone; 160 | pub use self::uniform::Uniform; 161 | pub use self::unimodal::Unimodal; 162 | pub use self::utility::{Access, AccessInto, Encode}; 163 | -------------------------------------------------------------------------------- /src/utility.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | //! Contains constants, enums, traits and functions used by all of the encoding 9 | //! types provided by the `mayda` crate. 10 | 11 | use std::mem; 12 | 13 | // Flags that indicate minimum width required to decode. Hidden from the docs 14 | // because the constants are implementation dependent. 15 | #[doc(hidden)] 16 | pub const U8_FLAG: u32 = 0x00000000; 17 | #[doc(hidden)] 18 | pub const U16_FLAG: u32 = 0x00000001; 19 | #[doc(hidden)] 20 | pub const U32_FLAG: u32 = 0x00000002; 21 | #[doc(hidden)] 22 | pub const U64_FLAG: u32 = 0x00000003; 23 | 24 | /// Indicates that the bitwise representation of the type is known to `mayda`. 25 | /// Intended to be implemented only for the primitive integer types. Mainly 26 | /// used as a bound on the `Encode` trait. 27 | pub trait Bits { 28 | /// Number of bits in the standard representation. 29 | fn width() -> u32; 30 | 31 | /// Number of bits required to represent the number in binary. Notice that 32 | /// `0.bits() == 0u32` intentionally. 33 | fn bits(&self) -> u32; 34 | } 35 | 36 | macro_rules! bits_impl { 37 | ($(($t: ty: $size: expr))*) => ($( 38 | impl Bits for $t { 39 | #[inline] 40 | fn width() -> u32 { $size } 41 | 42 | #[inline] 43 | fn bits(&self) -> u32 { $size - self.leading_zeros() } 44 | } 45 | )*) 46 | } 47 | 48 | bits_impl!{ 49 | (u8: 8) 50 | (u16: 16) 51 | (u32: 32) 52 | (u64: 64) 53 | (usize: mem::size_of::() as u32 * 8) 54 | (i8: 8) 55 | (i16: 16) 56 | (i32: 32) 57 | (i64: 64) 58 | (isize: mem::size_of::() as u32 * 8) 59 | } 60 | 61 | /// Indicates that the type can be encoded and decoded by `mayda`. 62 | /// 63 | /// The default implementations of `encode` and `decode` return an error or 64 | /// panic to indicate that there is no available specialization for the type. 65 | /// This should not happen unless the user implements `Bits` for some other 66 | /// type or there is a library bug. 67 | pub trait Encode { 68 | /// Encodes the slice into the `Encode` object. 69 | /// 70 | /// # Errors 71 | /// 72 | /// By convention, returns an error if the input slice contains more than the 73 | /// supported number of entries (currently 237 - 27). 74 | fn encode(&mut self, &[B]) -> Result<(), super::Error>; 75 | 76 | /// Decodes the contents of the `Encode` object. Returns a vector because 77 | /// ownership of the returned value must be given to the caller. 78 | fn decode(&self) -> Vec; 79 | 80 | /// Decodes the contents of the `Encode` object and writes the result into 81 | /// the slice provided. More efficient than `decode` if the slice is already 82 | /// allocated. Returns the number of decoded entries. 83 | /// 84 | /// # Panics 85 | /// 86 | /// By convention, panics if the slice is of insufficient length. 87 | fn decode_into(&self, &mut [B]) -> usize; 88 | } 89 | 90 | /// A trait for indexing an encoded vector. Similar to but less convenient than 91 | /// `Index`. `Index::index()` returns a reference, but an encoded vector type 92 | /// must give ownership of the returned value to the caller. 93 | /// 94 | /// # Panics 95 | /// 96 | /// By convention, panics when the index is out of bounds. 97 | /// 98 | /// The default implementations of `access` panic to indicate that there is no 99 | /// available specialization for the type. This should not happen unless there 100 | /// is a library bug. 101 | pub trait Access { 102 | /// The type returned by the access operation. 103 | type Output; 104 | 105 | /// The method for the access `foo.access(bar)` operation. 106 | fn access(&self, Idx) -> Self::Output; 107 | } 108 | 109 | /// A trait for indexing a range of an encoded vector. Writes the result into 110 | /// the slice provided. Similar to but less convenient than `Index`. 111 | /// 112 | /// # Panics 113 | /// 114 | /// By convention, panics when the index is out of bounds or the slice is of 115 | /// insufficient length. 116 | /// 117 | /// The default implementations of `access_into` panic to indicate that there 118 | /// is no available specialization for the type. This should not happen unless 119 | /// there is a library bug. 120 | pub trait AccessInto: Access { 121 | /// The method for the access `foo.access_into(bar, slice)` operation. 122 | fn access_into(&self, Idx, &mut [B]) -> usize; 123 | } 124 | 125 | /// Returns number of words required to store the given number of bits. A word 126 | /// is 32 bits long. 127 | /// 128 | /// # Panics 129 | /// 130 | /// Integer overflow occurs when the value of bits is above `u32::MAX - 31`. 131 | /// This should not happen in `mayda` since this function is only used to find 132 | /// the number of words required for an encoded block of up to 128 integers. 133 | /// 134 | /// # Examples 135 | /// 136 | /// ``` 137 | /// use std::mem; 138 | /// use mayda::utility::words_for_bits; 139 | /// 140 | /// let words = words_for_bits(13 * (mem::size_of::() * 8) as u32); 141 | /// assert_eq!(4, words); 142 | /// ``` 143 | #[inline] 144 | pub fn words_for_bits(bits: u32) -> usize { 145 | ((bits + 31) >> 5) as usize 146 | } 147 | 148 | /// A modified version of the Floyd-Rivest algorithm with fewer comparisions 149 | /// and fewer swaps, specialized for the case of slices with length < 500. The 150 | /// modifications may not be known in the literature. Intended to be used to 151 | /// find the median of a block. 152 | /// 153 | /// # Examples 154 | /// 155 | /// ``` 156 | /// use mayda::utility::select_m; 157 | /// 158 | /// let mut array: [u32; 7] = [1, 4, 2, 8, 5, 7, 1]; 159 | /// 160 | /// let min: u32 = select_m(&mut array, 0); 161 | /// let max: u32 = select_m(&mut array, 6); 162 | /// let med: u32 = select_m(&mut array, 3); 163 | /// 164 | /// assert_eq!(1, min); 165 | /// assert_eq!(8, max); 166 | /// assert_eq!(4, med); 167 | /// ``` 168 | pub fn select_m(array: &mut [T], k: usize) -> T { 169 | unsafe { 170 | let k: *mut T = array.as_mut_ptr().offset(k as isize); 171 | let mut l: *mut T = array.as_mut_ptr(); 172 | let mut r: *mut T = array.as_mut_ptr().offset(array.len() as isize - 1); 173 | 174 | while (l as usize) < (r as usize) { 175 | // Median of three 176 | if *k < *l { 177 | mem::swap(&mut *l, &mut *k); 178 | } 179 | if *k < *r { 180 | mem::swap(&mut *k, &mut *r); 181 | } 182 | if *r < *l { 183 | mem::swap(&mut *r, &mut *l); 184 | } 185 | 186 | // Median value is on the right 187 | let t: T = *r; 188 | 189 | let mut i: *mut T = l.offset(1); 190 | let mut j: *mut T = r.offset(-1); 191 | while *i < t { 192 | i = i.offset(1); 193 | } 194 | while *j > t { 195 | j = j.offset(-1); 196 | } 197 | 198 | while (i as usize) < (j as usize) { 199 | mem::swap(&mut *i, &mut *j); 200 | i = i.offset(1); 201 | j = j.offset(-1); 202 | while *i < t { 203 | i = i.offset(1); 204 | } 205 | while *j > t { 206 | j = j.offset(-1); 207 | } 208 | } 209 | 210 | // Move pivot to sorted positon 211 | j = j.offset(1); 212 | mem::swap(&mut *j, &mut *r); 213 | 214 | if (j as usize) <= (k as usize) { 215 | l = j.offset(1); 216 | } 217 | if (k as usize) <= (j as usize) { 218 | r = j.offset(-1); 219 | } 220 | } 221 | *k 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /tests/monotone.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | #![feature(inclusive_range_syntax)] 9 | #![allow(non_snake_case)] 10 | 11 | extern crate mayda; 12 | extern crate rand; 13 | 14 | use mayda::{Access, AccessInto, Encode, Monotone}; 15 | use rand::distributions::{IndependentSample, Range}; 16 | use std::{isize, usize, i16, i32, i64, i8, u16, u32, u64, u8}; 17 | 18 | fn rand_increasing(min: T, max: T, length: usize) -> Vec 19 | where 20 | T: Ord + rand::distributions::range::SampleRange, 21 | { 22 | let mut output: Vec = Vec::with_capacity(length); 23 | let val = Range::new(min, max); 24 | let mut rng = rand::thread_rng(); 25 | for _ in 0..length { 26 | output.push(val.ind_sample(&mut rng)); 27 | } 28 | output.sort(); 29 | output 30 | } 31 | 32 | macro_rules! random_values { 33 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 34 | #[test] 35 | fn $name() { 36 | let mut bin = Monotone::new(); 37 | let input: Vec<$t> = rand_increasing($min, $max, $length); 38 | println!("{:?}", input); 39 | bin.encode(&input).unwrap(); 40 | for a in bin.storage() { println!("{:032b}", a); } 41 | let output = bin.decode(); 42 | println!("{:?}", output); 43 | assert_eq!(input, output); 44 | } 45 | )*) 46 | } 47 | 48 | random_values!{ 49 | (u8: 0, 16, 0, rv_u8_0_16_0) 50 | (u8: 0, 16, 1, rv_u8_0_16_1) 51 | (u8: 0, 16, 2, rv_u8_0_16_2) 52 | (u8: 0, 16, 3, rv_u8_0_16_3) 53 | (u8: 0, 16, 4, rv_u8_0_16_4) 54 | (u8: 0, 16, 5, rv_u8_0_16_5) 55 | (u8: 0, 16, 7, rv_u8_0_16_7) 56 | (u8: 0, 16, 8, rv_u8_0_16_8) 57 | (u8: 0, 16, 9, rv_u8_0_16_9) 58 | (u8: 0, 16, 15, rv_u8_0_16_15) 59 | (u8: 0, 16, 16, rv_u8_0_16_16) 60 | (u8: 0, 16, 17, rv_u8_0_16_17) 61 | (u8: 0, 16, 31, rv_u8_0_16_31) 62 | (u8: 0, 16, 32, rv_u8_0_16_32) 63 | (u8: 0, 16, 33, rv_u8_0_16_33) 64 | (u8: 0, 64, 127, rv_u8_0_64_127) 65 | (u8: 0, 64, 128, rv_u8_0_64_128) 66 | (u8: 0, 64, 129, rv_u8_0_64_129) 67 | (u8: 0, 128, 511, rv_u8_0_128_511) 68 | (u8: 0, 128, 512, rv_u8_0_128_512) 69 | (u8: 0, 128, 513, rv_u8_0_128_513) 70 | (u8: 0, u8::MAX, 1024, rv_u8_0_MAX_1024) 71 | (i8: -8, 8, 0, rv_i8_8_8_0) 72 | (i8: -8, 8, 1, rv_i8_8_8_1) 73 | (i8: -8, 8, 2, rv_i8_8_8_2) 74 | (i8: -8, 8, 3, rv_i8_8_8_3) 75 | (i8: -8, 8, 4, rv_i8_8_8_4) 76 | (i8: -8, 8, 5, rv_i8_8_8_5) 77 | (i8: -8, 8, 7, rv_i8_8_8_7) 78 | (i8: -8, 8, 8, rv_i8_8_8_8) 79 | (i8: -8, 8, 9, rv_i8_8_8_9) 80 | (i8: -8, 8, 15, rv_i8_8_8_15) 81 | (i8: -8, 8, 16, rv_i8_8_8_16) 82 | (i8: -8, 8, 17, rv_i8_8_8_17) 83 | (i8: -8, 8, 31, rv_i8_8_8_31) 84 | (i8: -8, 8, 32, rv_i8_8_8_32) 85 | (i8: -8, 8, 33, rv_i8_8_8_33) 86 | (i8: -32, 32, 127, rv_i8_32_32_127) 87 | (i8: -32, 32, 128, rv_i8_32_32_128) 88 | (i8: -32, 32, 129, rv_i8_32_32_129) 89 | (i8: -64, 64, 511, rv_i8_64_64_511) 90 | (i8: -64, 64, 512, rv_i8_64_64_512) 91 | (i8: -64, 64, 513, rv_i8_64_64_513) 92 | (i8: i8::MIN, i8::MAX, 1024, rv_i8_MIN_MAX_1024) 93 | } 94 | 95 | random_values!{ 96 | (u16: 0, 16, 0, rv_u16_0_16_0) 97 | (u16: 0, 16, 1, rv_u16_0_16_1) 98 | (u16: 0, 16, 2, rv_u16_0_16_2) 99 | (u16: 0, 16, 3, rv_u16_0_16_3) 100 | (u16: 0, 16, 4, rv_u16_0_16_4) 101 | (u16: 0, 16, 5, rv_u16_0_16_5) 102 | (u16: 0, 16, 7, rv_u16_0_16_7) 103 | (u16: 0, 16, 8, rv_u16_0_16_8) 104 | (u16: 0, 16, 9, rv_u16_0_16_9) 105 | (u16: 0, 16, 15, rv_u16_0_16_15) 106 | (u16: 0, 16, 16, rv_u16_0_16_16) 107 | (u16: 0, 16, 17, rv_u16_0_16_17) 108 | (u16: 0, 16, 31, rv_u16_0_16_31) 109 | (u16: 0, 16, 32, rv_u16_0_16_32) 110 | (u16: 0, 16, 33, rv_u16_0_16_33) 111 | (u16: 0, 64, 127, rv_u16_0_64_127) 112 | (u16: 0, 64, 128, rv_u16_0_64_128) 113 | (u16: 0, 64, 129, rv_u16_0_64_129) 114 | (u16: 0, 128, 511, rv_u16_0_128_511) 115 | (u16: 0, 128, 512, rv_u16_0_128_512) 116 | (u16: 0, 128, 513, rv_u16_0_128_513) 117 | (u16: 0, u16::MAX, 1024, rv_u16_0_MAX_1024) 118 | (i16: -8, 8, 0, rv_i16_8_8_0) 119 | (i16: -8, 8, 1, rv_i16_8_8_1) 120 | (i16: -8, 8, 2, rv_i16_8_8_2) 121 | (i16: -8, 8, 3, rv_i16_8_8_3) 122 | (i16: -8, 8, 4, rv_i16_8_8_4) 123 | (i16: -8, 8, 5, rv_i16_8_8_5) 124 | (i16: -8, 8, 7, rv_i16_8_8_7) 125 | (i16: -8, 8, 8, rv_i16_8_8_8) 126 | (i16: -8, 8, 9, rv_i16_8_8_9) 127 | (i16: -8, 8, 15, rv_i16_8_8_15) 128 | (i16: -8, 8, 16, rv_i16_8_8_16) 129 | (i16: -8, 8, 17, rv_i16_8_8_17) 130 | (i16: -8, 8, 31, rv_i16_8_8_31) 131 | (i16: -8, 8, 32, rv_i16_8_8_32) 132 | (i16: -8, 8, 33, rv_i16_8_8_33) 133 | (i16: -32, 32, 127, rv_i16_32_32_127) 134 | (i16: -32, 32, 128, rv_i16_32_32_128) 135 | (i16: -32, 32, 129, rv_i16_32_32_129) 136 | (i16: -64, 64, 511, rv_i16_64_64_511) 137 | (i16: -64, 64, 512, rv_i16_64_64_512) 138 | (i16: -64, 64, 513, rv_i16_64_64_513) 139 | (i16: i16::MIN, i16::MAX, 1024, rv_i16_MIN_MAX_1024) 140 | } 141 | 142 | random_values!{ 143 | (u32: 0, 16, 0, rv_u32_0_16_0) 144 | (u32: 0, 16, 1, rv_u32_0_16_1) 145 | (u32: 0, 16, 2, rv_u32_0_16_2) 146 | (u32: 0, 16, 3, rv_u32_0_16_3) 147 | (u32: 0, 16, 4, rv_u32_0_16_4) 148 | (u32: 0, 16, 5, rv_u32_0_16_5) 149 | (u32: 0, 16, 7, rv_u32_0_16_7) 150 | (u32: 0, 16, 8, rv_u32_0_16_8) 151 | (u32: 0, 16, 9, rv_u32_0_16_9) 152 | (u32: 0, 16, 15, rv_u32_0_16_15) 153 | (u32: 0, 16, 16, rv_u32_0_16_16) 154 | (u32: 0, 16, 17, rv_u32_0_16_17) 155 | (u32: 0, 16, 31, rv_u32_0_16_31) 156 | (u32: 0, 16, 32, rv_u32_0_16_32) 157 | (u32: 0, 16, 33, rv_u32_0_16_33) 158 | (u32: 0, 64, 127, rv_u32_0_64_127) 159 | (u32: 0, 64, 128, rv_u32_0_64_128) 160 | (u32: 0, 64, 129, rv_u32_0_64_129) 161 | (u32: 0, 128, 511, rv_u32_0_128_511) 162 | (u32: 0, 128, 512, rv_u32_0_128_512) 163 | (u32: 0, 128, 513, rv_u32_0_128_513) 164 | (u32: 0, u32::MAX, 1024, rv_u32_0_MAX_1024) 165 | (i32: -8, 8, 0, rv_i32_8_8_0) 166 | (i32: -8, 8, 1, rv_i32_8_8_1) 167 | (i32: -8, 8, 2, rv_i32_8_8_2) 168 | (i32: -8, 8, 3, rv_i32_8_8_3) 169 | (i32: -8, 8, 4, rv_i32_8_8_4) 170 | (i32: -8, 8, 5, rv_i32_8_8_5) 171 | (i32: -8, 8, 7, rv_i32_8_8_7) 172 | (i32: -8, 8, 8, rv_i32_8_8_8) 173 | (i32: -8, 8, 9, rv_i32_8_8_9) 174 | (i32: -8, 8, 15, rv_i32_8_8_15) 175 | (i32: -8, 8, 16, rv_i32_8_8_16) 176 | (i32: -8, 8, 17, rv_i32_8_8_17) 177 | (i32: -8, 8, 31, rv_i32_8_8_31) 178 | (i32: -8, 8, 32, rv_i32_8_8_32) 179 | (i32: -8, 8, 33, rv_i32_8_8_33) 180 | (i32: -32, 32, 127, rv_i32_32_32_127) 181 | (i32: -32, 32, 128, rv_i32_32_32_128) 182 | (i32: -32, 32, 129, rv_i32_32_32_129) 183 | (i32: -64, 64, 511, rv_i32_64_64_511) 184 | (i32: -64, 64, 512, rv_i32_64_64_512) 185 | (i32: -64, 64, 513, rv_i32_64_64_513) 186 | (i32: i32::MIN, i32::MAX, 1024, rv_i32_MIN_MAX_1024) 187 | } 188 | 189 | random_values!{ 190 | (u64: 0, 16, 0, rv_u64_0_16_0) 191 | (u64: 0, 16, 1, rv_u64_0_16_1) 192 | (u64: 0, 16, 2, rv_u64_0_16_2) 193 | (u64: 0, 16, 3, rv_u64_0_16_3) 194 | (u64: 0, 16, 4, rv_u64_0_16_4) 195 | (u64: 0, 16, 5, rv_u64_0_16_5) 196 | (u64: 0, 16, 7, rv_u64_0_16_7) 197 | (u64: 0, 16, 8, rv_u64_0_16_8) 198 | (u64: 0, 16, 9, rv_u64_0_16_9) 199 | (u64: 0, 16, 15, rv_u64_0_16_15) 200 | (u64: 0, 16, 16, rv_u64_0_16_16) 201 | (u64: 0, 16, 17, rv_u64_0_16_17) 202 | (u64: 0, 16, 31, rv_u64_0_16_31) 203 | (u64: 0, 16, 32, rv_u64_0_16_32) 204 | (u64: 0, 16, 33, rv_u64_0_16_33) 205 | (u64: 0, 64, 127, rv_u64_0_64_127) 206 | (u64: 0, 64, 128, rv_u64_0_64_128) 207 | (u64: 0, 64, 129, rv_u64_0_64_129) 208 | (u64: 0, 128, 511, rv_u64_0_128_511) 209 | (u64: 0, 128, 512, rv_u64_0_128_512) 210 | (u64: 0, 128, 513, rv_u64_0_128_513) 211 | (u64: 0, u64::MAX, 1024, rv_u64_0_MAX_1024) 212 | (i64: -8, 8, 0, rv_i64_8_8_0) 213 | (i64: -8, 8, 1, rv_i64_8_8_1) 214 | (i64: -8, 8, 2, rv_i64_8_8_2) 215 | (i64: -8, 8, 3, rv_i64_8_8_3) 216 | (i64: -8, 8, 4, rv_i64_8_8_4) 217 | (i64: -8, 8, 5, rv_i64_8_8_5) 218 | (i64: -8, 8, 7, rv_i64_8_8_7) 219 | (i64: -8, 8, 8, rv_i64_8_8_8) 220 | (i64: -8, 8, 9, rv_i64_8_8_9) 221 | (i64: -8, 8, 15, rv_i64_8_8_15) 222 | (i64: -8, 8, 16, rv_i64_8_8_16) 223 | (i64: -8, 8, 17, rv_i64_8_8_17) 224 | (i64: -8, 8, 31, rv_i64_8_8_31) 225 | (i64: -8, 8, 32, rv_i64_8_8_32) 226 | (i64: -8, 8, 33, rv_i64_8_8_33) 227 | (i64: -32, 32, 127, rv_i64_32_32_127) 228 | (i64: -32, 32, 128, rv_i64_32_32_128) 229 | (i64: -32, 32, 129, rv_i64_32_32_129) 230 | (i64: -64, 64, 511, rv_i64_64_64_511) 231 | (i64: -64, 64, 512, rv_i64_64_64_512) 232 | (i64: -64, 64, 513, rv_i64_64_64_513) 233 | (i64: i64::MIN, i64::MAX, 1024, rv_i64_MIN_MAX_1024) 234 | } 235 | 236 | // Verify that methods provided by u64 or u32 237 | random_values!{ 238 | (usize: 0, usize::MAX, 1024, cv_usize_0_MAX_1024) 239 | (isize: isize::MIN, isize::MAX, 1024, cv_isize_MIN_MAX_1024) 240 | } 241 | 242 | macro_rules! decode_into { 243 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 244 | #[test] 245 | fn $name() { 246 | let mut bin = Monotone::new(); 247 | let input: Vec<$t> = rand_increasing($min, $max, $length); 248 | println!("{:?}", input); 249 | bin.encode(&input).unwrap(); 250 | for a in bin.storage() { println!("{:032b}", a); } 251 | let mut output = vec![0; $length + 1]; 252 | let length: usize = bin.decode_into(&mut *output); 253 | println!("{:?}", output); 254 | assert_eq!($length, length); 255 | assert_eq!(*input, output[..$length]); 256 | } 257 | )*) 258 | } 259 | 260 | decode_into!{ 261 | (u8: 0, 128, 513, di_u8_0_128_513) 262 | (i8: -64, 64, 513, di_i8_64_64_513) 263 | (u16: 0, 128, 513, di_u16_0_128_513) 264 | (i16: -64, 64, 513, di_i16_64_64_513) 265 | (u32: 0, 128, 513, di_u32_0_128_513) 266 | (i32: -64, 64, 513, di_i32_64_64_513) 267 | (u64: 0, 128, 513, di_u64_0_128_513) 268 | (i64: -64, 64, 513, di_i64_64_64_513) 269 | } 270 | 271 | macro_rules! decode_into_panic { 272 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 273 | #[test] 274 | #[should_panic] 275 | fn $name() { 276 | let mut bin = Monotone::new(); 277 | let input: Vec<$t> = rand_increasing($min, $max, $length); 278 | println!("{:?}", input); 279 | bin.encode(&input).unwrap(); 280 | for a in bin.storage() { println!("{:032b}", a); } 281 | let mut output = vec![0; $length - 1]; 282 | bin.decode_into(&mut *output); 283 | } 284 | )*) 285 | } 286 | 287 | decode_into_panic!{ 288 | (u8: 0, 128, 513, di_pan_u8_0_128_513) 289 | (i8: -64, 64, 513, di_pan_i8_64_64_513) 290 | (u16: 0, 128, 513, di_pan_u16_0_128_513) 291 | (i16: -64, 64, 513, di_pan_i16_64_64_513) 292 | (u32: 0, 128, 513, di_pan_u32_0_128_513) 293 | (i32: -64, 64, 513, di_pan_i32_64_64_513) 294 | (u64: 0, 128, 513, di_pan_u64_0_128_513) 295 | (i64: -64, 64, 513, di_pan_i64_64_64_513) 296 | } 297 | 298 | macro_rules! increasing_values { 299 | ($(($t: ty: $min: expr, $max: expr, $name: ident))*) => ($( 300 | #[test] 301 | fn $name() { 302 | let mut bin = Monotone::new(); 303 | let input: Vec<$t> = ($min..=$max).collect(); 304 | println!("{:?}", input); 305 | bin.encode(&input).unwrap(); 306 | for a in bin.storage() { println!("{:032b}", a); } 307 | let output = bin.decode(); 308 | println!("{:?}", output); 309 | assert_eq!(input, output); 310 | } 311 | )*) 312 | } 313 | 314 | increasing_values!{ 315 | (u8: 0, 255, iv_u8_0_255) 316 | (u16: 0, 255, iv_u16_0_255) 317 | (u32: 0, 255, iv_u32_0_255) 318 | (u64: 0, 255, iv_u64_0_255) 319 | (usize: 0, 255, iv_usize_0_255) 320 | (i8: -128, 127, iv_i8_128_127) 321 | (i16: -128, 127, iv_i16_128_127) 322 | (i32: -128, 127, iv_i32_128_127) 323 | (i64: -128, 127, iv_i64_128_127) 324 | (isize: -128, 127, iv_isize_128_127) 325 | } 326 | 327 | macro_rules! indexing { 328 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 329 | #[test] 330 | fn $name() { 331 | let mut bin = Monotone::new(); 332 | let input: Vec<$t> = rand_increasing($min, $max, $length); 333 | println!("{:?}", input); 334 | bin.encode(&input).unwrap(); 335 | for a in bin.storage() { println!("{:032b}", a); } 336 | for a in 0..$length { 337 | let b = bin.access(a); 338 | println!("{} {}", input[a], b); 339 | assert_eq!(input[a], b); 340 | } 341 | } 342 | )*) 343 | } 344 | 345 | indexing!{ 346 | (u8: 0, u8::MAX, 1024, idx_u8_0_MAX_1024) 347 | (u16: 0, u16::MAX, 1024, idx_u16_0_MAX_1024) 348 | (u32: 0, u32::MAX, 1024, idx_u32_0_MAX_1024) 349 | (u64: 0, u64::MAX, 1024, idx_u64_0_MAX_1024) 350 | (usize: 0, usize::MAX, 1024, idx_usize_0_MAX_1024) 351 | (i8: i8::MIN, i8::MAX, 1024, idx_i8_MIN_MAX_1024) 352 | (i16: i16::MIN, i16::MAX, 1024, idx_i16_MIN_MAX_1024) 353 | (i32: i32::MIN, i32::MAX, 1024, idx_i32_MIN_MAX_1024) 354 | (i64: i64::MIN, i64::MAX, 1024, idx_i64_MIN_MAX_1024) 355 | (isize: isize::MIN, isize::MAX, 1024, idx_isize_MIN_MAX_1024) 356 | } 357 | 358 | macro_rules! indexing_panic { 359 | ($(($t: ty: $length: expr, $idx: expr, $name: ident))*) => ($( 360 | #[test] 361 | #[should_panic] 362 | fn $name() { 363 | let mut bin = Monotone::new(); 364 | let input: Vec<$t> = vec![0; $length]; 365 | println!("{:?}", input); 366 | bin.encode(&input).unwrap(); 367 | for a in bin.storage() { println!("{:032b}", a); } 368 | bin.access($idx); 369 | } 370 | )*) 371 | } 372 | 373 | indexing_panic!{ 374 | (u8: 0, 1, idx_pan_u8_0_1) 375 | (u8: 1, 2, idx_pan_u8_1_2) 376 | (u8: 1, 128, idx_pan_u8_1_128) 377 | (u16: 0, 1, idx_pan_u16_0_1) 378 | (u16: 1, 2, idx_pan_u16_1_2) 379 | (u16: 1, 128, idx_pan_u16_1_128) 380 | (u32: 0, 1, idx_pan_u32_0_1) 381 | (u32: 1, 2, idx_pan_u32_1_2) 382 | (u32: 1, 128, idx_pan_u32_1_128) 383 | (u64: 0, 1, idx_pan_u64_0_1) 384 | (u64: 1, 2, idx_pan_u64_1_2) 385 | (u64: 1, 128, idx_pan_u64_1_128) 386 | (i8: 0, 1, idx_pan_i8_0_1) 387 | (i8: 1, 2, idx_pan_i8_1_2) 388 | (i8: 1, 128, idx_pan_i8_1_128) 389 | (i16: 0, 1, idx_pan_i16_0_1) 390 | (i16: 1, 2, idx_pan_i16_1_2) 391 | (i16: 1, 128, idx_pan_i16_1_128) 392 | (i32: 0, 1, idx_pan_i32_0_1) 393 | (i32: 1, 2, idx_pan_i32_1_2) 394 | (i32: 1, 128, idx_pan_i32_1_128) 395 | (i64: 0, 1, idx_pan_i64_0_1) 396 | (i64: 1, 2, idx_pan_i64_1_2) 397 | (i64: 1, 128, idx_pan_i64_1_128) 398 | } 399 | 400 | macro_rules! range { 401 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $width: expr, $name: ident))*) => ($( 402 | #[test] 403 | fn $name() { 404 | let mut bin = Monotone::new(); 405 | let input = rand_increasing($min, $max, $length); 406 | println!("{:?}", input); 407 | bin.encode(&input).unwrap(); 408 | for a in bin.storage() { println!("{:032b}", a); } 409 | for a in 0..($length - $width + 1) { 410 | let vec = bin.access(a..($width + a)); 411 | println!("{:?} {:?}", &input[a..($width + a)], &vec[..]); 412 | assert_eq!(&input[a..($width + a)], &vec[..]); 413 | } 414 | } 415 | )*) 416 | } 417 | 418 | range!{ 419 | (u8: 0, u8::MAX, 1024, 15, r_u8_0_MAX_1024_15) 420 | (u16: 0, u16::MAX, 1024, 15, r_u16_0_MAX_1024_15) 421 | (u32: 0, u32::MAX, 1024, 15, r_u32_0_MAX_1024_15) 422 | (u64: 0, u64::MAX, 1024, 15, r_u64_0_MAX_1024_15) 423 | (usize: 0, usize::MAX, 1024, 15, r_usize_0_MAX_1024_15) 424 | (i8: i8::MIN, i8::MAX, 1024, 15, r_i8_MIN_MAX_1024_15) 425 | (i16: i16::MIN, i16::MAX, 1024, 15, r_i16_MIN_MAX_1024_15) 426 | (i32: i32::MIN, i32::MAX, 1024, 15, r_i32_MIN_MAX_1024_15) 427 | (i64: i64::MIN, i64::MAX, 1024, 15, r_i64_MIN_MAX_1024_15) 428 | (isize: isize::MIN, isize::MAX, 1024, 15, r_isize_MIN_MAX_1024_15) 429 | } 430 | 431 | macro_rules! range_panic { 432 | ($(($t: ty: $length: expr, $range: expr, $name: ident))*) => ($( 433 | #[test] 434 | #[should_panic] 435 | fn $name() { 436 | let mut bin = Monotone::new(); 437 | let input: Vec<$t> = vec![0; $length]; 438 | println!("{:?}", input); 439 | bin.encode(&input).unwrap(); 440 | for a in bin.storage() { println!("{:032b}", a); } 441 | bin.access($range); 442 | } 443 | )*) 444 | } 445 | 446 | range_panic!{ 447 | (u8: 0, 0..1, r_pan_u8_0_0_1) 448 | (u8: 0, 1..1, r_pan_u8_0_1_1) 449 | (u8: 1, 0..2, r_pan_u8_1_0_2) 450 | (u8: 1, 2..2, r_pan_u8_1_2_2) 451 | (u8: 2, 1..0, r_pan_u8_2_1_0) 452 | (u8: 2, 127..128, r_pan_u8_2_127_128) 453 | (u8: 2, 128..129, r_pan_u8_2_128_129) 454 | (u16: 0, 0..1, r_pan_u16_0_0_1) 455 | (u16: 0, 1..1, r_pan_u16_0_1_1) 456 | (u16: 1, 0..2, r_pan_u16_1_0_2) 457 | (u16: 1, 2..2, r_pan_u16_1_2_2) 458 | (u16: 2, 1..0, r_pan_u16_2_1_0) 459 | (u16: 2, 127..128, r_pan_u16_2_127_128) 460 | (u16: 2, 128..129, r_pan_u16_2_128_129) 461 | (u32: 0, 0..1, r_pan_u32_0_0_1) 462 | (u32: 0, 1..1, r_pan_u32_0_1_1) 463 | (u32: 1, 0..2, r_pan_u32_1_0_2) 464 | (u32: 1, 2..2, r_pan_u32_1_2_2) 465 | (u32: 2, 1..0, r_pan_u32_2_1_0) 466 | (u32: 2, 127..128, r_pan_u32_2_127_128) 467 | (u32: 2, 128..129, r_pan_u32_2_128_129) 468 | (u64: 0, 0..1, r_pan_u64_0_0_1) 469 | (u64: 0, 1..1, r_pan_u64_0_1_1) 470 | (u64: 1, 0..2, r_pan_u64_1_0_2) 471 | (u64: 1, 2..2, r_pan_u64_1_2_2) 472 | (u64: 2, 1..0, r_pan_u64_2_1_0) 473 | (u64: 2, 127..128, r_pan_u64_2_127_128) 474 | (u64: 2, 128..129, r_pan_u64_2_128_129) 475 | (i8: 0, 0..1, r_pan_i8_0_0_1) 476 | (i8: 0, 1..1, r_pan_i8_0_1_1) 477 | (i8: 1, 0..2, r_pan_i8_1_0_2) 478 | (i8: 1, 2..2, r_pan_i8_1_2_2) 479 | (i8: 2, 1..0, r_pan_i8_2_1_0) 480 | (i8: 2, 127..128, r_pan_i8_2_127_128) 481 | (i8: 2, 128..129, r_pan_i8_2_128_129) 482 | (i16: 0, 0..1, r_pan_i16_0_0_1) 483 | (i16: 0, 1..1, r_pan_i16_0_1_1) 484 | (i16: 1, 0..2, r_pan_i16_1_0_2) 485 | (i16: 1, 2..2, r_pan_i16_1_2_2) 486 | (i16: 2, 1..0, r_pan_i16_2_1_0) 487 | (i16: 2, 127..128, r_pan_i16_2_127_128) 488 | (i16: 2, 128..129, r_pan_i16_2_128_129) 489 | (i32: 0, 0..1, r_pan_i32_0_0_1) 490 | (i32: 0, 1..1, r_pan_i32_0_1_1) 491 | (i32: 1, 0..2, r_pan_i32_1_0_2) 492 | (i32: 1, 2..2, r_pan_i32_1_2_2) 493 | (i32: 2, 1..0, r_pan_i32_2_1_0) 494 | (i32: 2, 127..128, r_pan_i32_2_127_128) 495 | (i32: 2, 128..129, r_pan_i32_2_128_129) 496 | (i64: 0, 0..1, r_pan_i64_0_0_1) 497 | (i64: 0, 1..1, r_pan_i64_0_1_1) 498 | (i64: 1, 0..2, r_pan_i64_1_0_2) 499 | (i64: 1, 2..2, r_pan_i64_1_2_2) 500 | (i64: 2, 1..0, r_pan_i64_2_1_0) 501 | (i64: 2, 127..128, r_pan_i64_2_127_128) 502 | (i64: 2, 128..129, r_pan_i64_2_128_129) 503 | } 504 | 505 | macro_rules! range_from { 506 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 507 | #[test] 508 | fn $name() { 509 | let mut bin = Monotone::new(); 510 | let input: Vec<$t> = rand_increasing($min, $max, $length); 511 | println!("{:?}", input); 512 | bin.encode(&input).unwrap(); 513 | for a in bin.storage() { println!("{:032b}", a); } 514 | for a in 0..$length { 515 | let vec = bin.access(a..); 516 | println!("{:?} {:?}", &input[a..], &vec[..]); 517 | assert_eq!(input[a..], vec[..]); 518 | } 519 | } 520 | )*) 521 | } 522 | 523 | range_from!{ 524 | (u8: 0, u8::MAX, 1024, rf_u8_0_MAX_1024) 525 | (u16: 0, u16::MAX, 1024, rf_u16_0_MAX_1024) 526 | (u32: 0, u32::MAX, 1024, rf_u32_0_MAX_1024) 527 | (u64: 0, u64::MAX, 1024, rf_u64_0_MAX_1024) 528 | (usize: 0, usize::MAX, 1024, rf_usize_0_MAX_1024) 529 | (i8: i8::MIN, i8::MAX, 1024, rf_i8_MIN_MAX_1024) 530 | (i16: i16::MIN, i16::MAX, 1024, rf_i16_MIN_MAX_1024) 531 | (i32: i32::MIN, i32::MAX, 1024, rf_i32_MIN_MAX_1024) 532 | (i64: i64::MIN, i64::MAX, 1024, rf_i64_MIN_MAX_1024) 533 | (isize: isize::MIN, isize::MAX, 1024, rf_isize_MIN_MAX_1024) 534 | } 535 | 536 | macro_rules! range_to { 537 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 538 | #[test] 539 | fn $name() { 540 | let mut bin = Monotone::new(); 541 | let input: Vec<$t> = rand_increasing($min, $max, $length); 542 | println!("{:?}", input); 543 | bin.encode(&input).unwrap(); 544 | for a in bin.storage() { println!("{:032b}", a); } 545 | for a in 0..($length + 1) { 546 | let vec = bin.access(..a); 547 | println!("{:?} {:?}", &input[..a], &vec[..]); 548 | assert_eq!(input[..a], vec[..]); 549 | } 550 | } 551 | )*) 552 | } 553 | 554 | range_to!{ 555 | (u8: 0, u8::MAX, 1024, rt_u8_0_MAX_1024) 556 | (u16: 0, u16::MAX, 1024, rt_u16_0_MAX_1024) 557 | (u32: 0, u32::MAX, 1024, rt_u32_0_MAX_1024) 558 | (u64: 0, u64::MAX, 1024, rt_u64_0_MAX_1024) 559 | (usize: 0, usize::MAX, 1024, rt_usize_0_MAX_1024) 560 | (i8: i8::MIN, i8::MAX, 1024, rt_i8_MIN_MAX_1024) 561 | (i16: i16::MIN, i16::MAX, 1024, rt_i16_MIN_MAX_1024) 562 | (i32: i32::MIN, i32::MAX, 1024, rt_i32_MIN_MAX_1024) 563 | (i64: i64::MIN, i64::MAX, 1024, rt_i64_MIN_MAX_1024) 564 | (isize: isize::MIN, isize::MAX, 1024, rt_isize_MIN_MAX_1024) 565 | } 566 | 567 | macro_rules! range_full { 568 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 569 | #[test] 570 | fn $name() { 571 | let mut bin = Monotone::new(); 572 | let input: Vec<$t> = rand_increasing($min, $max, $length); 573 | println!("{:?}", input); 574 | bin.encode(&input).unwrap(); 575 | for a in bin.storage() { println!("{:032b}", a); } 576 | let vec = bin.access(..); 577 | println!("{:?}", vec); 578 | assert_eq!(input[..], vec[..]); 579 | } 580 | )*) 581 | } 582 | 583 | range_full!{ 584 | (u8: 0, u8::MAX, 1024, ru_u8_0_MAX_1024) 585 | (u16: 0, u16::MAX, 1024, ru_u16_0_MAX_1024) 586 | (u32: 0, u32::MAX, 1024, ru_u32_0_MAX_1024) 587 | (u64: 0, u64::MAX, 1024, ru_u64_0_MAX_1024) 588 | (usize: 0, usize::MAX, 1024, ru_usize_0_MAX_1024) 589 | (i8: i8::MIN, i8::MAX, 1024, ru_i8_MIN_MAX_1024) 590 | (i16: i16::MIN, i16::MAX, 1024, ru_i16_MIN_MAX_1024) 591 | (i32: i32::MIN, i32::MAX, 1024, ru_i32_MIN_MAX_1024) 592 | (i64: i64::MIN, i64::MAX, 1024, ru_i64_MIN_MAX_1024) 593 | (isize: isize::MIN, isize::MAX, 1024, ru_isize_MIN_MAX_1024) 594 | } 595 | 596 | macro_rules! range_inclusive { 597 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $width: expr, $name: ident))*) => ($( 598 | #[test] 599 | fn $name() { 600 | let mut bin = Monotone::new(); 601 | let input: Vec<$t> = rand_increasing($min, $max, $length); 602 | println!("{:?}", input); 603 | bin.encode(&input).unwrap(); 604 | for a in bin.storage() { println!("{:032b}", a); } 605 | for a in 0..($length - $width) { 606 | let vec = bin.access(a..=($width + a)); 607 | println!("{:?} {:?}", &input[a..=($width + a)], &vec[..]); 608 | assert_eq!(&input[a..=($width + a)], &vec[..]); 609 | } 610 | } 611 | )*) 612 | } 613 | 614 | range_inclusive!{ 615 | (u8: 0, u8::MAX, 1024, 15, ri_u8_0_MAX_1024_15) 616 | (u16: 0, u16::MAX, 1024, 15, ri_u16_0_MAX_1024_15) 617 | (u32: 0, u32::MAX, 1024, 15, ri_u32_0_MAX_1024_15) 618 | (u64: 0, u64::MAX, 1024, 15, ri_u64_0_MAX_1024_15) 619 | (usize: 0, usize::MAX, 1024, 15, ri_usize_0_MAX_1024_15) 620 | (i8: i8::MIN, i8::MAX, 1024, 15, ri_i8_MIN_MAX_1024_15) 621 | (i16: i16::MIN, i16::MAX, 1024, 15, ri_i16_MIN_MAX_1024_15) 622 | (i32: i32::MIN, i32::MAX, 1024, 15, ri_i32_MIN_MAX_1024_15) 623 | (i64: i64::MIN, i64::MAX, 1024, 15, ri_i64_MIN_MAX_1024_15) 624 | (isize: isize::MIN, isize::MAX, 1024, 15, ri_isize_MIN_MAX_1024_15) 625 | } 626 | 627 | macro_rules! range_into { 628 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $width: expr, $name: ident))*) => ($( 629 | #[test] 630 | fn $name() { 631 | let mut bin = Monotone::new(); 632 | let input: Vec<$t> = rand_increasing($min, $max, $length); 633 | println!("{:?}", input); 634 | bin.encode(&input).unwrap(); 635 | for a in bin.storage() { println!("{:032b}", a); } 636 | let mut output = vec![0; $width + 1]; 637 | for a in 0..($length - $width + 1) { 638 | let width = bin.access_into(a..($width + a), &mut *output); 639 | println!("{:?} {:?}", &input[a..($width + a)], &output[..$width]); 640 | assert_eq!($width, width); 641 | assert_eq!(&input[a..($width + a)], &output[..$width]); 642 | } 643 | } 644 | )*) 645 | } 646 | 647 | range_into!{ 648 | (u8: 0, 128, 513, 15, ri_u8_0_128_513_15) 649 | (i8: -64, 64, 513, 15, ri_i8_64_64_513_15) 650 | (u16: 0, 128, 513, 15, ri_u16_0_128_513_15) 651 | (i16: -64, 64, 513, 15, ri_i16_64_64_513_15) 652 | (u32: 0, 128, 513, 15, ri_u32_0_128_513_15) 653 | (i32: -64, 64, 513, 15, ri_i32_64_64_513_15) 654 | (u64: 0, 128, 513, 15, ri_u64_0_128_513_15) 655 | (i64: -64, 64, 513, 15, ri_i64_64_64_513_15) 656 | } 657 | 658 | macro_rules! range_from_into { 659 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 660 | #[test] 661 | fn $name() { 662 | let mut bin = Monotone::new(); 663 | let input: Vec<$t> = rand_increasing($min, $max, $length); 664 | println!("{:?}", input); 665 | bin.encode(&input).unwrap(); 666 | for a in bin.storage() { println!("{:032b}", a); } 667 | let mut output = vec![0; $length + 1]; 668 | for a in 0..$length { 669 | let width = bin.access_into(a.., &mut *output); 670 | println!("{:?} {:?}", &input[a..], &output[..width]); 671 | assert_eq!(input[a..], output[..width]); 672 | } 673 | } 674 | )*) 675 | } 676 | 677 | range_from_into!{ 678 | (u8: 0, u8::MAX, 1024, rfi_u8_0_MAX_1024) 679 | (u16: 0, u16::MAX, 1024, rfi_u16_0_MAX_1024) 680 | (u32: 0, u32::MAX, 1024, rfi_u32_0_MAX_1024) 681 | (u64: 0, u64::MAX, 1024, rfi_u64_0_MAX_1024) 682 | (usize: 0, usize::MAX, 1024, rfi_usize_0_MAX_1024) 683 | (i8: i8::MIN, i8::MAX, 1024, rfi_i8_MIN_MAX_1024) 684 | (i16: i16::MIN, i16::MAX, 1024, rfi_i16_MIN_MAX_1024) 685 | (i32: i32::MIN, i32::MAX, 1024, rfi_i32_MIN_MAX_1024) 686 | (i64: i64::MIN, i64::MAX, 1024, rfi_i64_MIN_MAX_1024) 687 | (isize: isize::MIN, isize::MAX, 1024, rfi_isize_MIN_MAX_1024) 688 | } 689 | -------------------------------------------------------------------------------- /tests/quickcheck.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | #![feature(inclusive_range_syntax)] 9 | #![feature(plugin)] 10 | #![plugin(quickcheck_macros)] 11 | 12 | extern crate mayda; 13 | extern crate quickcheck; 14 | 15 | use mayda::{Access, AccessInto, Encode, Monotone, Uniform, Unimodal}; 16 | 17 | macro_rules! encode_decode { 18 | ($(($mayda_ty: ident: $int_ty: ty, $name: ident))*) => ($( 19 | #[quickcheck] 20 | fn $name(input: Vec<$int_ty>) -> bool { 21 | let mut bin = $mayda_ty::new(); 22 | bin.encode(&input).unwrap(); 23 | input == bin.decode() 24 | } 25 | )*) 26 | } 27 | 28 | encode_decode!{ 29 | (Monotone: u8, enc_dec_mon_u8) 30 | (Monotone: u16, enc_dec_mon_u16) 31 | (Monotone: u32, enc_dec_mon_u32) 32 | (Monotone: u64, enc_dec_mon_u64) 33 | (Monotone: usize, enc_dec_mon_usize) 34 | (Monotone: i8, enc_dec_mon_i8) 35 | (Monotone: i16, enc_dec_mon_i16) 36 | (Monotone: i32, enc_dec_mon_i32) 37 | (Monotone: i64, enc_dec_mon_i64) 38 | (Monotone: isize, enc_dec_mon_isize) 39 | } 40 | 41 | encode_decode!{ 42 | (Uniform: u8, enc_dec_unf_u8) 43 | (Uniform: u16, enc_dec_unf_u16) 44 | (Uniform: u32, enc_dec_unf_u32) 45 | (Uniform: u64, enc_dec_unf_u64) 46 | (Uniform: usize, enc_dec_unf_usize) 47 | (Uniform: i8, enc_dec_unf_i8) 48 | (Uniform: i16, enc_dec_unf_i16) 49 | (Uniform: i32, enc_dec_unf_i32) 50 | (Uniform: i64, enc_dec_unf_i64) 51 | (Uniform: isize, enc_dec_unf_isize) 52 | } 53 | 54 | encode_decode!{ 55 | (Unimodal: u8, enc_dec_umd_u8) 56 | (Unimodal: u16, enc_dec_umd_u16) 57 | (Unimodal: u32, enc_dec_umd_u32) 58 | (Unimodal: u64, enc_dec_umd_u64) 59 | (Unimodal: usize, enc_dec_umd_usize) 60 | (Unimodal: i8, enc_dec_umd_i8) 61 | (Unimodal: i16, enc_dec_umd_i16) 62 | (Unimodal: i32, enc_dec_umd_i32) 63 | (Unimodal: i64, enc_dec_umd_i64) 64 | (Unimodal: isize, enc_dec_umd_isize) 65 | } 66 | 67 | macro_rules! encode_f_decode_i { 68 | ($(($mayda_ty: ident: $int_ty: ty, $name: ident))*) => ($( 69 | #[quickcheck] 70 | fn $name(input: Vec<$int_ty>) -> bool { 71 | let bin = $mayda_ty::from_slice(&*input).unwrap(); 72 | let mut output: Vec<$int_ty> = vec![0; input.len()]; 73 | bin.decode_into(&mut *output); 74 | input == output 75 | } 76 | )*) 77 | } 78 | 79 | encode_f_decode_i!{ 80 | (Monotone: u8, enc_f_dec_i_mon_u8) 81 | (Monotone: u16, enc_f_dec_i_mon_u16) 82 | (Monotone: u32, enc_f_dec_i_mon_u32) 83 | (Monotone: u64, enc_f_dec_i_mon_u64) 84 | (Monotone: usize, enc_f_dec_i_mon_usize) 85 | (Monotone: i8, enc_f_dec_i_mon_i8) 86 | (Monotone: i16, enc_f_dec_i_mon_i16) 87 | (Monotone: i32, enc_f_dec_i_mon_i32) 88 | (Monotone: i64, enc_f_dec_i_mon_i64) 89 | (Monotone: isize, enc_f_dec_i_mon_isize) 90 | } 91 | 92 | encode_f_decode_i!{ 93 | (Uniform: u8, enc_f_dec_i_unf_u8) 94 | (Uniform: u16, enc_f_dec_i_unf_u16) 95 | (Uniform: u32, enc_f_dec_i_unf_u32) 96 | (Uniform: u64, enc_f_dec_i_unf_u64) 97 | (Uniform: usize, enc_f_dec_i_unf_usize) 98 | (Uniform: i8, enc_f_dec_i_unf_i8) 99 | (Uniform: i16, enc_f_dec_i_unf_i16) 100 | (Uniform: i32, enc_f_dec_i_unf_i32) 101 | (Uniform: i64, enc_f_dec_i_unf_i64) 102 | (Uniform: isize, enc_f_dec_i_unf_isize) 103 | } 104 | 105 | encode_f_decode_i!{ 106 | (Unimodal: u8, enc_f_dec_i_umd_u8) 107 | (Unimodal: u16, enc_f_dec_i_umd_u16) 108 | (Unimodal: u32, enc_f_dec_i_umd_u32) 109 | (Unimodal: u64, enc_f_dec_i_umd_u64) 110 | (Unimodal: usize, enc_f_dec_i_umd_usize) 111 | (Unimodal: i8, enc_f_dec_i_umd_i8) 112 | (Unimodal: i16, enc_f_dec_i_umd_i16) 113 | (Unimodal: i32, enc_f_dec_i_umd_i32) 114 | (Unimodal: i64, enc_f_dec_i_umd_i64) 115 | (Unimodal: isize, enc_f_dec_i_umd_isize) 116 | } 117 | 118 | macro_rules! indexing { 119 | ($(($mayda_ty: ident: $int_ty: ty, $name: ident))*) => ($( 120 | #[quickcheck] 121 | fn $name(input: Vec<$int_ty>) -> bool { 122 | let mut bin = $mayda_ty::new(); 123 | bin.encode(&input).unwrap(); 124 | for a in 0..input.len() { 125 | if input[a] != bin.access(a) { 126 | return false 127 | } 128 | } 129 | true 130 | } 131 | )*) 132 | } 133 | 134 | indexing!{ 135 | (Monotone: u8, idx_mon_u8) 136 | (Monotone: u16, idx_mon_u16) 137 | (Monotone: u32, idx_mon_u32) 138 | (Monotone: u64, idx_mon_u64) 139 | (Monotone: usize, idx_mon_usize) 140 | (Monotone: i8, idx_mon_i8) 141 | (Monotone: i16, idx_mon_i16) 142 | (Monotone: i32, idx_mon_i32) 143 | (Monotone: i64, idx_mon_i64) 144 | (Monotone: isize, idx_mon_isize) 145 | } 146 | 147 | indexing!{ 148 | (Uniform: u8, idx_unf_u8) 149 | (Uniform: u16, idx_unf_u16) 150 | (Uniform: u32, idx_unf_u32) 151 | (Uniform: u64, idx_unf_u64) 152 | (Uniform: usize, idx_unf_usize) 153 | (Uniform: i8, idx_unf_i8) 154 | (Uniform: i16, idx_unf_i16) 155 | (Uniform: i32, idx_unf_i32) 156 | (Uniform: i64, idx_unf_i64) 157 | (Uniform: isize, idx_unf_isize) 158 | } 159 | 160 | indexing!{ 161 | (Unimodal: u8, idx_umd_u8) 162 | (Unimodal: u16, idx_umd_u16) 163 | (Unimodal: u32, idx_umd_u32) 164 | (Unimodal: u64, idx_umd_u64) 165 | (Unimodal: usize, idx_umd_usize) 166 | (Unimodal: i8, idx_umd_i8) 167 | (Unimodal: i16, idx_umd_i16) 168 | (Unimodal: i32, idx_umd_i32) 169 | (Unimodal: i64, idx_umd_i64) 170 | (Unimodal: isize, idx_umd_isize) 171 | } 172 | 173 | macro_rules! range { 174 | ($(($mayda_ty: ident: $int_ty: ty, $name: ident))*) => ($( 175 | #[quickcheck] 176 | fn $name(input: Vec<$int_ty>, lwr: usize, upr: usize) -> bool { 177 | let mut bin = $mayda_ty::new(); 178 | bin.encode(&input).unwrap(); 179 | if input.len() > 0 { 180 | let mut lwr = lwr % input.len(); 181 | let mut upr = upr % (input.len() + 1); 182 | if lwr > upr { std::mem::swap(&mut lwr, &mut upr); } 183 | if input[lwr..upr] != *bin.access(lwr..upr) { 184 | return false 185 | } 186 | } 187 | true 188 | } 189 | )*) 190 | } 191 | 192 | range!{ 193 | (Monotone: u8, r_mon_u8) 194 | (Monotone: u16, r_mon_u16) 195 | (Monotone: u32, r_mon_u32) 196 | (Monotone: u64, r_mon_u64) 197 | (Monotone: usize, r_mon_usize) 198 | (Monotone: i8, r_mon_i8) 199 | (Monotone: i16, r_mon_i16) 200 | (Monotone: i32, r_mon_i32) 201 | (Monotone: i64, r_mon_i64) 202 | (Monotone: isize, r_mon_isize) 203 | } 204 | 205 | range!{ 206 | (Uniform: u8, r_unf_u8) 207 | (Uniform: u16, r_unf_u16) 208 | (Uniform: u32, r_unf_u32) 209 | (Uniform: u64, r_unf_u64) 210 | (Uniform: usize, r_unf_usize) 211 | (Uniform: i8, r_unf_i8) 212 | (Uniform: i16, r_unf_i16) 213 | (Uniform: i32, r_unf_i32) 214 | (Uniform: i64, r_unf_i64) 215 | (Uniform: isize, r_unf_isize) 216 | } 217 | 218 | range!{ 219 | (Unimodal: u8, r_umd_u8) 220 | (Unimodal: u16, r_umd_u16) 221 | (Unimodal: u32, r_umd_u32) 222 | (Unimodal: u64, r_umd_u64) 223 | (Unimodal: usize, r_umd_usize) 224 | (Unimodal: i8, r_umd_i8) 225 | (Unimodal: i16, r_umd_i16) 226 | (Unimodal: i32, r_umd_i32) 227 | (Unimodal: i64, r_umd_i64) 228 | (Unimodal: isize, r_umd_isize) 229 | } 230 | 231 | macro_rules! range_from { 232 | ($(($mayda_ty: ident: $int_ty: ty, $name: ident))*) => ($( 233 | #[quickcheck] 234 | fn $name(input: Vec<$int_ty>) -> bool { 235 | let mut bin = $mayda_ty::new(); 236 | bin.encode(&input).unwrap(); 237 | for a in 0..input.len() { 238 | if input[a..] != *bin.access(a..) { 239 | return false 240 | } 241 | } 242 | true 243 | } 244 | )*) 245 | } 246 | 247 | range_from!{ 248 | (Monotone: u8, rf_mon_u8) 249 | (Monotone: u16, rf_mon_u16) 250 | (Monotone: u32, rf_mon_u32) 251 | (Monotone: u64, rf_mon_u64) 252 | (Monotone: usize, rf_mon_usize) 253 | (Monotone: i8, rf_mon_i8) 254 | (Monotone: i16, rf_mon_i16) 255 | (Monotone: i32, rf_mon_i32) 256 | (Monotone: i64, rf_mon_i64) 257 | (Monotone: isize, rf_mon_isize) 258 | } 259 | 260 | range_from!{ 261 | (Uniform: u8, rf_unf_u8) 262 | (Uniform: u16, rf_unf_u16) 263 | (Uniform: u32, rf_unf_u32) 264 | (Uniform: u64, rf_unf_u64) 265 | (Uniform: usize, rf_unf_usize) 266 | (Uniform: i8, rf_unf_i8) 267 | (Uniform: i16, rf_unf_i16) 268 | (Uniform: i32, rf_unf_i32) 269 | (Uniform: i64, rf_unf_i64) 270 | (Uniform: isize, rf_unf_isize) 271 | } 272 | 273 | range_from!{ 274 | (Unimodal: u8, rf_umd_u8) 275 | (Unimodal: u16, rf_umd_u16) 276 | (Unimodal: u32, rf_umd_u32) 277 | (Unimodal: u64, rf_umd_u64) 278 | (Unimodal: usize, rf_umd_usize) 279 | (Unimodal: i8, rf_umd_i8) 280 | (Unimodal: i16, rf_umd_i16) 281 | (Unimodal: i32, rf_umd_i32) 282 | (Unimodal: i64, rf_umd_i64) 283 | (Unimodal: isize, rf_umd_isize) 284 | } 285 | 286 | macro_rules! range_to { 287 | ($(($mayda_ty: ident: $int_ty: ty, $name: ident))*) => ($( 288 | #[quickcheck] 289 | fn $name(input: Vec<$int_ty>) -> bool { 290 | let mut bin = $mayda_ty::new(); 291 | bin.encode(&input).unwrap(); 292 | for a in 0..(input.len() + 1) { 293 | if input[..a] != *bin.access(..a) { 294 | return false 295 | } 296 | } 297 | true 298 | } 299 | )*) 300 | } 301 | 302 | range_to!{ 303 | (Monotone: u8, rt_mon_u8) 304 | (Monotone: u16, rt_mon_u16) 305 | (Monotone: u32, rt_mon_u32) 306 | (Monotone: u64, rt_mon_u64) 307 | (Monotone: usize, rt_mon_usize) 308 | (Monotone: i8, rt_mon_i8) 309 | (Monotone: i16, rt_mon_i16) 310 | (Monotone: i32, rt_mon_i32) 311 | (Monotone: i64, rt_mon_i64) 312 | (Monotone: isize, rt_mon_isize) 313 | } 314 | 315 | range_to!{ 316 | (Uniform: u8, rt_unf_u8) 317 | (Uniform: u16, rt_unf_u16) 318 | (Uniform: u32, rt_unf_u32) 319 | (Uniform: u64, rt_unf_u64) 320 | (Uniform: usize, rt_unf_usize) 321 | (Uniform: i8, rt_unf_i8) 322 | (Uniform: i16, rt_unf_i16) 323 | (Uniform: i32, rt_unf_i32) 324 | (Uniform: i64, rt_unf_i64) 325 | (Uniform: isize, rt_unf_isize) 326 | } 327 | 328 | range_to!{ 329 | (Unimodal: u8, rt_umd_u8) 330 | (Unimodal: u16, rt_umd_u16) 331 | (Unimodal: u32, rt_umd_u32) 332 | (Unimodal: u64, rt_umd_u64) 333 | (Unimodal: usize, rt_umd_usize) 334 | (Unimodal: i8, rt_umd_i8) 335 | (Unimodal: i16, rt_umd_i16) 336 | (Unimodal: i32, rt_umd_i32) 337 | (Unimodal: i64, rt_umd_i64) 338 | (Unimodal: isize, rt_umd_isize) 339 | } 340 | 341 | macro_rules! range_inclusive { 342 | ($(($mayda_ty: ident: $int_ty: ty, $name: ident))*) => ($( 343 | #[quickcheck] 344 | fn $name(input: Vec<$int_ty>, lwr: usize, upr: usize) -> bool { 345 | let mut bin = $mayda_ty::new(); 346 | bin.encode(&input).unwrap(); 347 | if input.len() > 0 { 348 | let mut lwr = lwr % input.len(); 349 | let mut upr = upr % input.len(); 350 | if lwr > upr { std::mem::swap(&mut lwr, &mut upr); } 351 | if input[lwr..=upr] != *bin.access(lwr..=upr) { 352 | return false 353 | } 354 | } 355 | true 356 | } 357 | )*) 358 | } 359 | 360 | range_inclusive!{ 361 | (Monotone: u8, rc_mon_u8) 362 | (Monotone: u16, rc_mon_u16) 363 | (Monotone: u32, rc_mon_u32) 364 | (Monotone: u64, rc_mon_u64) 365 | (Monotone: usize, rc_mon_usize) 366 | (Monotone: i8, rc_mon_i8) 367 | (Monotone: i16, rc_mon_i16) 368 | (Monotone: i32, rc_mon_i32) 369 | (Monotone: i64, rc_mon_i64) 370 | (Monotone: isize, rc_mon_isize) 371 | } 372 | 373 | range_inclusive!{ 374 | (Uniform: u8, rc_unf_u8) 375 | (Uniform: u16, rc_unf_u16) 376 | (Uniform: u32, rc_unf_u32) 377 | (Uniform: u64, rc_unf_u64) 378 | (Uniform: usize, rc_unf_usize) 379 | (Uniform: i8, rc_unf_i8) 380 | (Uniform: i16, rc_unf_i16) 381 | (Uniform: i32, rc_unf_i32) 382 | (Uniform: i64, rc_unf_i64) 383 | (Uniform: isize, rc_unf_isize) 384 | } 385 | 386 | range_inclusive!{ 387 | (Unimodal: u8, rc_umd_u8) 388 | (Unimodal: u16, rc_umd_u16) 389 | (Unimodal: u32, rc_umd_u32) 390 | (Unimodal: u64, rc_umd_u64) 391 | (Unimodal: usize, rc_umd_usize) 392 | (Unimodal: i8, rc_umd_i8) 393 | (Unimodal: i16, rc_umd_i16) 394 | (Unimodal: i32, rc_umd_i32) 395 | (Unimodal: i64, rc_umd_i64) 396 | (Unimodal: isize, rc_umd_isize) 397 | } 398 | 399 | macro_rules! range_into { 400 | ($(($mayda_ty: ident: $int_ty: ty, $name: ident))*) => ($( 401 | #[quickcheck] 402 | fn $name(input: Vec<$int_ty>, lwr: usize, upr: usize) -> bool { 403 | let mut bin = $mayda_ty::new(); 404 | bin.encode(&input).unwrap(); 405 | if input.len() > 0 { 406 | let mut lwr = lwr % input.len(); 407 | let mut upr = upr % (input.len() + 1); 408 | if lwr > upr { std::mem::swap(&mut lwr, &mut upr); } 409 | let mut output: Vec<$int_ty> = vec![0; upr - lwr]; 410 | bin.access_into(lwr..upr, &mut *output); 411 | if input[lwr..upr] != output[..] { 412 | return false 413 | } 414 | } 415 | true 416 | } 417 | )*) 418 | } 419 | 420 | range_into!{ 421 | (Monotone: u8, ri_mon_u8) 422 | (Monotone: u16, ri_mon_u16) 423 | (Monotone: u32, ri_mon_u32) 424 | (Monotone: u64, ri_mon_u64) 425 | (Monotone: usize, ri_mon_usize) 426 | (Monotone: i8, ri_mon_i8) 427 | (Monotone: i16, ri_mon_i16) 428 | (Monotone: i32, ri_mon_i32) 429 | (Monotone: i64, ri_mon_i64) 430 | (Monotone: isize, ri_mon_isize) 431 | } 432 | 433 | range_into!{ 434 | (Uniform: u8, ri_unf_u8) 435 | (Uniform: u16, ri_unf_u16) 436 | (Uniform: u32, ri_unf_u32) 437 | (Uniform: u64, ri_unf_u64) 438 | (Uniform: usize, ri_unf_usize) 439 | (Uniform: i8, ri_unf_i8) 440 | (Uniform: i16, ri_unf_i16) 441 | (Uniform: i32, ri_unf_i32) 442 | (Uniform: i64, ri_unf_i64) 443 | (Uniform: isize, ri_unf_isize) 444 | } 445 | 446 | range_into!{ 447 | (Unimodal: u8, ri_umd_u8) 448 | (Unimodal: u16, ri_umd_u16) 449 | (Unimodal: u32, ri_umd_u32) 450 | (Unimodal: u64, ri_umd_u64) 451 | (Unimodal: usize, ri_umd_usize) 452 | (Unimodal: i8, ri_umd_i8) 453 | (Unimodal: i16, ri_umd_i16) 454 | (Unimodal: i32, ri_umd_i32) 455 | (Unimodal: i64, ri_umd_i64) 456 | (Unimodal: isize, ri_umd_isize) 457 | } 458 | -------------------------------------------------------------------------------- /tests/uniform.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | #![feature(inclusive_range_syntax)] 9 | #![allow(non_snake_case)] 10 | 11 | extern crate mayda; 12 | extern crate rand; 13 | 14 | use mayda::{Access, AccessInto, Encode, Uniform}; 15 | use rand::distributions::{IndependentSample, Range}; 16 | use std::{isize, usize, i16, i32, i64, i8, u16, u32, u64, u8}; 17 | 18 | fn rand_uniform(min: T, max: T, length: usize) -> Vec 19 | where 20 | T: PartialOrd + rand::distributions::range::SampleRange, 21 | { 22 | let mut output: Vec = Vec::with_capacity(length); 23 | let val = Range::new(min, max); 24 | let mut rng = rand::thread_rng(); 25 | for _ in 0..length { 26 | output.push(val.ind_sample(&mut rng)); 27 | } 28 | output 29 | } 30 | 31 | macro_rules! random_values { 32 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 33 | #[test] 34 | fn $name() { 35 | let mut bin = Uniform::new(); 36 | let input: Vec<$t> = rand_uniform($min, $max, $length); 37 | println!("{:?}", input); 38 | bin.encode(&input).unwrap(); 39 | for a in bin.storage() { println!("{:032b}", a); } 40 | let output = bin.decode(); 41 | println!("{:?}", output); 42 | assert_eq!(input, output); 43 | } 44 | )*) 45 | } 46 | 47 | random_values!{ 48 | (u8: 0, 16, 0, rv_u8_0_16_0) 49 | (u8: 0, 16, 1, rv_u8_0_16_1) 50 | (u8: 0, 16, 2, rv_u8_0_16_2) 51 | (u8: 0, 16, 3, rv_u8_0_16_3) 52 | (u8: 0, 16, 4, rv_u8_0_16_4) 53 | (u8: 0, 16, 5, rv_u8_0_16_5) 54 | (u8: 0, 16, 7, rv_u8_0_16_7) 55 | (u8: 0, 16, 8, rv_u8_0_16_8) 56 | (u8: 0, 16, 9, rv_u8_0_16_9) 57 | (u8: 0, 16, 15, rv_u8_0_16_15) 58 | (u8: 0, 16, 16, rv_u8_0_16_16) 59 | (u8: 0, 16, 17, rv_u8_0_16_17) 60 | (u8: 0, 16, 31, rv_u8_0_16_31) 61 | (u8: 0, 16, 32, rv_u8_0_16_32) 62 | (u8: 0, 16, 33, rv_u8_0_16_33) 63 | (u8: 0, 64, 127, rv_u8_0_64_127) 64 | (u8: 0, 64, 128, rv_u8_0_64_128) 65 | (u8: 0, 64, 129, rv_u8_0_64_129) 66 | (u8: 0, 128, 511, rv_u8_0_128_511) 67 | (u8: 0, 128, 512, rv_u8_0_128_512) 68 | (u8: 0, 128, 513, rv_u8_0_128_513) 69 | (u8: 0, u8::MAX, 1024, rv_u8_0_MAX_1024) 70 | (i8: -8, 8, 0, rv_i8_8_8_0) 71 | (i8: -8, 8, 1, rv_i8_8_8_1) 72 | (i8: -8, 8, 2, rv_i8_8_8_2) 73 | (i8: -8, 8, 3, rv_i8_8_8_3) 74 | (i8: -8, 8, 4, rv_i8_8_8_4) 75 | (i8: -8, 8, 5, rv_i8_8_8_5) 76 | (i8: -8, 8, 7, rv_i8_8_8_7) 77 | (i8: -8, 8, 8, rv_i8_8_8_8) 78 | (i8: -8, 8, 9, rv_i8_8_8_9) 79 | (i8: -8, 8, 15, rv_i8_8_8_15) 80 | (i8: -8, 8, 16, rv_i8_8_8_16) 81 | (i8: -8, 8, 17, rv_i8_8_8_17) 82 | (i8: -8, 8, 31, rv_i8_8_8_31) 83 | (i8: -8, 8, 32, rv_i8_8_8_32) 84 | (i8: -8, 8, 33, rv_i8_8_8_33) 85 | (i8: -32, 32, 127, rv_i8_32_32_127) 86 | (i8: -32, 32, 128, rv_i8_32_32_128) 87 | (i8: -32, 32, 129, rv_i8_32_32_129) 88 | (i8: -64, 64, 511, rv_i8_64_64_511) 89 | (i8: -64, 64, 512, rv_i8_64_64_512) 90 | (i8: -64, 64, 513, rv_i8_64_64_513) 91 | (i8: i8::MIN, i8::MAX, 1024, rv_i8_MIN_MAX_1024) 92 | } 93 | 94 | random_values!{ 95 | (u16: 0, 16, 0, rv_u16_0_16_0) 96 | (u16: 0, 16, 1, rv_u16_0_16_1) 97 | (u16: 0, 16, 2, rv_u16_0_16_2) 98 | (u16: 0, 16, 3, rv_u16_0_16_3) 99 | (u16: 0, 16, 4, rv_u16_0_16_4) 100 | (u16: 0, 16, 5, rv_u16_0_16_5) 101 | (u16: 0, 16, 7, rv_u16_0_16_7) 102 | (u16: 0, 16, 8, rv_u16_0_16_8) 103 | (u16: 0, 16, 9, rv_u16_0_16_9) 104 | (u16: 0, 16, 15, rv_u16_0_16_15) 105 | (u16: 0, 16, 16, rv_u16_0_16_16) 106 | (u16: 0, 16, 17, rv_u16_0_16_17) 107 | (u16: 0, 16, 31, rv_u16_0_16_31) 108 | (u16: 0, 16, 32, rv_u16_0_16_32) 109 | (u16: 0, 16, 33, rv_u16_0_16_33) 110 | (u16: 0, 64, 127, rv_u16_0_64_127) 111 | (u16: 0, 64, 128, rv_u16_0_64_128) 112 | (u16: 0, 64, 129, rv_u16_0_64_129) 113 | (u16: 0, 128, 511, rv_u16_0_128_511) 114 | (u16: 0, 128, 512, rv_u16_0_128_512) 115 | (u16: 0, 128, 513, rv_u16_0_128_513) 116 | (u16: 0, u16::MAX, 1024, rv_u16_0_MAX_1024) 117 | (i16: -8, 8, 0, rv_i16_8_8_0) 118 | (i16: -8, 8, 1, rv_i16_8_8_1) 119 | (i16: -8, 8, 2, rv_i16_8_8_2) 120 | (i16: -8, 8, 3, rv_i16_8_8_3) 121 | (i16: -8, 8, 4, rv_i16_8_8_4) 122 | (i16: -8, 8, 5, rv_i16_8_8_5) 123 | (i16: -8, 8, 7, rv_i16_8_8_7) 124 | (i16: -8, 8, 8, rv_i16_8_8_8) 125 | (i16: -8, 8, 9, rv_i16_8_8_9) 126 | (i16: -8, 8, 15, rv_i16_8_8_15) 127 | (i16: -8, 8, 16, rv_i16_8_8_16) 128 | (i16: -8, 8, 17, rv_i16_8_8_17) 129 | (i16: -8, 8, 31, rv_i16_8_8_31) 130 | (i16: -8, 8, 32, rv_i16_8_8_32) 131 | (i16: -8, 8, 33, rv_i16_8_8_33) 132 | (i16: -32, 32, 127, rv_i16_32_32_127) 133 | (i16: -32, 32, 128, rv_i16_32_32_128) 134 | (i16: -32, 32, 129, rv_i16_32_32_129) 135 | (i16: -64, 64, 511, rv_i16_64_64_511) 136 | (i16: -64, 64, 512, rv_i16_64_64_512) 137 | (i16: -64, 64, 513, rv_i16_64_64_513) 138 | (i16: i16::MIN, i16::MAX, 1024, rv_i16_MIN_MAX_1024) 139 | } 140 | 141 | random_values!{ 142 | (u32: 0, 16, 0, rv_u32_0_16_0) 143 | (u32: 0, 16, 1, rv_u32_0_16_1) 144 | (u32: 0, 16, 2, rv_u32_0_16_2) 145 | (u32: 0, 16, 3, rv_u32_0_16_3) 146 | (u32: 0, 16, 4, rv_u32_0_16_4) 147 | (u32: 0, 16, 5, rv_u32_0_16_5) 148 | (u32: 0, 16, 7, rv_u32_0_16_7) 149 | (u32: 0, 16, 8, rv_u32_0_16_8) 150 | (u32: 0, 16, 9, rv_u32_0_16_9) 151 | (u32: 0, 16, 15, rv_u32_0_16_15) 152 | (u32: 0, 16, 16, rv_u32_0_16_16) 153 | (u32: 0, 16, 17, rv_u32_0_16_17) 154 | (u32: 0, 16, 31, rv_u32_0_16_31) 155 | (u32: 0, 16, 32, rv_u32_0_16_32) 156 | (u32: 0, 16, 33, rv_u32_0_16_33) 157 | (u32: 0, 64, 127, rv_u32_0_64_127) 158 | (u32: 0, 64, 128, rv_u32_0_64_128) 159 | (u32: 0, 64, 129, rv_u32_0_64_129) 160 | (u32: 0, 128, 511, rv_u32_0_128_511) 161 | (u32: 0, 128, 512, rv_u32_0_128_512) 162 | (u32: 0, 128, 513, rv_u32_0_128_513) 163 | (u32: 0, u32::MAX, 1024, rv_u32_0_MAX_1024) 164 | (i32: -8, 8, 0, rv_i32_8_8_0) 165 | (i32: -8, 8, 1, rv_i32_8_8_1) 166 | (i32: -8, 8, 2, rv_i32_8_8_2) 167 | (i32: -8, 8, 3, rv_i32_8_8_3) 168 | (i32: -8, 8, 4, rv_i32_8_8_4) 169 | (i32: -8, 8, 5, rv_i32_8_8_5) 170 | (i32: -8, 8, 7, rv_i32_8_8_7) 171 | (i32: -8, 8, 8, rv_i32_8_8_8) 172 | (i32: -8, 8, 9, rv_i32_8_8_9) 173 | (i32: -8, 8, 15, rv_i32_8_8_15) 174 | (i32: -8, 8, 16, rv_i32_8_8_16) 175 | (i32: -8, 8, 17, rv_i32_8_8_17) 176 | (i32: -8, 8, 31, rv_i32_8_8_31) 177 | (i32: -8, 8, 32, rv_i32_8_8_32) 178 | (i32: -8, 8, 33, rv_i32_8_8_33) 179 | (i32: -32, 32, 127, rv_i32_32_32_127) 180 | (i32: -32, 32, 128, rv_i32_32_32_128) 181 | (i32: -32, 32, 129, rv_i32_32_32_129) 182 | (i32: -64, 64, 511, rv_i32_64_64_511) 183 | (i32: -64, 64, 512, rv_i32_64_64_512) 184 | (i32: -64, 64, 513, rv_i32_64_64_513) 185 | (i32: i32::MIN, i32::MAX, 1024, rv_i32_MIN_MAX_1024) 186 | } 187 | 188 | random_values!{ 189 | (u64: 0, 16, 0, rv_u64_0_16_0) 190 | (u64: 0, 16, 1, rv_u64_0_16_1) 191 | (u64: 0, 16, 2, rv_u64_0_16_2) 192 | (u64: 0, 16, 3, rv_u64_0_16_3) 193 | (u64: 0, 16, 4, rv_u64_0_16_4) 194 | (u64: 0, 16, 5, rv_u64_0_16_5) 195 | (u64: 0, 16, 7, rv_u64_0_16_7) 196 | (u64: 0, 16, 8, rv_u64_0_16_8) 197 | (u64: 0, 16, 9, rv_u64_0_16_9) 198 | (u64: 0, 16, 15, rv_u64_0_16_15) 199 | (u64: 0, 16, 16, rv_u64_0_16_16) 200 | (u64: 0, 16, 17, rv_u64_0_16_17) 201 | (u64: 0, 16, 31, rv_u64_0_16_31) 202 | (u64: 0, 16, 32, rv_u64_0_16_32) 203 | (u64: 0, 16, 33, rv_u64_0_16_33) 204 | (u64: 0, 64, 127, rv_u64_0_64_127) 205 | (u64: 0, 64, 128, rv_u64_0_64_128) 206 | (u64: 0, 64, 129, rv_u64_0_64_129) 207 | (u64: 0, 128, 511, rv_u64_0_128_511) 208 | (u64: 0, 128, 512, rv_u64_0_128_512) 209 | (u64: 0, 128, 513, rv_u64_0_128_513) 210 | (u64: 0, u64::MAX, 1024, rv_u64_0_MAX_1024) 211 | (i64: -8, 8, 0, rv_i64_8_8_0) 212 | (i64: -8, 8, 1, rv_i64_8_8_1) 213 | (i64: -8, 8, 2, rv_i64_8_8_2) 214 | (i64: -8, 8, 3, rv_i64_8_8_3) 215 | (i64: -8, 8, 4, rv_i64_8_8_4) 216 | (i64: -8, 8, 5, rv_i64_8_8_5) 217 | (i64: -8, 8, 7, rv_i64_8_8_7) 218 | (i64: -8, 8, 8, rv_i64_8_8_8) 219 | (i64: -8, 8, 9, rv_i64_8_8_9) 220 | (i64: -8, 8, 15, rv_i64_8_8_15) 221 | (i64: -8, 8, 16, rv_i64_8_8_16) 222 | (i64: -8, 8, 17, rv_i64_8_8_17) 223 | (i64: -8, 8, 31, rv_i64_8_8_31) 224 | (i64: -8, 8, 32, rv_i64_8_8_32) 225 | (i64: -8, 8, 33, rv_i64_8_8_33) 226 | (i64: -32, 32, 127, rv_i64_32_32_127) 227 | (i64: -32, 32, 128, rv_i64_32_32_128) 228 | (i64: -32, 32, 129, rv_i64_32_32_129) 229 | (i64: -64, 64, 511, rv_i64_64_64_511) 230 | (i64: -64, 64, 512, rv_i64_64_64_512) 231 | (i64: -64, 64, 513, rv_i64_64_64_513) 232 | (i64: i64::MIN, i64::MAX, 1024, rv_i64_MIN_MAX_1024) 233 | } 234 | 235 | // Verify that methods provided by u64 or u32 236 | random_values!{ 237 | (usize: 0, usize::MAX, 1024, cv_usize_0_MAX_1024) 238 | (isize: isize::MIN, isize::MAX, 1024, cv_isize_MIN_MAX_1024) 239 | } 240 | 241 | macro_rules! decode_into { 242 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 243 | #[test] 244 | fn $name() { 245 | let mut bin = Uniform::new(); 246 | let input: Vec<$t> = rand_uniform($min, $max, $length); 247 | println!("{:?}", input); 248 | bin.encode(&input).unwrap(); 249 | for a in bin.storage() { println!("{:032b}", a); } 250 | let mut output = vec![0; $length + 1]; 251 | let length: usize = bin.decode_into(&mut *output); 252 | println!("{:?}", output); 253 | assert_eq!($length, length); 254 | assert_eq!(*input, output[..$length]); 255 | } 256 | )*) 257 | } 258 | 259 | decode_into!{ 260 | (u8: 0, 128, 513, di_u8_0_128_513) 261 | (i8: -64, 64, 513, di_i8_64_64_513) 262 | (u16: 0, 128, 513, di_u16_0_128_513) 263 | (i16: -64, 64, 513, di_i16_64_64_513) 264 | (u32: 0, 128, 513, di_u32_0_128_513) 265 | (i32: -64, 64, 513, di_i32_64_64_513) 266 | (u64: 0, 128, 513, di_u64_0_128_513) 267 | (i64: -64, 64, 513, di_i64_64_64_513) 268 | } 269 | 270 | macro_rules! decode_into_panic { 271 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 272 | #[test] 273 | #[should_panic] 274 | fn $name() { 275 | let mut bin = Uniform::new(); 276 | let input: Vec<$t> = rand_uniform($min, $max, $length); 277 | println!("{:?}", input); 278 | bin.encode(&input).unwrap(); 279 | for a in bin.storage() { println!("{:032b}", a); } 280 | let mut output = vec![0; $length - 1]; 281 | bin.decode_into(&mut *output); 282 | } 283 | )*) 284 | } 285 | 286 | decode_into_panic!{ 287 | (u8: 0, 128, 513, di_pan_u8_0_128_513) 288 | (i8: -64, 64, 513, di_pan_i8_64_64_513) 289 | (u16: 0, 128, 513, di_pan_u16_0_128_513) 290 | (i16: -64, 64, 513, di_pan_i16_64_64_513) 291 | (u32: 0, 128, 513, di_pan_u32_0_128_513) 292 | (i32: -64, 64, 513, di_pan_i32_64_64_513) 293 | (u64: 0, 128, 513, di_pan_u64_0_128_513) 294 | (i64: -64, 64, 513, di_pan_i64_64_64_513) 295 | } 296 | 297 | macro_rules! increasing_values { 298 | ($(($t: ty: $min: expr, $max: expr, $name: ident))*) => ($( 299 | #[test] 300 | fn $name() { 301 | let mut bin = Uniform::new(); 302 | let input: Vec<$t> = ($min..=$max).collect(); 303 | println!("{:?}", input); 304 | bin.encode(&input).unwrap(); 305 | for a in bin.storage() { println!("{:032b}", a); } 306 | let output = bin.decode(); 307 | println!("{:?}", output); 308 | assert_eq!(input, output); 309 | } 310 | )*) 311 | } 312 | 313 | increasing_values!{ 314 | (u8: 0, 255, iv_u8_0_255) 315 | (u16: 0, 255, iv_u16_0_255) 316 | (u32: 0, 255, iv_u32_0_255) 317 | (u64: 0, 255, iv_u64_0_255) 318 | (usize: 0, 255, iv_usize_0_255) 319 | (i8: -128, 127, iv_i8_128_127) 320 | (i16: -128, 127, iv_i16_128_127) 321 | (i32: -128, 127, iv_i32_128_127) 322 | (i64: -128, 127, iv_i64_128_127) 323 | (isize: -128, 127, iv_isize_128_127) 324 | } 325 | 326 | macro_rules! indexing { 327 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 328 | #[test] 329 | fn $name() { 330 | let mut bin = Uniform::new(); 331 | let input: Vec<$t> = rand_uniform($min, $max, $length); 332 | println!("{:?}", input); 333 | bin.encode(&input).unwrap(); 334 | for a in bin.storage() { println!("{:032b}", a); } 335 | for a in 0..$length { 336 | let b = bin.access(a); 337 | println!("{} {}", input[a], b); 338 | assert_eq!(input[a], b); 339 | } 340 | } 341 | )*) 342 | } 343 | 344 | indexing!{ 345 | (u8: 0, u8::MAX, 1024, idx_u8_0_MAX_1024) 346 | (u16: 0, u16::MAX, 1024, idx_u16_0_MAX_1024) 347 | (u32: 0, u32::MAX, 1024, idx_u32_0_MAX_1024) 348 | (u64: 0, u64::MAX, 1024, idx_u64_0_MAX_1024) 349 | (usize: 0, usize::MAX, 1024, idx_usize_0_MAX_1024) 350 | (i8: i8::MIN, i8::MAX, 1024, idx_i8_MIN_MAX_1024) 351 | (i16: i16::MIN, i16::MAX, 1024, idx_i16_MIN_MAX_1024) 352 | (i32: i32::MIN, i32::MAX, 1024, idx_i32_MIN_MAX_1024) 353 | (i64: i64::MIN, i64::MAX, 1024, idx_i64_MIN_MAX_1024) 354 | (isize: isize::MIN, isize::MAX, 1024, idx_isize_MIN_MAX_1024) 355 | } 356 | 357 | macro_rules! indexing_panic { 358 | ($(($t: ty: $length: expr, $idx: expr, $name: ident))*) => ($( 359 | #[test] 360 | #[should_panic] 361 | fn $name() { 362 | let mut bin = Uniform::new(); 363 | let input: Vec<$t> = vec![0; $length]; 364 | println!("{:?}", input); 365 | bin.encode(&input).unwrap(); 366 | for a in bin.storage() { println!("{:032b}", a); } 367 | bin.access($idx); 368 | } 369 | )*) 370 | } 371 | 372 | indexing_panic!{ 373 | (u8: 0, 1, idx_pan_u8_0_1) 374 | (u8: 1, 2, idx_pan_u8_1_2) 375 | (u8: 1, 128, idx_pan_u8_1_128) 376 | (u16: 0, 1, idx_pan_u16_0_1) 377 | (u16: 1, 2, idx_pan_u16_1_2) 378 | (u16: 1, 128, idx_pan_u16_1_128) 379 | (u32: 0, 1, idx_pan_u32_0_1) 380 | (u32: 1, 2, idx_pan_u32_1_2) 381 | (u32: 1, 128, idx_pan_u32_1_128) 382 | (u64: 0, 1, idx_pan_u64_0_1) 383 | (u64: 1, 2, idx_pan_u64_1_2) 384 | (u64: 1, 128, idx_pan_u64_1_128) 385 | (i8: 0, 1, idx_pan_i8_0_1) 386 | (i8: 1, 2, idx_pan_i8_1_2) 387 | (i8: 1, 128, idx_pan_i8_1_128) 388 | (i16: 0, 1, idx_pan_i16_0_1) 389 | (i16: 1, 2, idx_pan_i16_1_2) 390 | (i16: 1, 128, idx_pan_i16_1_128) 391 | (i32: 0, 1, idx_pan_i32_0_1) 392 | (i32: 1, 2, idx_pan_i32_1_2) 393 | (i32: 1, 128, idx_pan_i32_1_128) 394 | (i64: 0, 1, idx_pan_i64_0_1) 395 | (i64: 1, 2, idx_pan_i64_1_2) 396 | (i64: 1, 128, idx_pan_i64_1_128) 397 | } 398 | 399 | macro_rules! range { 400 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $width: expr, $name: ident))*) => ($( 401 | #[test] 402 | fn $name() { 403 | let mut bin = Uniform::new(); 404 | let input: Vec<$t> = rand_uniform($min, $max, $length); 405 | println!("{:?}", input); 406 | bin.encode(&input).unwrap(); 407 | for a in bin.storage() { println!("{:032b}", a); } 408 | for a in 0..($length - $width + 1) { 409 | let vec = bin.access(a..($width + a)); 410 | println!("{:?} {:?}", &input[a..($width + a)], &vec[..]); 411 | assert_eq!(&input[a..($width + a)], &vec[..]); 412 | } 413 | } 414 | )*) 415 | } 416 | 417 | range!{ 418 | (u8: 0, u8::MAX, 1024, 15, r_u8_0_MAX_1024_15) 419 | (u16: 0, u16::MAX, 1024, 15, r_u16_0_MAX_1024_15) 420 | (u32: 0, u32::MAX, 1024, 15, r_u32_0_MAX_1024_15) 421 | (u64: 0, u64::MAX, 1024, 15, r_u64_0_MAX_1024_15) 422 | (usize: 0, usize::MAX, 1024, 15, r_usize_0_MAX_1024_15) 423 | (i8: i8::MIN, i8::MAX, 1024, 15, r_i8_MIN_MAX_1024_15) 424 | (i16: i16::MIN, i16::MAX, 1024, 15, r_i16_MIN_MAX_1024_15) 425 | (i32: i32::MIN, i32::MAX, 1024, 15, r_i32_MIN_MAX_1024_15) 426 | (i64: i64::MIN, i64::MAX, 1024, 15, r_i64_MIN_MAX_1024_15) 427 | (isize: isize::MIN, isize::MAX, 1024, 15, r_isize_MIN_MAX_1024_15) 428 | } 429 | 430 | macro_rules! range_panic { 431 | ($(($t: ty: $length: expr, $range: expr, $name: ident))*) => ($( 432 | #[test] 433 | #[should_panic] 434 | fn $name() { 435 | let mut bin = Uniform::new(); 436 | let input: Vec<$t> = vec![0; $length]; 437 | println!("{:?}", input); 438 | bin.encode(&input).unwrap(); 439 | for a in bin.storage() { println!("{:032b}", a); } 440 | bin.access($range); 441 | } 442 | )*) 443 | } 444 | 445 | range_panic!{ 446 | (u8: 0, 0..1, r_pan_u8_0_0_1) 447 | (u8: 0, 1..1, r_pan_u8_0_1_1) 448 | (u8: 1, 0..2, r_pan_u8_1_0_2) 449 | (u8: 1, 2..2, r_pan_u8_1_2_2) 450 | (u8: 2, 1..0, r_pan_u8_2_1_0) 451 | (u8: 2, 127..128, r_pan_u8_2_127_128) 452 | (u8: 2, 128..129, r_pan_u8_2_128_129) 453 | (u16: 0, 0..1, r_pan_u16_0_0_1) 454 | (u16: 0, 1..1, r_pan_u16_0_1_1) 455 | (u16: 1, 0..2, r_pan_u16_1_0_2) 456 | (u16: 1, 2..2, r_pan_u16_1_2_2) 457 | (u16: 2, 1..0, r_pan_u16_2_1_0) 458 | (u16: 2, 127..128, r_pan_u16_2_127_128) 459 | (u16: 2, 128..129, r_pan_u16_2_128_129) 460 | (u32: 0, 0..1, r_pan_u32_0_0_1) 461 | (u32: 0, 1..1, r_pan_u32_0_1_1) 462 | (u32: 1, 0..2, r_pan_u32_1_0_2) 463 | (u32: 1, 2..2, r_pan_u32_1_2_2) 464 | (u32: 2, 1..0, r_pan_u32_2_1_0) 465 | (u32: 2, 127..128, r_pan_u32_2_127_128) 466 | (u32: 2, 128..129, r_pan_u32_2_128_129) 467 | (u64: 0, 0..1, r_pan_u64_0_0_1) 468 | (u64: 0, 1..1, r_pan_u64_0_1_1) 469 | (u64: 1, 0..2, r_pan_u64_1_0_2) 470 | (u64: 1, 2..2, r_pan_u64_1_2_2) 471 | (u64: 2, 1..0, r_pan_u64_2_1_0) 472 | (u64: 2, 127..128, r_pan_u64_2_127_128) 473 | (u64: 2, 128..129, r_pan_u64_2_128_129) 474 | (i8: 0, 0..1, r_pan_i8_0_0_1) 475 | (i8: 0, 1..1, r_pan_i8_0_1_1) 476 | (i8: 1, 0..2, r_pan_i8_1_0_2) 477 | (i8: 1, 2..2, r_pan_i8_1_2_2) 478 | (i8: 2, 1..0, r_pan_i8_2_1_0) 479 | (i8: 2, 127..128, r_pan_i8_2_127_128) 480 | (i8: 2, 128..129, r_pan_i8_2_128_129) 481 | (i16: 0, 0..1, r_pan_i16_0_0_1) 482 | (i16: 0, 1..1, r_pan_i16_0_1_1) 483 | (i16: 1, 0..2, r_pan_i16_1_0_2) 484 | (i16: 1, 2..2, r_pan_i16_1_2_2) 485 | (i16: 2, 1..0, r_pan_i16_2_1_0) 486 | (i16: 2, 127..128, r_pan_i16_2_127_128) 487 | (i16: 2, 128..129, r_pan_i16_2_128_129) 488 | (i32: 0, 0..1, r_pan_i32_0_0_1) 489 | (i32: 0, 1..1, r_pan_i32_0_1_1) 490 | (i32: 1, 0..2, r_pan_i32_1_0_2) 491 | (i32: 1, 2..2, r_pan_i32_1_2_2) 492 | (i32: 2, 1..0, r_pan_i32_2_1_0) 493 | (i32: 2, 127..128, r_pan_i32_2_127_128) 494 | (i32: 2, 128..129, r_pan_i32_2_128_129) 495 | (i64: 0, 0..1, r_pan_i64_0_0_1) 496 | (i64: 0, 1..1, r_pan_i64_0_1_1) 497 | (i64: 1, 0..2, r_pan_i64_1_0_2) 498 | (i64: 1, 2..2, r_pan_i64_1_2_2) 499 | (i64: 2, 1..0, r_pan_i64_2_1_0) 500 | (i64: 2, 127..128, r_pan_i64_2_127_128) 501 | (i64: 2, 128..129, r_pan_i64_2_128_129) 502 | } 503 | 504 | macro_rules! range_from { 505 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 506 | #[test] 507 | fn $name() { 508 | let mut bin = Uniform::new(); 509 | let input: Vec<$t> = rand_uniform($min, $max, $length); 510 | println!("{:?}", input); 511 | bin.encode(&input).unwrap(); 512 | for a in bin.storage() { println!("{:032b}", a); } 513 | for a in 0..$length { 514 | let vec = bin.access(a..); 515 | println!("{:?} {:?}", &input[a..], &vec[..]); 516 | assert_eq!(input[a..], vec[..]); 517 | } 518 | } 519 | )*) 520 | } 521 | 522 | range_from!{ 523 | (u8: 0, u8::MAX, 1024, rf_u8_0_MAX_1024) 524 | (u16: 0, u16::MAX, 1024, rf_u16_0_MAX_1024) 525 | (u32: 0, u32::MAX, 1024, rf_u32_0_MAX_1024) 526 | (u64: 0, u64::MAX, 1024, rf_u64_0_MAX_1024) 527 | (usize: 0, usize::MAX, 1024, rf_usize_0_MAX_1024) 528 | (i8: i8::MIN, i8::MAX, 1024, rf_i8_MIN_MAX_1024) 529 | (i16: i16::MIN, i16::MAX, 1024, rf_i16_MIN_MAX_1024) 530 | (i32: i32::MIN, i32::MAX, 1024, rf_i32_MIN_MAX_1024) 531 | (i64: i64::MIN, i64::MAX, 1024, rf_i64_MIN_MAX_1024) 532 | (isize: isize::MIN, isize::MAX, 1024, rf_isize_MIN_MAX_1024) 533 | } 534 | 535 | macro_rules! range_to { 536 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 537 | #[test] 538 | fn $name() { 539 | let mut bin = Uniform::new(); 540 | let input: Vec<$t> = rand_uniform($min, $max, $length); 541 | println!("{:?}", input); 542 | bin.encode(&input).unwrap(); 543 | for a in bin.storage() { println!("{:032b}", a); } 544 | for a in 0..($length + 1) { 545 | let vec = bin.access(..a); 546 | println!("{:?} {:?}", &input[..a], &vec[..]); 547 | assert_eq!(input[..a], vec[..]); 548 | } 549 | } 550 | )*) 551 | } 552 | 553 | range_to!{ 554 | (u8: 0, u8::MAX, 1024, rt_u8_0_MAX_1024) 555 | (u16: 0, u16::MAX, 1024, rt_u16_0_MAX_1024) 556 | (u32: 0, u32::MAX, 1024, rt_u32_0_MAX_1024) 557 | (u64: 0, u64::MAX, 1024, rt_u64_0_MAX_1024) 558 | (usize: 0, usize::MAX, 1024, rt_usize_0_MAX_1024) 559 | (i8: i8::MIN, i8::MAX, 1024, rt_i8_MIN_MAX_1024) 560 | (i16: i16::MIN, i16::MAX, 1024, rt_i16_MIN_MAX_1024) 561 | (i32: i32::MIN, i32::MAX, 1024, rt_i32_MIN_MAX_1024) 562 | (i64: i64::MIN, i64::MAX, 1024, rt_i64_MIN_MAX_1024) 563 | (isize: isize::MIN, isize::MAX, 1024, rt_isize_MIN_MAX_1024) 564 | } 565 | 566 | macro_rules! range_full { 567 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 568 | #[test] 569 | fn $name() { 570 | let mut bin = Uniform::new(); 571 | let input: Vec<$t> = rand_uniform($min, $max, $length); 572 | println!("{:?}", input); 573 | bin.encode(&input).unwrap(); 574 | for a in bin.storage() { println!("{:032b}", a); } 575 | let vec = bin.access(..); 576 | println!("{:?}", vec); 577 | assert_eq!(input[..], vec[..]); 578 | } 579 | )*) 580 | } 581 | 582 | range_full!{ 583 | (u8: 0, u8::MAX, 1024, ru_u8_0_MAX_1024) 584 | (u16: 0, u16::MAX, 1024, ru_u16_0_MAX_1024) 585 | (u32: 0, u32::MAX, 1024, ru_u32_0_MAX_1024) 586 | (u64: 0, u64::MAX, 1024, ru_u64_0_MAX_1024) 587 | (usize: 0, usize::MAX, 1024, ru_usize_0_MAX_1024) 588 | (i8: i8::MIN, i8::MAX, 1024, ru_i8_MIN_MAX_1024) 589 | (i16: i16::MIN, i16::MAX, 1024, ru_i16_MIN_MAX_1024) 590 | (i32: i32::MIN, i32::MAX, 1024, ru_i32_MIN_MAX_1024) 591 | (i64: i64::MIN, i64::MAX, 1024, ru_i64_MIN_MAX_1024) 592 | (isize: isize::MIN, isize::MAX, 1024, ru_isize_MIN_MAX_1024) 593 | } 594 | 595 | macro_rules! range_inclusive { 596 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $width: expr, $name: ident))*) => ($( 597 | #[test] 598 | fn $name() { 599 | let mut bin = Uniform::new(); 600 | let input: Vec<$t> = rand_uniform($min, $max, $length); 601 | println!("{:?}", input); 602 | bin.encode(&input).unwrap(); 603 | for a in bin.storage() { println!("{:032b}", a); } 604 | for a in 0..($length - $width) { 605 | let vec = bin.access(a..=($width + a)); 606 | println!("{:?} {:?}", &input[a..=($width + a)], &vec[..]); 607 | assert_eq!(&input[a..=($width + a)], &vec[..]); 608 | } } 609 | )*) 610 | } 611 | 612 | range_inclusive!{ 613 | (u8: 0, u8::MAX, 1024, 15, rc_u8_0_MAX_1024_15) 614 | (u16: 0, u16::MAX, 1024, 15, rc_u16_0_MAX_1024_15) 615 | (u32: 0, u32::MAX, 1024, 15, rc_u32_0_MAX_1024_15) 616 | (u64: 0, u64::MAX, 1024, 15, rc_u64_0_MAX_1024_15) 617 | (usize: 0, usize::MAX, 1024, 15, rc_usize_0_MAX_1024_15) 618 | (i8: i8::MIN, i8::MAX, 1024, 15, rc_i8_MIN_MAX_1024_15) 619 | (i16: i16::MIN, i16::MAX, 1024, 15, rc_i16_MIN_MAX_1024_15) 620 | (i32: i32::MIN, i32::MAX, 1024, 15, rc_i32_MIN_MAX_1024_15) 621 | (i64: i64::MIN, i64::MAX, 1024, 15, rc_i64_MIN_MAX_1024_15) 622 | (isize: isize::MIN, isize::MAX, 1024, 15, rc_isize_MIN_MAX_1024_15) 623 | } 624 | 625 | macro_rules! range_into { 626 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $width: expr, $name: ident))*) => ($( 627 | #[test] 628 | fn $name() { 629 | let mut bin = Uniform::new(); 630 | let input: Vec<$t> = rand_uniform($min, $max, $length); 631 | println!("{:?}", input); 632 | bin.encode(&input).unwrap(); 633 | for a in bin.storage() { println!("{:032b}", a); } 634 | let mut output = vec![0; $width + 1]; 635 | for a in 0..($length - $width + 1) { 636 | let width = bin.access_into(a..($width + a), &mut *output); 637 | println!("{:?} {:?}", &input[a..($width + a)], &output[..$width]); 638 | assert_eq!($width, width); 639 | assert_eq!(&input[a..($width + a)], &output[..$width]); 640 | } 641 | } 642 | )*) 643 | } 644 | 645 | range_into!{ 646 | (u8: 0, 128, 513, 15, ri_u8_0_128_513_15) 647 | (u16: 0, 128, 513, 15, ri_u16_0_128_513_15) 648 | (u32: 0, 128, 513, 15, ri_u32_0_128_513_15) 649 | (u64: 0, 128, 513, 15, ri_u64_0_128_513_15) 650 | (i8: -64, 64, 513, 15, ri_i8_64_64_513_15) 651 | (i16: -64, 64, 513, 15, ri_i16_64_64_513_15) 652 | (i32: -64, 64, 513, 15, ri_i32_64_64_513_15) 653 | (i64: -64, 64, 513, 15, ri_i64_64_64_513_15) 654 | } 655 | 656 | macro_rules! range_from_into { 657 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 658 | #[test] 659 | fn $name() { 660 | let mut bin = Uniform::new(); 661 | let input: Vec<$t> = rand_uniform($min, $max, $length); 662 | println!("{:?}", input); 663 | bin.encode(&input).unwrap(); 664 | for a in bin.storage() { println!("{:032b}", a); } 665 | let mut output = vec![0; $length + 1]; 666 | for a in 0..$length { 667 | let width = bin.access_into(a.., &mut *output); 668 | println!("{:?} {:?}", &input[a..], &output[..width]); 669 | assert_eq!(input[a..], output[..width]); 670 | } 671 | } 672 | )*) 673 | } 674 | 675 | range_from_into!{ 676 | (u8: 0, u8::MAX, 1024, rfi_u8_0_MAX_1024) 677 | (u16: 0, u16::MAX, 1024, rfi_u16_0_MAX_1024) 678 | (u32: 0, u32::MAX, 1024, rfi_u32_0_MAX_1024) 679 | (u64: 0, u64::MAX, 1024, rfi_u64_0_MAX_1024) 680 | (usize: 0, usize::MAX, 1024, rfi_usize_0_MAX_1024) 681 | (i8: i8::MIN, i8::MAX, 1024, rfi_i8_MIN_MAX_1024) 682 | (i16: i16::MIN, i16::MAX, 1024, rfi_i16_MIN_MAX_1024) 683 | (i32: i32::MIN, i32::MAX, 1024, rfi_i32_MIN_MAX_1024) 684 | (i64: i64::MIN, i64::MAX, 1024, rfi_i64_MIN_MAX_1024) 685 | (isize: isize::MIN, isize::MAX, 1024, rfi_isize_MIN_MAX_1024) 686 | } 687 | -------------------------------------------------------------------------------- /tests/unimodal.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jeremy Mason 2 | // 3 | // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | // copied, modified, or distributed except according to those terms. 7 | 8 | #![feature(inclusive_range_syntax)] 9 | #![allow(non_snake_case)] 10 | 11 | extern crate mayda; 12 | extern crate num; 13 | extern crate rand; 14 | 15 | use mayda::{Access, AccessInto, Encode, Unimodal}; 16 | use num::{Bounded, FromPrimitive, ToPrimitive}; 17 | use rand::distributions::{IndependentSample, Normal, Range}; 18 | 19 | fn rand_outliers(mean: T, std_dev: T, length: usize) -> Vec 20 | where 21 | T: PartialOrd + Bounded + FromPrimitive + ToPrimitive + rand::distributions::range::SampleRange, 22 | { 23 | let mut output: Vec = Vec::with_capacity(length); 24 | if length > 0 { 25 | let val = Normal::new(mean.to_f64().unwrap(), std_dev.to_f64().unwrap()); 26 | let mut rng = rand::thread_rng(); 27 | for _ in 0..length { 28 | output.push(FromPrimitive::from_f64(val.ind_sample(&mut rng)).unwrap()); 29 | } 30 | let idx = Range::new(0, length); 31 | let val = Range::new(Bounded::min_value(), Bounded::max_value()); 32 | for _ in 0..(length / 16) { 33 | output[idx.ind_sample(&mut rng)] = val.ind_sample(&mut rng); 34 | } 35 | } 36 | output 37 | } 38 | 39 | macro_rules! random_values { 40 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($( 41 | #[test] 42 | fn $name() { 43 | let mut bin = Unimodal::new(); 44 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 45 | println!("{:?}", input); 46 | bin.encode(&input).unwrap(); 47 | for a in bin.storage() { println!("{:032b}", a); } 48 | let output = bin.decode(); 49 | println!("{:?}", output); 50 | assert_eq!(input, output); 51 | } 52 | )*) 53 | } 54 | 55 | random_values!{ 56 | (u8: 128, 16, 0, rv_u8_128_16_0) 57 | (u8: 128, 16, 1, rv_u8_128_16_1) 58 | (u8: 128, 16, 2, rv_u8_128_16_2) 59 | (u8: 128, 16, 3, rv_u8_128_16_3) 60 | (u8: 128, 16, 4, rv_u8_128_16_4) 61 | (u8: 128, 16, 5, rv_u8_128_16_5) 62 | (u8: 128, 16, 7, rv_u8_128_16_7) 63 | (u8: 128, 16, 8, rv_u8_128_16_8) 64 | (u8: 128, 16, 9, rv_u8_128_16_9) 65 | (u8: 128, 16, 15, rv_u8_128_16_15) 66 | (u8: 128, 16, 16, rv_u8_128_16_16) 67 | (u8: 128, 16, 17, rv_u8_128_16_17) 68 | (u8: 128, 16, 31, rv_u8_128_16_31) 69 | (u8: 128, 16, 32, rv_u8_128_16_32) 70 | (u8: 128, 16, 33, rv_u8_128_16_33) 71 | (u8: 128, 16, 127, rv_u8_128_16_127) 72 | (u8: 128, 16, 128, rv_u8_128_16_128) 73 | (u8: 128, 16, 129, rv_u8_128_16_129) 74 | (u8: 128, 16, 511, rv_u8_128_16_511) 75 | (u8: 128, 16, 512, rv_u8_128_16_512) 76 | (u8: 128, 16, 513, rv_u8_128_16_513) 77 | (u8: 128, 16, 1024, rv_u8_128_16_1024) 78 | (i8: 0, 16, 0, rv_i8_0_16_0) 79 | (i8: 0, 16, 1, rv_i8_0_16_1) 80 | (i8: 0, 16, 2, rv_i8_0_16_2) 81 | (i8: 0, 16, 3, rv_i8_0_16_3) 82 | (i8: 0, 16, 4, rv_i8_0_16_4) 83 | (i8: 0, 16, 5, rv_i8_0_16_5) 84 | (i8: 0, 16, 7, rv_i8_0_16_7) 85 | (i8: 0, 16, 8, rv_i8_0_16_8) 86 | (i8: 0, 16, 9, rv_i8_0_16_9) 87 | (i8: 0, 16, 15, rv_i8_0_16_15) 88 | (i8: 0, 16, 16, rv_i8_0_16_16) 89 | (i8: 0, 16, 17, rv_i8_0_16_17) 90 | (i8: 0, 16, 31, rv_i8_0_16_31) 91 | (i8: 0, 16, 32, rv_i8_0_16_32) 92 | (i8: 0, 16, 33, rv_i8_0_16_33) 93 | (i8: 0, 16, 127, rv_i8_0_16_127) 94 | (i8: 0, 16, 128, rv_i8_0_16_128) 95 | (i8: 0, 16, 129, rv_i8_0_16_129) 96 | (i8: 0, 16, 511, rv_i8_0_16_511) 97 | (i8: 0, 16, 512, rv_i8_0_16_512) 98 | (i8: 0, 16, 513, rv_i8_0_16_513) 99 | (i8: 0, 16, 1024, rv_i8_0_16_1024) 100 | } 101 | 102 | random_values!{ 103 | (u16: 1024, 32, 0, rv_u16_1024_32_0) 104 | (u16: 1024, 32, 1, rv_u16_1024_32_1) 105 | (u16: 1024, 32, 2, rv_u16_1024_32_2) 106 | (u16: 1024, 32, 3, rv_u16_1024_32_3) 107 | (u16: 1024, 32, 4, rv_u16_1024_32_4) 108 | (u16: 1024, 32, 5, rv_u16_1024_32_5) 109 | (u16: 1024, 32, 7, rv_u16_1024_32_7) 110 | (u16: 1024, 32, 8, rv_u16_1024_32_8) 111 | (u16: 1024, 32, 9, rv_u16_1024_32_9) 112 | (u16: 1024, 32, 15, rv_u16_1024_32_15) 113 | (u16: 1024, 32, 16, rv_u16_1024_32_16) 114 | (u16: 1024, 32, 17, rv_u16_1024_32_17) 115 | (u16: 1024, 32, 31, rv_u16_1024_32_31) 116 | (u16: 1024, 32, 32, rv_u16_1024_32_32) 117 | (u16: 1024, 32, 33, rv_u16_1024_32_33) 118 | (u16: 1024, 32, 127, rv_u16_1024_32_127) 119 | (u16: 1024, 32, 128, rv_u16_1024_32_128) 120 | (u16: 1024, 32, 129, rv_u16_1024_32_129) 121 | (u16: 1024, 32, 511, rv_u16_1024_32_511) 122 | (u16: 1024, 32, 512, rv_u16_1024_32_512) 123 | (u16: 1024, 32, 513, rv_u16_1024_32_513) 124 | (u16: 1024, 32, 1024, rv_u16_1024_32_1024) 125 | (i16: 0, 32, 0, rv_i16_0_32_0) 126 | (i16: 0, 32, 1, rv_i16_0_32_1) 127 | (i16: 0, 32, 2, rv_i16_0_32_2) 128 | (i16: 0, 32, 3, rv_i16_0_32_3) 129 | (i16: 0, 32, 4, rv_i16_0_32_4) 130 | (i16: 0, 32, 5, rv_i16_0_32_5) 131 | (i16: 0, 32, 7, rv_i16_0_32_7) 132 | (i16: 0, 32, 8, rv_i16_0_32_8) 133 | (i16: 0, 32, 9, rv_i16_0_32_9) 134 | (i16: 0, 32, 15, rv_i16_0_32_15) 135 | (i16: 0, 32, 16, rv_i16_0_32_16) 136 | (i16: 0, 32, 17, rv_i16_0_32_17) 137 | (i16: 0, 32, 31, rv_i16_0_32_31) 138 | (i16: 0, 32, 32, rv_i16_0_32_32) 139 | (i16: 0, 32, 33, rv_i16_0_32_33) 140 | (i16: 0, 32, 127, rv_i16_0_32_127) 141 | (i16: 0, 32, 128, rv_i16_0_32_128) 142 | (i16: 0, 32, 129, rv_i16_0_32_129) 143 | (i16: 0, 32, 511, rv_i16_0_32_511) 144 | (i16: 0, 32, 512, rv_i16_0_32_512) 145 | (i16: 0, 32, 513, rv_i16_0_32_513) 146 | (i16: 0, 32, 1024, rv_i16_0_32_1024) 147 | } 148 | 149 | random_values!{ 150 | (u32: 1024, 32, 0, rv_u32_1024_32_0) 151 | (u32: 1024, 32, 1, rv_u32_1024_32_1) 152 | (u32: 1024, 32, 2, rv_u32_1024_32_2) 153 | (u32: 1024, 32, 3, rv_u32_1024_32_3) 154 | (u32: 1024, 32, 4, rv_u32_1024_32_4) 155 | (u32: 1024, 32, 5, rv_u32_1024_32_5) 156 | (u32: 1024, 32, 7, rv_u32_1024_32_7) 157 | (u32: 1024, 32, 8, rv_u32_1024_32_8) 158 | (u32: 1024, 32, 9, rv_u32_1024_32_9) 159 | (u32: 1024, 32, 15, rv_u32_1024_32_15) 160 | (u32: 1024, 32, 16, rv_u32_1024_32_16) 161 | (u32: 1024, 32, 17, rv_u32_1024_32_17) 162 | (u32: 1024, 32, 31, rv_u32_1024_32_31) 163 | (u32: 1024, 32, 32, rv_u32_1024_32_32) 164 | (u32: 1024, 32, 33, rv_u32_1024_32_33) 165 | (u32: 1024, 32, 127, rv_u32_1024_32_127) 166 | (u32: 1024, 32, 128, rv_u32_1024_32_128) 167 | (u32: 1024, 32, 129, rv_u32_1024_32_129) 168 | (u32: 1024, 32, 511, rv_u32_1024_32_511) 169 | (u32: 1024, 32, 512, rv_u32_1024_32_512) 170 | (u32: 1024, 32, 513, rv_u32_1024_32_513) 171 | (u32: 1024, 32, 1024, rv_u32_1024_32_1024) 172 | (i32: 0, 32, 0, rv_i32_0_32_0) 173 | (i32: 0, 32, 1, rv_i32_0_32_1) 174 | (i32: 0, 32, 2, rv_i32_0_32_2) 175 | (i32: 0, 32, 3, rv_i32_0_32_3) 176 | (i32: 0, 32, 4, rv_i32_0_32_4) 177 | (i32: 0, 32, 5, rv_i32_0_32_5) 178 | (i32: 0, 32, 7, rv_i32_0_32_7) 179 | (i32: 0, 32, 8, rv_i32_0_32_8) 180 | (i32: 0, 32, 9, rv_i32_0_32_9) 181 | (i32: 0, 32, 15, rv_i32_0_32_15) 182 | (i32: 0, 32, 16, rv_i32_0_32_16) 183 | (i32: 0, 32, 17, rv_i32_0_32_17) 184 | (i32: 0, 32, 31, rv_i32_0_32_31) 185 | (i32: 0, 32, 32, rv_i32_0_32_32) 186 | (i32: 0, 32, 33, rv_i32_0_32_33) 187 | (i32: 0, 32, 127, rv_i32_0_32_127) 188 | (i32: 0, 32, 128, rv_i32_0_32_128) 189 | (i32: 0, 32, 129, rv_i32_0_32_129) 190 | (i32: 0, 32, 511, rv_i32_0_32_511) 191 | (i32: 0, 32, 512, rv_i32_0_32_512) 192 | (i32: 0, 32, 513, rv_i32_0_32_513) 193 | (i32: 0, 32, 1024, rv_i32_0_32_1024) 194 | } 195 | 196 | random_values!{ 197 | (u64: 1024, 32, 0, rv_u64_1024_32_0) 198 | (u64: 1024, 32, 1, rv_u64_1024_32_1) 199 | (u64: 1024, 32, 2, rv_u64_1024_32_2) 200 | (u64: 1024, 32, 3, rv_u64_1024_32_3) 201 | (u64: 1024, 32, 4, rv_u64_1024_32_4) 202 | (u64: 1024, 32, 5, rv_u64_1024_32_5) 203 | (u64: 1024, 32, 7, rv_u64_1024_32_7) 204 | (u64: 1024, 32, 8, rv_u64_1024_32_8) 205 | (u64: 1024, 32, 9, rv_u64_1024_32_9) 206 | (u64: 1024, 32, 15, rv_u64_1024_32_15) 207 | (u64: 1024, 32, 16, rv_u64_1024_32_16) 208 | (u64: 1024, 32, 17, rv_u64_1024_32_17) 209 | (u64: 1024, 32, 31, rv_u64_1024_32_31) 210 | (u64: 1024, 32, 32, rv_u64_1024_32_32) 211 | (u64: 1024, 32, 33, rv_u64_1024_32_33) 212 | (u64: 1024, 32, 127, rv_u64_1024_32_127) 213 | (u64: 1024, 32, 128, rv_u64_1024_32_128) 214 | (u64: 1024, 32, 129, rv_u64_1024_32_129) 215 | (u64: 1024, 32, 511, rv_u64_1024_32_511) 216 | (u64: 1024, 32, 512, rv_u64_1024_32_512) 217 | (u64: 1024, 32, 513, rv_u64_1024_32_513) 218 | (u64: 1024, 32, 1024, rv_u64_1024_32_1024) 219 | (i64: 0, 32, 0, rv_i64_0_32_0) 220 | (i64: 0, 32, 1, rv_i64_0_32_1) 221 | (i64: 0, 32, 2, rv_i64_0_32_2) 222 | (i64: 0, 32, 3, rv_i64_0_32_3) 223 | (i64: 0, 32, 4, rv_i64_0_32_4) 224 | (i64: 0, 32, 5, rv_i64_0_32_5) 225 | (i64: 0, 32, 7, rv_i64_0_32_7) 226 | (i64: 0, 32, 8, rv_i64_0_32_8) 227 | (i64: 0, 32, 9, rv_i64_0_32_9) 228 | (i64: 0, 32, 15, rv_i64_0_32_15) 229 | (i64: 0, 32, 16, rv_i64_0_32_16) 230 | (i64: 0, 32, 17, rv_i64_0_32_17) 231 | (i64: 0, 32, 31, rv_i64_0_32_31) 232 | (i64: 0, 32, 32, rv_i64_0_32_32) 233 | (i64: 0, 32, 33, rv_i64_0_32_33) 234 | (i64: 0, 32, 127, rv_i64_0_32_127) 235 | (i64: 0, 32, 128, rv_i64_0_32_128) 236 | (i64: 0, 32, 129, rv_i64_0_32_129) 237 | (i64: 0, 32, 511, rv_i64_0_32_511) 238 | (i64: 0, 32, 512, rv_i64_0_32_512) 239 | (i64: 0, 32, 513, rv_i64_0_32_513) 240 | (i64: 0, 32, 1024, rv_i64_0_32_1024) 241 | } 242 | 243 | // Verify that methods provided by u64 or u32 244 | random_values!{ 245 | (usize: 16384, 1024, 1024, cv_usize_16384_1024_1024) 246 | (isize: 0, 1024, 1024, cv_isize_0_1024_1024) 247 | } 248 | 249 | macro_rules! decode_into { 250 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 251 | #[test] 252 | fn $name() { 253 | let mut bin = Unimodal::new(); 254 | let input: Vec<$t> = rand_outliers($min, $max, $length); 255 | println!("{:?}", input); 256 | bin.encode(&input).unwrap(); 257 | for a in bin.storage() { println!("{:032b}", a); } 258 | let mut output = vec![0; $length + 1]; 259 | let length: usize = bin.decode_into(&mut *output); 260 | println!("{:?}", output); 261 | assert_eq!($length, length); 262 | assert_eq!(*input, output[..$length]); 263 | } 264 | )*) 265 | } 266 | 267 | decode_into!{ 268 | (u8: 0, 128, 513, di_u8_0_128_513) 269 | (i8: -64, 64, 513, di_i8_64_64_513) 270 | (u16: 0, 128, 513, di_u16_0_128_513) 271 | (i16: -64, 64, 513, di_i16_64_64_513) 272 | (u32: 0, 128, 513, di_u32_0_128_513) 273 | (i32: -64, 64, 513, di_i32_64_64_513) 274 | (u64: 0, 128, 513, di_u64_0_128_513) 275 | (i64: -64, 64, 513, di_i64_64_64_513) 276 | } 277 | 278 | macro_rules! decode_into_panic { 279 | ($(($t: ty: $min: expr, $max: expr, $length: expr, $name: ident))*) => ($( 280 | #[test] 281 | #[should_panic] 282 | fn $name() { 283 | let mut bin = Unimodal::new(); 284 | let input: Vec<$t> = rand_outliers($min, $max, $length); 285 | println!("{:?}", input); 286 | bin.encode(&input).unwrap(); 287 | for a in bin.storage() { println!("{:032b}", a); } 288 | let mut output = vec![0; $length - 1]; 289 | bin.decode_into(&mut *output); 290 | } 291 | )*) 292 | } 293 | 294 | decode_into_panic!{ 295 | (u8: 0, 128, 513, di_pan_u8_0_128_513) 296 | (i8: -64, 64, 513, di_pan_i8_64_64_513) 297 | (u16: 0, 128, 513, di_pan_u16_0_128_513) 298 | (i16: -64, 64, 513, di_pan_i16_64_64_513) 299 | (u32: 0, 128, 513, di_pan_u32_0_128_513) 300 | (i32: -64, 64, 513, di_pan_i32_64_64_513) 301 | (u64: 0, 128, 513, di_pan_u64_0_128_513) 302 | (i64: -64, 64, 513, di_pan_i64_64_64_513) 303 | } 304 | 305 | macro_rules! increasing_values { 306 | ($(($t: ty: $min: expr, $max: expr, $name: ident))*) => ($( 307 | #[test] 308 | fn $name() { 309 | let mut bin = Unimodal::new(); 310 | let input: Vec<$t> = ($min..=$max).collect(); 311 | println!("{:?}", input); 312 | bin.encode(&input).unwrap(); 313 | for a in bin.storage() { println!("{:032b}", a); } 314 | let output = bin.decode(); 315 | println!("{:?}", output); 316 | assert_eq!(input, output); 317 | } 318 | )*) 319 | } 320 | 321 | increasing_values!{ 322 | (u8: 0, 255, iv_u8_0_255) 323 | (u16: 0, 255, iv_u16_0_255) 324 | (u32: 0, 255, iv_u32_0_255) 325 | (u64: 0, 255, iv_u64_0_255) 326 | (usize: 0, 255, iv_usize_0_255) 327 | (i8: -128, 127, iv_i8_128_127) 328 | (i16: -128, 127, iv_i16_128_127) 329 | (i32: -128, 127, iv_i32_128_127) 330 | (i64: -128, 127, iv_i64_128_127) 331 | (isize: -128, 127, iv_isize_128_127) 332 | } 333 | 334 | macro_rules! indexing { 335 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($( 336 | #[test] 337 | fn $name() { 338 | let mut bin = Unimodal::new(); 339 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 340 | println!("{:?}", input); 341 | bin.encode(&input).unwrap(); 342 | for a in bin.storage() { println!("{:032b}", a); } 343 | for a in 0..$length { 344 | let b = bin.access(a); 345 | println!("{} {}", input[a], b); 346 | assert_eq!(input[a], b); 347 | } 348 | } 349 | )*) 350 | } 351 | 352 | indexing!{ 353 | (u8: 128, 16, 1024, idx_u8_128_16_1024) 354 | (u16: 1024, 32, 1024, idx_u16_1024_32_1024) 355 | (u32: 1024, 32, 1024, idx_u32_1024_32_1024) 356 | (u64: 1024, 32, 1024, idx_u64_1024_32_1024) 357 | (usize: 1024, 32, 1024, idx_usize_1024_32_1024) 358 | (i8: 0, 16, 1024, idx_i8_0_16_1024) 359 | (i16: 0, 32, 1024, idx_i16_0_32_1024) 360 | (i32: 0, 32, 1024, idx_i32_0_32_1024) 361 | (i64: 0, 32, 1024, idx_i64_0_32_1024) 362 | (isize: 0, 32, 1024, idx_isize_0_32_1024) 363 | } 364 | 365 | macro_rules! indexing_panic { 366 | ($(($t: ty: $length: expr, $idx: expr, $name: ident))*) => ($( 367 | #[test] 368 | #[should_panic] 369 | fn $name() { 370 | let mut bin = Unimodal::new(); 371 | let input: Vec<$t> = vec![0; $length]; 372 | println!("{:?}", input); 373 | bin.encode(&input).unwrap(); 374 | for a in bin.storage() { println!("{:032b}", a); } 375 | bin.access($idx); 376 | } 377 | )*) 378 | } 379 | 380 | indexing_panic!{ 381 | (u8: 0, 1, idx_pan_u8_0_1) 382 | (u8: 1, 2, idx_pan_u8_1_2) 383 | (u8: 1, 128, idx_pan_u8_1_128) 384 | (u16: 0, 1, idx_pan_u16_0_1) 385 | (u16: 1, 2, idx_pan_u16_1_2) 386 | (u16: 1, 128, idx_pan_u16_1_128) 387 | (u32: 0, 1, idx_pan_u32_0_1) 388 | (u32: 1, 2, idx_pan_u32_1_2) 389 | (u32: 1, 128, idx_pan_u32_1_128) 390 | (u64: 0, 1, idx_pan_u64_0_1) 391 | (u64: 1, 2, idx_pan_u64_1_2) 392 | (u64: 1, 128, idx_pan_u64_1_128) 393 | (i8: 0, 1, idx_pan_i8_0_1) 394 | (i8: 1, 2, idx_pan_i8_1_2) 395 | (i8: 1, 128, idx_pan_i8_1_128) 396 | (i16: 0, 1, idx_pan_i16_0_1) 397 | (i16: 1, 2, idx_pan_i16_1_2) 398 | (i16: 1, 128, idx_pan_i16_1_128) 399 | (i32: 0, 1, idx_pan_i32_0_1) 400 | (i32: 1, 2, idx_pan_i32_1_2) 401 | (i32: 1, 128, idx_pan_i32_1_128) 402 | (i64: 0, 1, idx_pan_i64_0_1) 403 | (i64: 1, 2, idx_pan_i64_1_2) 404 | (i64: 1, 128, idx_pan_i64_1_128) 405 | } 406 | 407 | macro_rules! range { 408 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $width: expr, $name: ident))*) => ($( 409 | #[test] 410 | fn $name() { 411 | let mut bin = Unimodal::new(); 412 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 413 | println!("{:?}", input); 414 | bin.encode(&input).unwrap(); 415 | for a in bin.storage() { println!("{:032b}", a); } 416 | for a in 0..($length - $width + 1) { 417 | let vec = bin.access(a..($width + a)); 418 | println!("{:?} {:?}", &input[a..($width + a)], &vec[..]); 419 | assert_eq!(&input[a..($width + a)], &vec[..]); 420 | } 421 | } 422 | )*) 423 | } 424 | 425 | range!{ 426 | (u8: 128, 16, 1024, 15, r_u8_128_16_1024_15) 427 | (u16: 1024, 32, 1024, 15, r_u16_1024_32_1024_15) 428 | (u32: 1024, 32, 1024, 15, r_u32_1024_32_1024_15) 429 | (u64: 1024, 32, 1024, 15, r_u64_1024_32_1024_15) 430 | (usize: 1024, 32, 1024, 15, r_usize_1024_32_1024_15) 431 | (i8: 0, 16, 1024, 15, r_i8_0_16_1024_15) 432 | (i16: 0, 32, 1024, 15, r_i16_0_32_1024_15) 433 | (i32: 0, 32, 1024, 15, r_i32_0_32_1024_15) 434 | (i64: 0, 32, 1024, 15, r_i64_0_32_1024_15) 435 | (isize: 0, 32, 1024, 15, r_isize_0_32_1024_15) 436 | } 437 | 438 | macro_rules! range_panic { 439 | ($(($t: ty: $length: expr, $range: expr, $name: ident))*) => ($( 440 | #[test] 441 | #[should_panic] 442 | fn $name() { 443 | let mut bin = Unimodal::new(); 444 | let input: Vec<$t> = vec![0; $length]; 445 | println!("{:?}", input); 446 | bin.encode(&input).unwrap(); 447 | for a in bin.storage() { println!("{:032b}", a); } 448 | bin.access($range); 449 | } 450 | )*) 451 | } 452 | 453 | range_panic!{ 454 | (u8: 0, 0..1, r_pan_u8_0_0_1) 455 | (u8: 0, 1..1, r_pan_u8_0_1_1) 456 | (u8: 1, 0..2, r_pan_u8_1_0_2) 457 | (u8: 1, 2..2, r_pan_u8_1_2_2) 458 | (u8: 2, 1..0, r_pan_u8_2_1_0) 459 | (u8: 2, 127..128, r_pan_u8_2_127_128) 460 | (u8: 2, 128..129, r_pan_u8_2_128_129) 461 | (u16: 0, 0..1, r_pan_u16_0_0_1) 462 | (u16: 0, 1..1, r_pan_u16_0_1_1) 463 | (u16: 1, 0..2, r_pan_u16_1_0_2) 464 | (u16: 1, 2..2, r_pan_u16_1_2_2) 465 | (u16: 2, 1..0, r_pan_u16_2_1_0) 466 | (u16: 2, 127..128, r_pan_u16_2_127_128) 467 | (u16: 2, 128..129, r_pan_u16_2_128_129) 468 | (u32: 0, 0..1, r_pan_u32_0_0_1) 469 | (u32: 0, 1..1, r_pan_u32_0_1_1) 470 | (u32: 1, 0..2, r_pan_u32_1_0_2) 471 | (u32: 1, 2..2, r_pan_u32_1_2_2) 472 | (u32: 2, 1..0, r_pan_u32_2_1_0) 473 | (u32: 2, 127..128, r_pan_u32_2_127_128) 474 | (u32: 2, 128..129, r_pan_u32_2_128_129) 475 | (u64: 0, 0..1, r_pan_u64_0_0_1) 476 | (u64: 0, 1..1, r_pan_u64_0_1_1) 477 | (u64: 1, 0..2, r_pan_u64_1_0_2) 478 | (u64: 1, 2..2, r_pan_u64_1_2_2) 479 | (u64: 2, 1..0, r_pan_u64_2_1_0) 480 | (u64: 2, 127..128, r_pan_u64_2_127_128) 481 | (u64: 2, 128..129, r_pan_u64_2_128_129) 482 | (i8: 0, 0..1, r_pan_i8_0_0_1) 483 | (i8: 0, 1..1, r_pan_i8_0_1_1) 484 | (i8: 1, 0..2, r_pan_i8_1_0_2) 485 | (i8: 1, 2..2, r_pan_i8_1_2_2) 486 | (i8: 2, 1..0, r_pan_i8_2_1_0) 487 | (i8: 2, 127..128, r_pan_i8_2_127_128) 488 | (i8: 2, 128..129, r_pan_i8_2_128_129) 489 | (i16: 0, 0..1, r_pan_i16_0_0_1) 490 | (i16: 0, 1..1, r_pan_i16_0_1_1) 491 | (i16: 1, 0..2, r_pan_i16_1_0_2) 492 | (i16: 1, 2..2, r_pan_i16_1_2_2) 493 | (i16: 2, 1..0, r_pan_i16_2_1_0) 494 | (i16: 2, 127..128, r_pan_i16_2_127_128) 495 | (i16: 2, 128..129, r_pan_i16_2_128_129) 496 | (i32: 0, 0..1, r_pan_i32_0_0_1) 497 | (i32: 0, 1..1, r_pan_i32_0_1_1) 498 | (i32: 1, 0..2, r_pan_i32_1_0_2) 499 | (i32: 1, 2..2, r_pan_i32_1_2_2) 500 | (i32: 2, 1..0, r_pan_i32_2_1_0) 501 | (i32: 2, 127..128, r_pan_i32_2_127_128) 502 | (i32: 2, 128..129, r_pan_i32_2_128_129) 503 | (i64: 0, 0..1, r_pan_i64_0_0_1) 504 | (i64: 0, 1..1, r_pan_i64_0_1_1) 505 | (i64: 1, 0..2, r_pan_i64_1_0_2) 506 | (i64: 1, 2..2, r_pan_i64_1_2_2) 507 | (i64: 2, 1..0, r_pan_i64_2_1_0) 508 | (i64: 2, 127..128, r_pan_i64_2_127_128) 509 | (i64: 2, 128..129, r_pan_i64_2_128_129) 510 | } 511 | 512 | macro_rules! range_from { 513 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($( 514 | #[test] 515 | fn $name() { 516 | let mut bin = Unimodal::new(); 517 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 518 | println!("{:?}", input); 519 | bin.encode(&input).unwrap(); 520 | for a in bin.storage() { println!("{:032b}", a); } 521 | for a in 0..$length { 522 | let vec = bin.access(a..); 523 | println!("{:?} {:?}", &input[a..], &vec[..]); 524 | assert_eq!(input[a..], vec[..]); 525 | } 526 | } 527 | )*) 528 | } 529 | 530 | range_from!{ 531 | (u8: 128, 16, 1024, rf_u8_128_16_1024) 532 | (u16: 1024, 32, 1024, rf_u16_1024_32_1024) 533 | (u32: 1024, 32, 1024, rf_u32_1024_32_1024) 534 | (u64: 1024, 32, 1024, rf_u64_1024_32_1024) 535 | (usize: 1024, 32, 1024, rf_usize_1024_32_1024) 536 | (i8: 0, 16, 1024, rf_i8_0_16_1024) 537 | (i16: 0, 32, 1024, rf_i16_0_32_1024) 538 | (i32: 0, 32, 1024, rf_i32_0_32_1024) 539 | (i64: 0, 32, 1024, rf_i64_0_32_1024) 540 | (isize: 0, 32, 1024, rf_isize_0_32_1024) 541 | } 542 | 543 | macro_rules! range_to { 544 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($( 545 | #[test] 546 | fn $name() { 547 | let mut bin = Unimodal::new(); 548 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 549 | println!("{:?}", input); 550 | bin.encode(&input).unwrap(); 551 | for a in bin.storage() { println!("{:032b}", a); } 552 | for a in 0..($length + 1) { 553 | let vec = bin.access(..a); 554 | println!("{:?} {:?}", &input[..a], &vec[..]); 555 | assert_eq!(input[..a], vec[..]); 556 | } 557 | } 558 | )*) 559 | } 560 | 561 | range_to!{ 562 | (u8: 128, 16, 1024, rt_u8_128_16_1024) 563 | (u16: 1024, 32, 1024, rt_u16_1024_32_1024) 564 | (u32: 1024, 32, 1024, rt_u32_1024_32_1024) 565 | (u64: 1024, 32, 1024, rt_u64_1024_32_1024) 566 | (usize: 1024, 32, 1024, rt_usize_1024_32_1024) 567 | (i8: 0, 16, 1024, rt_i8_0_16_1024) 568 | (i16: 0, 32, 1024, rt_i16_0_32_1024) 569 | (i32: 0, 32, 1024, rt_i32_0_32_1024) 570 | (i64: 0, 32, 1024, rt_i64_0_32_1024) 571 | (isize: 0, 32, 1024, rt_isize_0_32_1024) 572 | } 573 | 574 | macro_rules! range_full { 575 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($( 576 | #[test] 577 | fn $name() { 578 | let mut bin = Unimodal::new(); 579 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 580 | println!("{:?}", input); 581 | bin.encode(&input).unwrap(); 582 | for a in bin.storage() { println!("{:032b}", a); } 583 | let vec = bin.access(..); 584 | println!("{:?}", vec); 585 | assert_eq!(input[..], vec[..]); 586 | } 587 | )*) 588 | } 589 | 590 | range_full!{ 591 | (u8: 128, 16, 1024, ru_u8_128_16_1024) 592 | (u16: 1024, 32, 1024, ru_u16_1024_32_1024) 593 | (u32: 1024, 32, 1024, ru_u32_1024_32_1024) 594 | (u64: 1024, 32, 1024, ru_u64_1024_32_1024) 595 | (usize: 1024, 32, 1024, ru_usize_1024_32_1024) 596 | (i8: 0, 16, 1024, ru_i8_0_16_1024) 597 | (i16: 0, 32, 1024, ru_i16_0_32_1024) 598 | (i32: 0, 32, 1024, ru_i32_0_32_1024) 599 | (i64: 0, 32, 1024, ru_i64_0_32_1024) 600 | (isize: 0, 32, 1024, ru_isize_0_32_1024) 601 | } 602 | 603 | macro_rules! range_inclusive { 604 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $width: expr, $name: ident))*) => ($( 605 | #[test] 606 | fn $name() { 607 | let mut bin = Unimodal::new(); 608 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 609 | println!("{:?}", input); 610 | bin.encode(&input).unwrap(); 611 | for a in bin.storage() { println!("{:032b}", a); } 612 | for a in 0..($length - $width) { 613 | let vec = bin.access(a..=($width + a)); 614 | println!("{:?} {:?}", &input[a..=($width + a)], &vec[..]); 615 | assert_eq!(&input[a..=($width + a)], &vec[..]); 616 | } 617 | } 618 | )*) 619 | } 620 | 621 | range_inclusive!{ 622 | (u8: 128, 16, 1024, 15, ri_u8_128_16_1024_15) 623 | (u16: 1024, 32, 1024, 15, ri_u16_1024_32_1024_15) 624 | (u32: 1024, 32, 1024, 15, ri_u32_1024_32_1024_15) 625 | (u64: 1024, 32, 1024, 15, ri_u64_1024_32_1024_15) 626 | (usize: 1024, 32, 1024, 15, ri_usize_1024_32_1024_15) 627 | (i8: 0, 16, 1024, 15, ri_i8_0_16_1024_15) 628 | (i16: 0, 32, 1024, 15, ri_i16_0_32_1024_15) 629 | (i32: 0, 32, 1024, 15, ri_i32_0_32_1024_15) 630 | (i64: 0, 32, 1024, 15, ri_i64_0_32_1024_15) 631 | (isize: 0, 32, 1024, 15, ri_isize_0_32_1024_15) 632 | } 633 | 634 | macro_rules! range_into { 635 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $width: expr, $name: ident))*) => ($( 636 | #[test] 637 | fn $name() { 638 | let mut bin = Unimodal::new(); 639 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 640 | println!("{:?}", input); 641 | bin.encode(&input).unwrap(); 642 | for a in bin.storage() { println!("{:032b}", a); } 643 | let mut output = vec![0; $width + 1]; 644 | for a in 0..($length - $width + 1) { 645 | let width = bin.access_into(a..($width + a), &mut *output); 646 | println!("{:?} {:?}", &input[a..($width + a)], &output[..$width]); 647 | assert_eq!($width, width); 648 | assert_eq!(&input[a..($width + a)], &output[..$width]); 649 | } 650 | } 651 | )*) 652 | } 653 | 654 | range_into!{ 655 | (u8: 128, 16, 513, 15, ri_u8_128_16_513_15) 656 | (u16: 1024, 32, 513, 15, ri_u16_128_32_513_15) 657 | (u32: 1024, 32, 513, 15, ri_u32_128_32_513_15) 658 | (u64: 1024, 32, 513, 15, ri_u64_128_32_513_15) 659 | (i8: 0, 16, 513, 15, ri_i8_0_16_513_15) 660 | (i16: 0, 32, 513, 15, ri_i16_0_32_513_15) 661 | (i32: 0, 32, 513, 15, ri_i32_0_32_513_15) 662 | (i64: 0, 32, 513, 15, ri_i64_0_32_513_15) 663 | } 664 | 665 | macro_rules! range_from_into { 666 | ($(($t: ty: $mean: expr, $std_dev: expr, $length: expr, $name: ident))*) => ($( 667 | #[test] 668 | fn $name() { 669 | let mut bin = Unimodal::new(); 670 | let input: Vec<$t> = rand_outliers($mean, $std_dev, $length); 671 | println!("{:?}", input); 672 | bin.encode(&input).unwrap(); 673 | for a in bin.storage() { println!("{:032b}", a); } 674 | let mut output = vec![0; $length + 1]; 675 | for a in 0..$length { 676 | let width = bin.access_into(a.., &mut *output); 677 | println!("{:?} {:?}", &input[a..], &output[..width]); 678 | assert_eq!(input[a..], output[..width]); 679 | } 680 | } 681 | )*) 682 | } 683 | 684 | range_from_into!{ 685 | (u8: 128, 16, 1024, rfi_u8_128_16_1024) 686 | (u16: 1024, 32, 1024, rfi_u16_1024_32_1024) 687 | (u32: 1024, 32, 1024, rfi_u32_1024_32_1024) 688 | (u64: 1024, 32, 1024, rfi_u64_1024_32_1024) 689 | (usize: 1024, 32, 1024, rfi_usize_1024_32_1024) 690 | (i8: 0, 16, 1024, rfi_i8_0_16_1024) 691 | (i16: 0, 32, 1024, rfi_i16_0_32_1024) 692 | (i32: 0, 32, 1024, rfi_i32_0_32_1024) 693 | (i64: 0, 32, 1024, rfi_i64_0_32_1024) 694 | (isize: 0, 32, 1024, rfi_isize_0_32_1024) 695 | } 696 | --------------------------------------------------------------------------------