├── .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 |
--------------------------------------------------------------------------------