├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches └── comparison.rs ├── src ├── lib.rs └── tests.rs └── tests └── it └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bitsvec" 3 | version = "0.1.1" 4 | authors = ["Chojan Shang "] 5 | edition = "2021" 6 | license = "MIT / Apache-2.0" 7 | description = "A bit vector with the Rust standard library's portable SIMD API" 8 | repository = "https://github.com/psiace/bitsvec" 9 | documentation = "https://docs.rs/bitsvec" 10 | keywords = ["bitvec", "bitmap", "vec", "simd", "data-structures"] 11 | categories = ["data-structures"] 12 | readme = "README.md" 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [dependencies] 17 | smallvec = { version = "1.8", features = ["const_generics"] } 18 | 19 | [features] 20 | default = ["std"] 21 | std = [] 22 | 23 | [dev-dependencies] 24 | criterion = "0.3" 25 | # for normal bench 26 | bit-vec = "0.6" 27 | bitvec = "1.0.0" 28 | # for simd bench 29 | wide = "0.7.4" 30 | bitvec_simd = "0.15.0" 31 | bitvector_simd = "0.2.2" 32 | 33 | [[bench]] 34 | name = "comparison" 35 | harness = false 36 | -------------------------------------------------------------------------------- /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 | MIT License 2 | 3 | Copyright (c) 2022 Chojan Shang 4 | Copyright (c) 2021 GCCFeli - https://github.com/GCCFeli/bitvec_simd 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

bitsvec

3 | 4 |

5 | A bit vector with the Rust standard library's portable SIMD API 6 |

7 | 8 |

9 | crates.io page 10 | docs.rs docs 11 |

12 |
13 | 14 | ## Usage 15 | 16 | Add `bitsvec` to `Cargo.toml`: 17 | 18 | ```toml 19 | bitsvec = "x.y.z" 20 | ``` 21 | 22 | Write some code like this: 23 | 24 | ```rust 25 | let mut bitvec = BitVec::ones(1000); // create a bitvec contains 0 ..= 999 26 | bitvec.set(900, false); // delete 900 from bitvec 27 | bitvec.set(1200, true); // add 1200 to bitvec (and expand bitvec to length 1201) 28 | let bitvec2 = BitVec::ones(1000); 29 | 30 | let new_bitvec = bitvec.and_cloned(&bitvec2); // and operation, without consume 31 | let new_bitvec2 = bitvec & bitvec2; // and operation, consume both bitvec 32 | 33 | // Operation Supported: 34 | // and, or, xor, not, eq, eq_left 35 | 36 | assert_eq!(new_bitvec, new_bitvec2); 37 | ``` 38 | 39 | ## Performance 40 | 41 | Compared on AMD Ryzen 9 5900hs, aginst: 42 | 43 | * [bit_vec 0.6.3](https://docs.rs/bit-vec/0.6.3/bit_vec/index.html) 44 | * [bitvec 1.0.0](https://docs.rs/bitvec/1.0.0/bitvec/index.html) 45 | * [bitvec_simd 0.15.0](https://docs.rs/bitvec_simd/0.15.0/bitvec_simd/index.html) 46 | * [bitvector_simd 0.2.2](https://docs.rs/bitvector_simd/0.2.2/bitvector_simd/index.html) 47 | 48 |
49 | 50 | ``` 51 | $ cargo bench 52 | 53 | bitsvec(this crate) time: [330.34 ns 330.75 ns 331.18 ns] 54 | Found 6 outliers among 100 measurements (6.00%) 55 | 4 (4.00%) high mild 56 | 2 (2.00%) high severe 57 | 58 | bitsvec_u16x8(this crate) 59 | time: [332.23 ns 333.90 ns 335.98 ns] 60 | Found 16 outliers among 100 measurements (16.00%) 61 | 6 (6.00%) high mild 62 | 10 (10.00%) high severe 63 | 64 | bitvec_simd 0.15.0 time: [371.96 ns 372.23 ns 372.53 ns] 65 | Found 6 outliers among 100 measurements (6.00%) 66 | 4 (4.00%) high mild 67 | 2 (2.00%) high severe 68 | 69 | bitvec_simd 0.15.0 u16x8 70 | time: [578.38 ns 578.68 ns 579.01 ns] 71 | Found 7 outliers among 100 measurements (7.00%) 72 | 6 (6.00%) high mild 73 | 1 (1.00%) high severe 74 | 75 | bitvector_simd 0.2.2 time: [288.55 ns 289.11 ns 289.64 ns] 76 | Found 1 outliers among 100 measurements (1.00%) 77 | 1 (1.00%) high mild 78 | 79 | bit-vec 0.6 time: [1.5177 us 1.5200 us 1.5224 us] 80 | 81 | bitvec 1.0 time: [32.119 us 32.254 us 32.390 us] 82 | 83 | bitsvec(this crate) with creation 84 | time: [888.59 ns 889.45 ns 890.39 ns] 85 | Found 10 outliers among 100 measurements (10.00%) 86 | 9 (9.00%) high mild 87 | 1 (1.00%) high severe 88 | bitsvec_u16x8(this crate) with creation 89 | time: [1.1006 us 1.1031 us 1.1059 us] 90 | Found 11 outliers among 100 measurements (11.00%) 91 | 8 (8.00%) high mild 92 | 3 (3.00%) high severe 93 | 94 | bitvec_simd 0.15.0 with creation 95 | time: [970.09 ns 970.82 ns 971.67 ns] 96 | Found 12 outliers among 100 measurements (12.00%) 97 | 10 (10.00%) high mild 98 | 2 (2.00%) high severe 99 | bitvec_simd 0.15.0 u16x8 with creation 100 | time: [1.1158 us 1.1185 us 1.1215 us] 101 | Found 8 outliers among 100 measurements (8.00%) 102 | 6 (6.00%) low mild 103 | 2 (2.00%) high mild 104 | 105 | bitvector_simd 0.2.2 with creation 106 | time: [736.46 ns 737.95 ns 739.49 ns] 107 | Found 1 outliers among 100 measurements (1.00%) 108 | 1 (1.00%) high severe 109 | 110 | bit-vec 0.6 with creation 111 | time: [1.6515 us 1.6527 us 1.6539 us] 112 | Found 2 outliers among 100 measurements (2.00%) 113 | 2 (2.00%) high mild 114 | 115 | bitvec 1.0 with creation 116 | time: [28.484 us 28.501 us 28.518 us] 117 | Found 20 outliers among 100 measurements (20.00%) 118 | 15 (15.00%) low severe 119 | 3 (3.00%) high mild 120 | 2 (2.00%) high severe 121 | 122 | bitsvec(this crate) resize false 123 | time: [676.30 ns 677.13 ns 677.93 ns] 124 | bitsvec_u16x8(this crate) resize false 125 | time: [618.70 ns 619.73 ns 620.98 ns] 126 | Found 2 outliers among 100 measurements (2.00%) 127 | 1 (1.00%) high mild 128 | 1 (1.00%) high severe 129 | 130 | bitvec_simd 0.15.0 resize false 131 | time: [676.27 ns 677.96 ns 679.66 ns] 132 | Found 4 outliers among 100 measurements (4.00%) 133 | 3 (3.00%) high mild 134 | 1 (1.00%) high severe 135 | 136 | bitvec_simd 0.15.0 u16x8 resize false 137 | time: [472.84 ns 473.76 ns 474.71 ns] 138 | Found 2 outliers among 100 measurements (2.00%) 139 | 2 (2.00%) high mild 140 | 141 | bitvec 1.0 resize false time: [108.23 us 108.29 us 108.36 us] 142 | Found 9 outliers among 100 measurements (9.00%) 143 | 6 (6.00%) high mild 144 | 3 (3.00%) high severe 145 | 146 | bitsvec(this crate) resize true 147 | time: [679.71 ns 680.66 ns 681.75 ns] 148 | Found 9 outliers among 100 measurements (9.00%) 149 | 7 (7.00%) high mild 150 | 2 (2.00%) high severe 151 | 152 | bitsvec_u16x8(this crate) resize true 153 | time: [876.21 ns 876.89 ns 877.71 ns] 154 | Found 8 outliers among 100 measurements (8.00%) 155 | 6 (6.00%) high mild 156 | 2 (2.00%) high severe 157 | 158 | bitvec_simd 0.15.0 resize true 159 | time: [672.44 ns 672.82 ns 673.24 ns] 160 | Found 9 outliers among 100 measurements (9.00%) 161 | 6 (6.00%) high mild 162 | 3 (3.00%) high severe 163 | 164 | bitvec_simd 0.15.0 u16x8 resize true 165 | time: [748.77 ns 751.48 ns 754.59 ns] 166 | 167 | bitvec 1.0 resize true time: [100.50 us 100.63 us 100.75 us] 168 | ``` 169 | 170 |
171 | 172 | ## Credits 173 | 174 | Most code of this crate is from (https://github.com/GCCFeli/bitvec_simd). On top of that, some changes were made. 175 | 176 | ## License 177 | 178 | This library is licensed under either of: 179 | 180 | * MIT license [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT 181 | * Apache License 2.0 [LICENSE-APACHE](LICENSE-APACHE) or https://opensource.org/licenses/Apache-2.0 182 | 183 | at your option. 184 | -------------------------------------------------------------------------------- /benches/comparison.rs: -------------------------------------------------------------------------------- 1 | #![feature(portable_simd)] 2 | use core::simd::*; 3 | 4 | use criterion::*; 5 | 6 | fn benchmark_bitvector_simd(c: &mut Criterion) { 7 | let b1 = bitsvec::BitVec::ones(100_000); 8 | let b2 = bitsvec::BitVec::zeros(100_000); 9 | c.bench_function("bitsvec(this crate)", |b| { 10 | b.iter(|| { 11 | black_box(b1.and_cloned(&b2)); 12 | }) 13 | }); 14 | } 15 | 16 | fn benchmark_bitvector_simd2(c: &mut Criterion) { 17 | c.bench_function("bitsvec(this crate) with creation", |b| { 18 | b.iter(|| { 19 | let b1 = bitsvec::BitVec::ones(100_000); 20 | let b2 = bitsvec::BitVec::zeros(100_000); 21 | black_box(b1.and(b2)); 22 | }) 23 | }); 24 | } 25 | 26 | fn benchmark_bitvector_simd3(c: &mut Criterion) { 27 | c.bench_function("bitsvec(this crate) resize false", |b| { 28 | b.iter(|| { 29 | let mut b1 = bitsvec::BitVec::ones(100_000); 30 | black_box(b1.resize(200_000, false)); 31 | }) 32 | }); 33 | } 34 | 35 | fn benchmark_bitvector_simd4(c: &mut Criterion) { 36 | c.bench_function("bitsvec(this crate) resize true", |b| { 37 | b.iter(|| { 38 | let mut b1 = bitsvec::BitVec::ones(100_000); 39 | black_box(b1.resize(200_000, true)); 40 | }) 41 | }); 42 | } 43 | 44 | fn benchmark_bitvector_simd_u16x8(c: &mut Criterion) { 45 | let b1 = bitsvec::BitVecSimd::<[u16x8; 4], 8>::ones(100_000); 46 | let b2 = bitsvec::BitVecSimd::<[u16x8; 4], 8>::zeros(100_000); 47 | c.bench_function("bitsvec_u16x8(this crate)", |b| { 48 | b.iter(|| { 49 | black_box(b1.and_cloned(&b2)); 50 | }) 51 | }); 52 | } 53 | 54 | fn benchmark_bitvector_simd2_u16x8(c: &mut Criterion) { 55 | c.bench_function("bitsvec_u16x8(this crate) with creation", |b| { 56 | b.iter(|| { 57 | let b1 = bitsvec::BitVecSimd::<[u16x8; 4], 8>::ones(100_000); 58 | let b2 = bitsvec::BitVecSimd::<[u16x8; 4], 8>::zeros(100_000); 59 | black_box(b1.and(b2)); 60 | }) 61 | }); 62 | } 63 | 64 | fn benchmark_bitvector_simd3_u16x8(c: &mut Criterion) { 65 | c.bench_function("bitsvec_u16x8(this crate) resize false", |b| { 66 | b.iter(|| { 67 | let mut b1 = bitsvec::BitVecSimd::<[u16x8; 4], 8>::ones(100_000); 68 | black_box(b1.resize(200_000, false)); 69 | }) 70 | }); 71 | } 72 | 73 | fn benchmark_bitvector_simd4_u16x8(c: &mut Criterion) { 74 | c.bench_function("bitsvec_u16x8(this crate) resize true", |b| { 75 | b.iter(|| { 76 | let mut b1 = bitsvec::BitVecSimd::<[u16x8; 4], 8>::ones(100_000); 77 | black_box(b1.resize(200_000, true)); 78 | }) 79 | }); 80 | } 81 | 82 | fn benchmark_bitvector_bitvec_simd(c: &mut Criterion) { 83 | let b1 = bitvec_simd::BitVec::ones(100_000); 84 | let b2 = bitvec_simd::BitVec::zeros(100_000); 85 | c.bench_function("bitvec_simd 0.15.0", |b| { 86 | b.iter(|| { 87 | black_box(b1.and_cloned(&b2)); 88 | }) 89 | }); 90 | } 91 | 92 | fn benchmark_bitvector_bitvec_simd2(c: &mut Criterion) { 93 | c.bench_function("bitvec_simd 0.15.0 with creation", |b| { 94 | b.iter(|| { 95 | let b1 = bitvec_simd::BitVec::ones(100_000); 96 | let b2 = bitvec_simd::BitVec::zeros(100_000); 97 | black_box(b1.and(b2)); 98 | }) 99 | }); 100 | } 101 | 102 | fn benchmark_bitvector_bitvec_simd3(c: &mut Criterion) { 103 | c.bench_function("bitvec_simd 0.15.0 resize false", |b| { 104 | b.iter(|| { 105 | let mut b1 = bitvec_simd::BitVec::ones(100_000); 106 | black_box(b1.resize(200_000, false)); 107 | }) 108 | }); 109 | } 110 | 111 | fn benchmark_bitvector_bitvec_simd4(c: &mut Criterion) { 112 | c.bench_function("bitvec_simd 0.15.0 resize true", |b| { 113 | b.iter(|| { 114 | let mut b1 = bitvec_simd::BitVec::ones(100_000); 115 | black_box(b1.resize(200_000, true)); 116 | }) 117 | }); 118 | } 119 | 120 | fn benchmark_bitvector_bitvec_simd_u16x8(c: &mut Criterion) { 121 | use wide::*; 122 | 123 | let b1 = bitvec_simd::BitVecSimd::<[u16x8; 4], 8>::ones(100_000); 124 | let b2 = bitvec_simd::BitVecSimd::<[u16x8; 4], 8>::zeros(100_000); 125 | c.bench_function("bitvec_simd 0.15.0 u16x8", |b| { 126 | b.iter(|| { 127 | black_box(b1.and_cloned(&b2)); 128 | }) 129 | }); 130 | } 131 | 132 | fn benchmark_bitvector_bitvec_simd2_u16x8(c: &mut Criterion) { 133 | use wide::*; 134 | 135 | c.bench_function("bitvec_simd 0.15.0 u16x8 with creation", |b| { 136 | b.iter(|| { 137 | let b1 = bitvec_simd::BitVecSimd::<[u16x8; 4], 8>::ones(100_000); 138 | let b2 = bitvec_simd::BitVecSimd::<[u16x8; 4], 8>::zeros(100_000); 139 | black_box(b1.and(b2)); 140 | }) 141 | }); 142 | } 143 | 144 | fn benchmark_bitvector_bitvec_simd3_u16x8(c: &mut Criterion) { 145 | use wide::*; 146 | 147 | c.bench_function("bitvec_simd 0.15.0 u16x8 resize false", |b| { 148 | b.iter(|| { 149 | let mut b1 = bitvec_simd::BitVecSimd::<[u16x8; 4], 8>::ones(100_000); 150 | black_box(b1.resize(200_000, false)); 151 | }) 152 | }); 153 | } 154 | 155 | fn benchmark_bitvector_bitvec_simd4_u16x8(c: &mut Criterion) { 156 | use wide::*; 157 | 158 | c.bench_function("bitvec_simd 0.15.0 u16x8 resize true", |b| { 159 | b.iter(|| { 160 | let mut b1 = bitvec_simd::BitVecSimd::<[u16x8; 4], 8>::ones(100_000); 161 | black_box(b1.resize(200_000, true)); 162 | }) 163 | }); 164 | } 165 | 166 | fn benchmark_bitvector_bitvector_simd(c: &mut Criterion) { 167 | let b1 = bitvector_simd::BitVector::ones(100_000); 168 | let b2 = bitvector_simd::BitVector::zeros(100_000); 169 | c.bench_function("bitvector_simd 0.2.2", |b| { 170 | b.iter(|| { 171 | black_box(b1.and_cloned(&b2)); 172 | }) 173 | }); 174 | } 175 | 176 | fn benchmark_bitvector_bitvector_simd2(c: &mut Criterion) { 177 | c.bench_function("bitvector_simd 0.2.2 with creation", |b| { 178 | b.iter(|| { 179 | let b1 = bitvector_simd::BitVector::ones(100_000); 180 | let b2 = bitvector_simd::BitVector::zeros(100_000); 181 | black_box(b1.and(b2)); 182 | }) 183 | }); 184 | } 185 | 186 | fn benchmark_bitvector_bitvec(c: &mut Criterion) { 187 | let b1 = bit_vec::BitVec::from_elem(100_000, true); 188 | let b2 = bit_vec::BitVec::from_elem(100_000, false); 189 | c.bench_function("bit-vec 0.6", |b| { 190 | b.iter(|| { 191 | black_box(b1.clone().and(&b2)); 192 | }) 193 | }); 194 | } 195 | 196 | fn benchmark_bitvector_bitvec2(c: &mut Criterion) { 197 | c.bench_function("bit-vec 0.6 with creation", |b| { 198 | b.iter(|| { 199 | let mut b1 = bit_vec::BitVec::from_elem(100_000, true); 200 | let b2 = bit_vec::BitVec::from_elem(100_000, false); 201 | black_box(b1.and(&b2)); 202 | }) 203 | }); 204 | } 205 | 206 | fn benchmark_bitvector_bitvec_n(c: &mut Criterion) { 207 | let b1 = bitvec::bitvec![usize, bitvec::order::Msb0; 1; 100_000]; 208 | let b2 = bitvec::bitvec![usize, bitvec::order::Msb0; 0; 100_000]; 209 | c.bench_function("bitvec 1.0", |b| { 210 | b.iter(|| { 211 | black_box(b1.clone() & b2.clone()); 212 | }) 213 | }); 214 | } 215 | 216 | fn benchmark_bitvector_bitvec_n2(c: &mut Criterion) { 217 | c.bench_function("bitvec 1.0 with creation", |b| { 218 | b.iter(|| { 219 | let b1 = bitvec::bitvec![usize, bitvec::order::Msb0; 1; 100_000]; 220 | let b2 = bitvec::bitvec![usize, bitvec::order::Msb0; 0; 100_000]; 221 | black_box(b1 & b2); 222 | }) 223 | }); 224 | } 225 | 226 | fn benchmark_bitvector_bitvec_n3(c: &mut Criterion) { 227 | c.bench_function("bitvec 1.0 resize false", |b| { 228 | b.iter(|| { 229 | let mut b1 = bitvec::bitvec![usize, bitvec::order::Msb0; 1; 100_000]; 230 | black_box(b1.resize(200_000, false)); 231 | }) 232 | }); 233 | } 234 | 235 | fn benchmark_bitvector_bitvec_n4(c: &mut Criterion) { 236 | c.bench_function("bitvec 1.0 resize true", |b| { 237 | b.iter(|| { 238 | let mut b1 = bitvec::bitvec![usize, bitvec::order::Msb0; 1; 100_000]; 239 | black_box(b1.resize(200_000, true)); 240 | }) 241 | }); 242 | } 243 | 244 | criterion_group!( 245 | normal_benches, 246 | benchmark_bitvector_simd, 247 | benchmark_bitvector_simd_u16x8, 248 | benchmark_bitvector_bitvec_simd, 249 | benchmark_bitvector_bitvec_simd_u16x8, 250 | benchmark_bitvector_bitvector_simd, 251 | benchmark_bitvector_bitvec, 252 | benchmark_bitvector_bitvec_n 253 | ); 254 | criterion_group!( 255 | with_creation_benches, 256 | benchmark_bitvector_simd2, 257 | benchmark_bitvector_simd2_u16x8, 258 | benchmark_bitvector_bitvec_simd2, 259 | benchmark_bitvector_bitvec_simd2_u16x8, 260 | benchmark_bitvector_bitvector_simd2, 261 | benchmark_bitvector_bitvec2, 262 | benchmark_bitvector_bitvec_n2 263 | ); 264 | criterion_group!( 265 | resize_false_benches, 266 | benchmark_bitvector_simd3, 267 | benchmark_bitvector_simd3_u16x8, 268 | benchmark_bitvector_bitvec_simd3, 269 | benchmark_bitvector_bitvec_simd3_u16x8, 270 | benchmark_bitvector_bitvec_n3 271 | ); 272 | criterion_group!( 273 | resize_true_benches, 274 | benchmark_bitvector_simd4, 275 | benchmark_bitvector_simd4_u16x8, 276 | benchmark_bitvector_bitvec_simd4, 277 | benchmark_bitvector_bitvec_simd4_u16x8, 278 | benchmark_bitvector_bitvec_n4 279 | ); 280 | criterion_main!( 281 | normal_benches, 282 | with_creation_benches, 283 | resize_false_benches, 284 | resize_true_benches 285 | ); 286 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! ## BitVec implemented with [portable-simd](https://github.com/rust-lang/portable-simd). 2 | //! 3 | //! BitVec represents numbers by the position of bits. For example, for the set $\{1,3,5\}$, we 4 | //! can represent it by a just a byte `010101000` -- the most left (high) bit represent if `0` 5 | //! exits in this set or not, the second bit represent `1` ... 6 | //! 7 | //! BitVec is usually used in the algorithm which requires many set intersection/union operations, 8 | //! such like graph mining, formal concept analysis. Set operations in bitvec can be implemented 9 | //! with simple and/or/xor operations so it is much faster than "normal" version of `HashSet`. 10 | //! 11 | //! Furthermore, as SIMD introduces the ability for handling multiple data with a single instruction, 12 | //! set operations can be even faster with SIMD enabled. 13 | //! 14 | //! However, implementation with SIMD in Rust is not really an easy task -- now only low-level API 15 | //! is provided through [core::arch](https://doc.rust-lang.org/core/arch/index.html). It requires 16 | //! many `cfg(target_arch)`s (i.e. different implement on different arch) and 17 | //! assembly-like unsafe function calls. 18 | //! 19 | //! The Rust standard library's portable SIMD API provided a much better API for users. You can just 20 | //! treat SIMD operations as an operation on slices. Portable SIMD wraps all the low-level details 21 | //! for you -- no arch-specified code, no unsafe, just do what you've done on normal integer/floats. 22 | //! 23 | //! This crate uses Portable SIMD to implement a basic bitvec. 24 | //! 25 | //! ### Usage 26 | //! 27 | //! ```rust 28 | //! use bitsvec::BitVec; 29 | //! 30 | //! let mut bitvec = BitVec::ones(1_000); //create a set containing 0 ..= 999 31 | //! bitvec.set(1_999, true); // add 1999 to the set, bitvec will be automatically expanded 32 | //! bitvec.set(500, false); // delete 500 from the set 33 | //! // now the set contains: 0 ..=499, 501..=1999 34 | //! assert_eq!(bitvec.get(500), Some(false)); 35 | //! assert_eq!(bitvec.get(5_000), None); 36 | //! // When try to get number larger than current bitvec, it will return `None`. 37 | //! // of course if you don't care, you can just do: 38 | //! assert_eq!(bitvec.get(5_000).unwrap_or(false), false); 39 | //! 40 | //! let bitvec2 = BitVec::zeros(2000); // create a set containing 0 ..=1999 41 | //! 42 | //! let bitvec3 = bitvec.and_cloned(&bitvec2); 43 | //! // and/or/xor/not operation is provided. 44 | //! // these APIs usually have 2 version: 45 | //! // `.and` consume the inputs and `.and_clone()` accepts reference and will do clone on inputs. 46 | //! let bitvec4 = bitvec & bitvec2; 47 | //! // ofcourse you can just use bit-and operator on bitvecs, it will also consumes the inputs. 48 | //! assert_eq!(bitvec3, bitvec4); 49 | //! // A bitvec can also be constructed from a collection of bool, or a colluction of integer: 50 | //! let bitvec: BitVec = (0 .. 10).map(|x| x%2 == 0).into(); 51 | //! let bitvec2: BitVec = (0 .. 10).map(|x| x%3 == 0).into(); 52 | //! let bitvec3 = BitVec::from_bool_iterator((0..10).map(|x| x%6 == 0)); 53 | //! assert_eq!(bitvec & bitvec2, bitvec3) 54 | //! ``` 55 | //! 56 | //! ## Performance 57 | //! 58 | //! run `cargo bench` to see the benchmarks on your device. 59 | 60 | #![feature(portable_simd)] 61 | #![no_std] 62 | 63 | #[cfg(any(test, feature = "std"))] 64 | #[macro_use] 65 | extern crate std; 66 | #[cfg(feature = "std")] 67 | use std::vec::Vec; 68 | 69 | #[cfg(not(feature = "std"))] 70 | extern crate alloc; 71 | #[cfg(not(feature = "std"))] 72 | use alloc::vec::Vec; 73 | 74 | use core::fmt::{Binary, Debug, Display, Formatter, Result}; 75 | use core::ops::*; 76 | use core::simd::*; 77 | 78 | use smallvec::{Array, SmallVec}; 79 | 80 | #[cfg(test)] 81 | mod tests; 82 | 83 | // Declare the default BitVec type 84 | pub type BitVec = BitVecSimd<[u64x4; 4], 4>; 85 | 86 | /// Representation of a BitVec 87 | /// 88 | /// see the module's document for examples and details. 89 | /// 90 | #[derive(Debug, Clone)] 91 | #[repr(C)] 92 | pub struct BitVecSimd 93 | where 94 | A: Array + Index, 95 | A::Item: BitBlock, 96 | { 97 | // internal representation of bitvec 98 | // TODO: try `Vec`, may be better than smallvec 99 | storage: SmallVec, 100 | // actual number of bits exists in storage 101 | nbits: usize, 102 | } 103 | 104 | /// Proc macro can not export BitVec 105 | /// macro_rules! can not cancot ident 106 | /// so we use name, name_2 for function names 107 | macro_rules! impl_operation { 108 | ($name:ident, $name_cloned:ident, $name_inplace:ident, $op:tt) => { 109 | pub fn $name(self, other: Self) -> Self { 110 | assert_eq!(self.nbits, other.nbits); 111 | let storage = self 112 | .storage 113 | .into_iter() 114 | .zip(other.storage.into_iter()) 115 | .map(|(a, b)| a $op b) 116 | .collect(); 117 | Self { 118 | storage, 119 | nbits: self.nbits, 120 | } 121 | } 122 | pub fn $name_cloned(&self, other: &Self) -> Self { 123 | assert_eq!(self.nbits, other.nbits); 124 | let storage = self 125 | .storage 126 | .iter() 127 | .cloned() 128 | .zip(other.storage.iter().cloned()) 129 | .map(|(a, b)| a $op b) 130 | .collect(); 131 | Self { 132 | storage, 133 | nbits: self.nbits, 134 | } 135 | } 136 | pub fn $name_inplace(&mut self, other: &Self) { 137 | assert_eq!(self.nbits, other.nbits); 138 | self.storage.iter_mut().zip(other.storage.iter()).for_each(|(a, b)| a.$name_inplace(b)); 139 | } 140 | }; 141 | } 142 | 143 | impl BitVecSimd 144 | where 145 | A: Array + Index, 146 | A::Item: BitBlock, 147 | { 148 | // convert total bit to length 149 | // input: Number of bits 150 | // output: 151 | // 152 | // 1. the number of Vector used 153 | // 2. after filling 1, the remaining bytes should be filled 154 | // 3. after filling 2, the remaining bits should be filled 155 | // 156 | // notice that this result represents the length of vector 157 | // so if 3. is 0, it means no extra bits after filling bytes 158 | // return (length of storage, u64 of last container, bit of last elem) 159 | // any bits > length of last elem should be set to 0 160 | #[inline] 161 | fn bit_to_len(nbits: usize) -> (usize, usize, usize) { 162 | ( 163 | nbits / (A::Item::BIT_WIDTH), 164 | (nbits % A::Item::BIT_WIDTH) / A::Item::ELEMENT_BIT_WIDTH, 165 | nbits % A::Item::ELEMENT_BIT_WIDTH, 166 | ) 167 | } 168 | 169 | #[inline] 170 | fn set_bit( 171 | flag: bool, 172 | bytes: >::Item, 173 | offset: u32, 174 | ) -> >::Item { 175 | match flag { 176 | true => bytes | A::Item::ONE_ELEMENT.wrapping_shl(offset), 177 | false => bytes & !A::Item::ONE_ELEMENT.wrapping_shl(offset), 178 | } 179 | } 180 | 181 | /// Create an empty bitvec with `nbits` initial elements. 182 | /// Example: 183 | /// 184 | /// ```rust 185 | /// use bitsvec::BitVec; 186 | /// 187 | /// let bitvec = BitVec::zeros(10); 188 | /// assert_eq!(bitvec.len(), 10); 189 | /// ``` 190 | pub fn zeros(nbits: usize) -> Self { 191 | let len = (nbits + A::Item::BIT_WIDTH - 1) / A::Item::BIT_WIDTH; 192 | let storage = (0..len).map(|_| A::Item::ZERO).collect(); 193 | Self { storage, nbits } 194 | } 195 | 196 | /// Create a bitvec containing all 0 .. nbits elements. 197 | /// Example: 198 | /// 199 | /// ```rust 200 | /// use bitsvec::BitVec; 201 | /// 202 | /// let bitvec = BitVec::ones(10); 203 | /// assert_eq!(bitvec.len(), 10); 204 | /// ``` 205 | pub fn ones(nbits: usize) -> Self { 206 | let (len, bytes, bits) = Self::bit_to_len(nbits); 207 | let mut storage = (0..len).map(|_| A::Item::MAX).collect::>(); 208 | if bytes > 0 || bits > 0 { 209 | let mut arr = A::Item::MAX.to_array(); 210 | arr[bytes] = 211 | A::Item::MAX_ELEMENT.clear_high_bits((A::Item::ELEMENT_BIT_WIDTH - bits) as u32); 212 | for item in arr.iter_mut().take(A::Item::LANES).skip(bytes + 1) { 213 | *item = A::Item::ZERO_ELEMENT; 214 | } 215 | storage.push(A::Item::from(arr)); 216 | } 217 | Self { storage, nbits } 218 | } 219 | 220 | /// Create a bitvec from an Iterator of bool. 221 | /// 222 | /// Example: 223 | /// 224 | /// ```rust 225 | /// use bitsvec::BitVec; 226 | /// 227 | /// let bitvec = BitVec::from_bool_iterator((0..10).map(|x| x % 2 == 0)); 228 | /// assert_eq!(bitvec.len(), 10); 229 | /// assert_eq!(>>::into(bitvec), vec![true, false, true, false, true, false, true, false, true, false]); 230 | /// 231 | /// let bitvec = BitVec::from_bool_iterator((0..1000).map(|x| x < 50)); 232 | /// assert_eq!(bitvec.len(), 1000); 233 | /// assert_eq!(bitvec.get(49), Some(true)); 234 | /// assert_eq!(bitvec.get(50), Some(false)); 235 | /// assert_eq!(bitvec.get(999), Some(false)); 236 | /// assert_eq!(>>::into(bitvec), (0..1000).map(|x| x<50).collect::>()); 237 | /// ``` 238 | pub fn from_bool_iterator>(i: I) -> Self { 239 | // FIXME: any better implementation? 240 | let mut storage = SmallVec::new(); 241 | let mut current_slice = A::Item::ZERO.to_array(); 242 | let mut nbits = 0; 243 | for b in i { 244 | if b { 245 | current_slice[nbits % A::Item::BIT_WIDTH / A::Item::ELEMENT_BIT_WIDTH] |= 246 | A::Item::ONE_ELEMENT.wrapping_shl((nbits % A::Item::ELEMENT_BIT_WIDTH) as u32); 247 | } 248 | nbits += 1; 249 | if nbits % A::Item::BIT_WIDTH == 0 { 250 | storage.push(A::Item::from(current_slice)); 251 | current_slice = A::Item::ZERO.to_array(); 252 | } 253 | } 254 | if nbits % A::Item::BIT_WIDTH > 0 { 255 | storage.push(A::Item::from(current_slice)); 256 | } 257 | Self { storage, nbits } 258 | } 259 | 260 | /// Initialize from a set of integers. 261 | /// 262 | /// Example: 263 | /// 264 | /// ```rust 265 | /// use bitsvec::BitVec; 266 | /// 267 | /// let bitvec = BitVec::from_slice(&[0,5,9]); 268 | /// assert_eq!(>>::into(bitvec), vec![true, false, false, false, false, true, false, false, false, true]); 269 | /// ``` 270 | pub fn from_slice(slice: &[usize]) -> Self { 271 | let mut bv = BitVecSimd::zeros(slice.len()); 272 | for i in slice { 273 | bv.set(*i, true); 274 | } 275 | bv 276 | } 277 | 278 | /// Initialize from a E slice. 279 | /// Data will be copied from the slice. 280 | /// 281 | /// Example: 282 | /// 283 | /// ```rust 284 | /// use bitsvec::BitVec; 285 | /// 286 | /// let bitvec = BitVec::from_slice_copy(&[3], 3); 287 | /// assert_eq!(bitvec.get(0), Some(true)); 288 | /// assert_eq!(bitvec.get(1), Some(true)); 289 | /// assert_eq!(bitvec.get(2), Some(false)); 290 | /// assert_eq!(bitvec.get(3), None); 291 | /// ``` 292 | pub fn from_slice_copy(slice: &[>::Item], nbits: usize) -> Self { 293 | let len = (nbits + A::Item::ELEMENT_BIT_WIDTH - 1) / A::Item::ELEMENT_BIT_WIDTH; 294 | assert!(len <= slice.len()); 295 | 296 | let iter = &mut slice.iter(); 297 | let mut storage = SmallVec::with_capacity((len + A::Item::LANES - 1) / A::Item::LANES); 298 | let (i, bytes, bits) = Self::bit_to_len(nbits); 299 | 300 | while let Some(a0) = iter.next() { 301 | let mut arr = A::Item::ZERO.to_array(); 302 | arr[0] = *a0; 303 | for item in arr.iter_mut().take(A::Item::LANES).skip(1) { 304 | *item = *(iter.next().unwrap_or(&A::Item::ZERO_ELEMENT)); 305 | } 306 | 307 | if storage.len() == i && (bytes > 0 || bits > 0) { 308 | Self::clear_arr_high_bits(&mut arr, bytes, bits); 309 | } 310 | storage.push(A::Item::from(arr)); 311 | } 312 | 313 | Self { storage, nbits } 314 | } 315 | 316 | /// Initialize from a raw buffer. 317 | /// Data will be copied from the buffer which [ptr] points to. 318 | /// The buffer can be released after initialization. 319 | /// 320 | /// # Safety 321 | /// 322 | /// If any of the following conditions are violated, the result is Undefined 323 | /// Behavior: 324 | /// 325 | /// * ptr should be valid and point to an [allocated object] with length >= buffer_len 326 | /// 327 | /// * ptr.offset(buffer_len - 1), **in bytes**, cannot overflow an `isize`. 328 | /// 329 | /// * The offset being in bounds cannot rely on "wrapping around" the address 330 | /// space. That is, the infinite-precision sum, **in bytes** must fit in a usize. 331 | /// 332 | pub unsafe fn from_raw_copy( 333 | ptr: *const >::Item, 334 | buffer_len: usize, 335 | nbits: usize, 336 | ) -> Self { 337 | let len = (nbits + A::Item::ELEMENT_BIT_WIDTH - 1) / A::Item::ELEMENT_BIT_WIDTH; 338 | assert!(len <= buffer_len); 339 | 340 | let mut storage = SmallVec::with_capacity((len + A::Item::LANES - 1) / A::Item::LANES); 341 | let (i, bytes, bits) = Self::bit_to_len(nbits); 342 | 343 | for index in 0..(len as isize) { 344 | let mut arr = A::Item::ZERO.to_array(); 345 | for (j, item) in arr.iter_mut().enumerate().take(A::Item::LANES) { 346 | let k = index * A::Item::LANES as isize + j as isize; 347 | *item = if k < len as isize { 348 | // The only unsafe operation happens here 349 | *(ptr.offset(k)) 350 | } else { 351 | A::Item::ZERO_ELEMENT 352 | }; 353 | } 354 | if storage.len() == i && (bytes > 0 || bits > 0) { 355 | Self::clear_arr_high_bits(&mut arr, bytes, bits); 356 | } 357 | storage.push(A::Item::from(arr)); 358 | } 359 | 360 | Self { storage, nbits } 361 | } 362 | 363 | /// Length of this bitvec. 364 | /// 365 | /// To get the number of elements, use `count_ones` 366 | /// 367 | /// Example: 368 | /// 369 | /// ```rust 370 | /// use bitsvec::BitVec; 371 | /// 372 | /// let bitvec = BitVec::ones(3); 373 | /// assert_eq!(bitvec.len(), 3); 374 | /// ``` 375 | #[inline] 376 | pub fn len(&self) -> usize { 377 | self.nbits 378 | } 379 | 380 | /// Length of underlining storage. 381 | #[inline] 382 | pub fn storage_len(&self) -> usize { 383 | self.storage.len() 384 | } 385 | 386 | /// Capacity of underlining storage. 387 | #[inline] 388 | pub fn storage_capacity(&self) -> usize { 389 | self.storage.capacity() 390 | } 391 | 392 | /// Returns a raw pointer to the vector's buffer. 393 | pub fn as_ptr(&self) -> *const A::Item { 394 | self.storage.as_ptr() 395 | } 396 | 397 | /// Returns a raw mutable pointer to the vector's buffer. 398 | pub fn as_mut_ptr(&mut self) -> *mut A::Item { 399 | self.storage.as_mut_ptr() 400 | } 401 | 402 | /// Returns `true` if the data has spilled into a separate heap-allocated buffer. 403 | #[inline] 404 | pub fn spilled(&self) -> bool { 405 | self.storage.spilled() 406 | } 407 | 408 | fn clear_arr_high_bits(arr: &mut [>::Item], bytes: usize, bits: usize) { 409 | let mut end_bytes = bytes; 410 | if bits > 0 { 411 | arr[end_bytes] = 412 | arr[end_bytes].clear_high_bits((A::Item::ELEMENT_BIT_WIDTH - bits) as u32); 413 | end_bytes += 1; 414 | } 415 | for item in arr.iter_mut().take(A::Item::LANES).skip(end_bytes) { 416 | *item = A::Item::ZERO_ELEMENT; 417 | } 418 | } 419 | 420 | fn fill_arr_high_bits( 421 | arr: &mut [>::Item], 422 | bytes: usize, 423 | bits: usize, 424 | bytes_max: usize, 425 | ) { 426 | let mut end_bytes = bytes; 427 | if bits > 0 { 428 | arr[end_bytes] |= A::Item::MAX_ELEMENT.clear_low_bits(bits as u32); 429 | end_bytes += 1; 430 | } 431 | for item in arr.iter_mut().take(bytes_max).skip(end_bytes) { 432 | *item = A::Item::MAX_ELEMENT; 433 | } 434 | } 435 | 436 | fn clear_high_bits(&mut self, i: usize, bytes: usize, bits: usize) { 437 | if bytes > 0 || bits > 0 { 438 | let mut arr = self.storage[i].to_array(); 439 | Self::clear_arr_high_bits(&mut arr, bytes, bits); 440 | self.storage[i] = A::Item::from(arr); 441 | } 442 | } 443 | 444 | fn fill_high_bits(&mut self, i: usize, bytes: usize, bits: usize, bytes_max: usize) { 445 | if bytes > 0 || bits > 0 { 446 | let mut arr = self.storage[i].to_array(); 447 | Self::fill_arr_high_bits(&mut arr, bytes, bits, bytes_max); 448 | self.storage[i] = A::Item::from(arr); 449 | } 450 | } 451 | 452 | fn fix_high_bits( 453 | &mut self, 454 | old_i: usize, 455 | old_bytes: usize, 456 | old_bits: usize, 457 | i: usize, 458 | bytes: usize, 459 | bits: usize, 460 | ) { 461 | debug_assert!(old_i == i && old_bytes <= bytes && (bytes > 0 || bits > 0)); 462 | let mut arr = self.storage[i].to_array(); 463 | if old_bytes < bytes { 464 | Self::fill_arr_high_bits( 465 | &mut arr, 466 | old_bytes, 467 | old_bits, 468 | if bits > 0 { bytes + 1 } else { bytes }, 469 | ); 470 | } else { 471 | debug_assert!(old_bytes == bytes && bits >= old_bits); 472 | if bits > old_bits { 473 | // fix the only byte 474 | arr[bytes] |= A::Item::MAX_ELEMENT.clear_low_bits(old_bits as u32); 475 | } 476 | } 477 | Self::clear_arr_high_bits(&mut arr, bytes, bits); 478 | self.storage[i] = A::Item::from(arr); 479 | } 480 | 481 | /// Resize this bitvec to `nbits` in-place. 482 | /// If new length is greater than current length, `value` will be filled. 483 | /// 484 | /// Example: 485 | /// 486 | /// ```rust 487 | /// use bitsvec::BitVec; 488 | /// 489 | /// let mut bitvec = BitVec::ones(3); 490 | /// bitvec.resize(5, false); 491 | /// assert_eq!(bitvec.len(), 5); 492 | /// bitvec.resize(2, false); 493 | /// assert_eq!(bitvec.len(), 2); 494 | /// ``` 495 | pub fn resize(&mut self, nbits: usize, value: bool) { 496 | let (i, bytes, bits) = Self::bit_to_len(nbits); 497 | self.storage.resize( 498 | if bytes > 0 || bits > 0 { i + 1 } else { i }, 499 | if value { A::Item::MAX } else { A::Item::ZERO }, 500 | ); 501 | if nbits < self.nbits { 502 | self.clear_high_bits(i, bytes, bits); 503 | } else if value { 504 | // old_i <= i && filling 1 505 | let (old_i, old_bytes, old_bits) = Self::bit_to_len(self.nbits); 506 | if old_i < i { 507 | self.fill_high_bits(old_i, old_bytes, old_bits, A::Item::LANES); 508 | self.clear_high_bits(i, bytes, bits); 509 | } else if bytes > 0 || bits > 0 { 510 | self.fix_high_bits(old_i, old_bytes, old_bits, i, bytes, bits); 511 | } 512 | } 513 | self.nbits = nbits; 514 | } 515 | 516 | /// Shink this bitvec to new length in-place. 517 | /// Panics if new length is greater than original. 518 | /// 519 | /// Example: 520 | /// 521 | /// ```rust 522 | /// use bitsvec::BitVec; 523 | /// 524 | /// let mut bitvec = BitVec::ones(3); 525 | /// bitvec.shrink_to(2); 526 | /// assert_eq!(bitvec.len(), 2); 527 | /// ``` 528 | pub fn shrink_to(&mut self, nbits: usize) { 529 | if nbits >= self.nbits { 530 | panic!( 531 | "nbits {} should be less than current value {}", 532 | nbits, self.nbits 533 | ); 534 | } 535 | self.resize(nbits, false); 536 | } 537 | 538 | /// Remove or add `index` to the set. 539 | /// If index > self.len, the bitvec will be expanded to `index`. 540 | /// Example: 541 | /// 542 | /// ```rust 543 | /// use bitsvec::BitVec; 544 | /// 545 | /// let mut bitvec = BitVec::zeros(10); 546 | /// assert_eq!(bitvec.len(), 10); 547 | /// bitvec.set(15, true); 548 | /// // now 15 has been added to the set, its total len is 16. 549 | /// assert_eq!(bitvec.len(), 16); 550 | /// assert_eq!(bitvec.get(15), Some(true)); 551 | /// assert_eq!(bitvec.get(14), Some(false)); 552 | /// ``` 553 | pub fn set(&mut self, index: usize, flag: bool) { 554 | let (i, bytes, bits) = Self::bit_to_len(index); 555 | if self.nbits <= index { 556 | let new_len = if bytes > 0 || bits > 0 { i + 1 } else { i }; 557 | self.storage 558 | .extend((0..new_len - self.storage.len()).map(move |_| A::Item::ZERO)); 559 | self.nbits = index + 1; 560 | } 561 | let mut arr = self.storage[i].to_array(); 562 | arr[bytes] = Self::set_bit(flag, arr[bytes], bits as u32); 563 | self.storage[i] = A::Item::from(arr); 564 | } 565 | 566 | /// Copy content which ptr points to bitvec storage 567 | /// 568 | /// # Safety 569 | /// 570 | /// This is highly unsafe, due to the number of invariants that aren’t checked. 571 | pub unsafe fn set_raw_copy(&mut self, ptr: *mut A::Item, buffer_len: usize, nbits: usize) { 572 | let new_len = (nbits + A::Item::BIT_WIDTH - 1) / A::Item::BIT_WIDTH; 573 | assert!(new_len <= buffer_len); 574 | 575 | if new_len > self.len() { 576 | self.storage 577 | .extend((0..new_len - self.storage.len()).map(move |_| A::Item::ZERO)); 578 | } 579 | 580 | for i in 0..(new_len as isize) { 581 | self.storage[i as usize] = *ptr.offset(i); 582 | } 583 | self.nbits = nbits; 584 | } 585 | 586 | /// Directly set storage to ptr 587 | /// 588 | /// # Safety 589 | /// 590 | /// This is highly unsafe, due to the number of invariants that aren’t checked. 591 | pub unsafe fn set_raw( 592 | &mut self, 593 | ptr: *mut A::Item, 594 | buffer_len: usize, 595 | capacity: usize, 596 | nbits: usize, 597 | ) { 598 | self.storage = SmallVec::from_raw_parts(ptr, buffer_len, capacity); 599 | self.nbits = nbits; 600 | } 601 | 602 | /// Set all items in bitvec to false 603 | pub fn set_all_false(&mut self) { 604 | self.storage 605 | .iter_mut() 606 | .for_each(move |x| *x = A::Item::ZERO); 607 | } 608 | 609 | /// Set all items in bitvec to true 610 | pub fn set_all_true(&mut self) { 611 | let (_, bytes, bits) = Self::bit_to_len(self.nbits); 612 | self.storage.iter_mut().for_each(move |x| *x = A::Item::MAX); 613 | if bytes > 0 || bits > 0 { 614 | let mut arr = A::Item::MAX.to_array(); 615 | arr[bytes] = 616 | A::Item::MAX_ELEMENT.clear_high_bits((A::Item::ELEMENT_BIT_WIDTH - bits) as u32); 617 | for item in arr.iter_mut().take(A::Item::LANES).skip(bytes + 1) { 618 | *item = A::Item::ZERO_ELEMENT; 619 | } 620 | // unwrap here is safe since bytes > 0 || bits > 0 => self.nbits > 0 621 | *(self.storage.last_mut().unwrap()) = A::Item::from(arr); 622 | } 623 | } 624 | 625 | /// Set all items in bitvec to flag 626 | pub fn set_all(&mut self, flag: bool) { 627 | match flag { 628 | true => self.set_all_true(), 629 | false => self.set_all_false(), 630 | } 631 | } 632 | 633 | /// Check if `index` exists in current set. 634 | /// 635 | /// * If exists, return `Some(true)` 636 | /// * If index < current.len and element doesn't exist, return `Some(false)`. 637 | /// * If index >= current.len, return `None`. 638 | /// 639 | /// Examlpe: 640 | /// 641 | /// ```rust 642 | /// use bitsvec::BitVec; 643 | /// 644 | /// let bitvec : BitVec = (0 .. 15).map(|x| x%3 == 0).into(); 645 | /// assert_eq!(bitvec.get(3), Some(true)); 646 | /// assert_eq!(bitvec.get(5), Some(false)); 647 | /// assert_eq!(bitvec.get(14), Some(false)); 648 | /// assert_eq!(bitvec.get(15), None); 649 | /// ``` 650 | pub fn get(&self, index: usize) -> Option { 651 | if self.nbits <= index { 652 | None 653 | } else { 654 | let (index, bytes, bits) = Self::bit_to_len(index); 655 | Some( 656 | self.storage[index].to_array()[bytes] 657 | & A::Item::ONE_ELEMENT.wrapping_shl(bits as u32) 658 | != A::Item::ZERO_ELEMENT, 659 | ) 660 | } 661 | } 662 | 663 | /// Directly return a `bool` instead of an `Option` 664 | /// 665 | /// * If exists, return `true`. 666 | /// * If doesn't exist, return false. 667 | /// * If index >= current.len, panic. 668 | /// 669 | /// 670 | /// Examlpe: 671 | /// 672 | /// ```rust 673 | /// use bitsvec::BitVec; 674 | /// 675 | /// let bitvec : BitVec = (0 .. 15).map(|x| x%3 == 0).into(); 676 | /// assert_eq!(bitvec.get_unchecked(3), true); 677 | /// assert_eq!(bitvec.get_unchecked(5), false); 678 | /// assert_eq!(bitvec.get_unchecked(14), false); 679 | /// ``` 680 | pub fn get_unchecked(&self, index: usize) -> bool { 681 | if self.nbits <= index { 682 | panic!("index out of bounds {} > {}", index, self.nbits); 683 | } else { 684 | let (index, bytes, bits) = Self::bit_to_len(index); 685 | (self.storage[index].to_array()[bytes] & A::Item::ONE_ELEMENT.wrapping_shl(bits as u32)) 686 | != A::Item::ZERO_ELEMENT 687 | } 688 | } 689 | 690 | impl_operation!(and, and_cloned, and_inplace, &); 691 | impl_operation!(or, or_cloned, or_inplace, |); 692 | impl_operation!(xor, xor_cloned, xor_inplace, ^); 693 | 694 | /// difference operation 695 | /// 696 | /// `A.difference(B)` calculates `A\B`, e.g. 697 | /// 698 | /// ```text 699 | /// A = [1,2,3], B = [2,4,5] 700 | /// A\B = [1,3] 701 | /// ``` 702 | /// 703 | /// also notice that 704 | /// 705 | /// ```text 706 | /// A.difference(B) | B.difference(A) == A ^ B 707 | /// ``` 708 | /// 709 | /// Example: 710 | /// 711 | /// ```rust 712 | /// use bitsvec::BitVec; 713 | /// 714 | /// let bitvec: BitVec = (0 .. 5_000).map(|x| x % 2 == 0).into(); 715 | /// let bitvec2 : BitVec = (0 .. 5_000).map(|x| x % 3 == 0).into(); 716 | /// assert_eq!(bitvec.difference_cloned(&bitvec2) | bitvec2.difference_cloned(&bitvec), bitvec.xor_cloned(&bitvec2)); 717 | /// let bitvec3 : BitVec = (0 .. 5_000).map(|x| x % 2 == 0 && x % 3 != 0).into(); 718 | /// assert_eq!(bitvec.difference(bitvec2), bitvec3); 719 | /// ``` 720 | pub fn difference(self, other: Self) -> Self { 721 | self.and(other.not()) 722 | } 723 | 724 | pub fn difference_cloned(&self, other: &Self) -> Self { 725 | // FIXME: This implementation has one extra clone 726 | self.and_cloned(&<&BitVecSimd>::clone(&other).not()) 727 | } 728 | 729 | // not should make sure bits > nbits is 0 730 | /// inverse every bits in the vector. 731 | /// 732 | /// If your bitvec have len `1_000` and contains `[1,5]`, 733 | /// after inverse it will contains `0, 2..=4, 6..=999` 734 | pub fn inverse(&self) -> Self { 735 | let (i, bytes, bits) = Self::bit_to_len(self.nbits); 736 | let mut storage = self.storage.iter().map(|x| !(*x)).collect::>(); 737 | if bytes > 0 || bits > 0 { 738 | assert_eq!(storage.len(), i + 1); 739 | let s: &mut A::Item = &mut storage[i]; 740 | let mut arr = s.to_array(); 741 | arr[bytes] = arr[bytes].clear_high_bits((A::Item::ELEMENT_BIT_WIDTH - bits) as u32); 742 | for item in arr.iter_mut().take(A::Item::LANES).skip(bytes + 1) { 743 | *item = A::Item::ZERO_ELEMENT; 744 | } 745 | *s = arr.into(); 746 | } 747 | 748 | Self { 749 | storage, 750 | nbits: self.nbits, 751 | } 752 | } 753 | 754 | /// Count the number of elements existing in this bitvec. 755 | /// 756 | /// Example: 757 | /// 758 | /// ```rust 759 | /// use bitsvec::BitVec; 760 | /// 761 | /// let bitvec: BitVec = (0..10_000).map(|x| x%2==0).into(); 762 | /// assert_eq!(bitvec.count_ones(), 5000); 763 | /// 764 | /// let bitvec: BitVec = (0..30_000).map(|x| x%3==0).into(); 765 | /// assert_eq!(bitvec.count_ones(), 10_000); 766 | /// ``` 767 | pub fn count_ones(&self) -> usize { 768 | self.storage 769 | .iter() 770 | .map(|x| { 771 | x.to_array() 772 | .into_iter() 773 | .map(|a| a.count_ones()) 774 | .sum::() 775 | }) 776 | .sum::() as usize 777 | } 778 | 779 | /// Count the number of elements existing in this bitvec, before the specified index. 780 | /// Panics if index is invalid. 781 | /// 782 | /// Example: 783 | /// 784 | /// ```rust 785 | /// use bitsvec::BitVec; 786 | /// 787 | /// let bitvec: BitVec = (0..10_000).map(|x| x%2==0).into(); 788 | /// assert_eq!(bitvec.count_ones_before(5000), 2500); 789 | /// 790 | /// let bitvec: BitVec = (0..30_000).map(|x| x%3==0).into(); 791 | /// assert_eq!(bitvec.count_ones_before(10000), 3334); 792 | /// ``` 793 | pub fn count_ones_before(&self, index: usize) -> usize { 794 | assert!(index <= self.nbits); 795 | if index == 0 { 796 | return 0; 797 | } 798 | let (i, bytes, bits) = Self::bit_to_len(index - 1); 799 | let mut ones = self 800 | .storage 801 | .iter() 802 | .take(i) 803 | .map(|x| { 804 | x.to_array() 805 | .into_iter() 806 | .map(|a| a.count_ones()) 807 | .sum::() 808 | }) 809 | .sum::(); 810 | if bytes > 0 || bits > 0 { 811 | // Safe unwrap here 812 | let arr = self.storage.iter().nth(i).unwrap().to_array(); 813 | ones += arr 814 | .into_iter() 815 | .take(bytes) 816 | .map(|x| x.count_ones()) 817 | .sum::(); 818 | if bits > 0 { 819 | let x = arr.into_iter().nth(bytes).unwrap(); 820 | ones += (x 821 | & (A::Item::ONE_ELEMENT.wrapping_shl((bits + 1) as u32) 822 | - A::Item::ONE_ELEMENT)) 823 | .count_ones(); 824 | } 825 | } 826 | ones as usize 827 | } 828 | 829 | /// Count the number of leading zeros in this bitvec. 830 | /// 831 | /// Example: 832 | /// 833 | /// ```rust 834 | /// use bitsvec::BitVec; 835 | /// 836 | /// let mut bitvec = BitVec::zeros(10); 837 | /// bitvec.set(3, true); 838 | /// assert_eq!(bitvec.leading_zeros(), 6); 839 | /// ``` 840 | pub fn leading_zeros(&self) -> usize { 841 | let mut zero_item_count = 0; 842 | let mut iter = self 843 | .storage 844 | .iter() 845 | .rev() 846 | .skip_while(|x| match **x == A::Item::ZERO { 847 | true => { 848 | zero_item_count += A::Item::LANES; 849 | true 850 | } 851 | false => false, 852 | }); 853 | 854 | if let Some(x) = iter.next() { 855 | let arr = x.to_array(); 856 | let mut x_iter = 857 | arr.into_iter() 858 | .rev() 859 | .skip_while(|y| match *y == A::Item::ZERO_ELEMENT { 860 | true => { 861 | zero_item_count += 1; 862 | true 863 | } 864 | false => false, 865 | }); 866 | 867 | // Safe unwrap here, since there should be at least one non-zero item in arr. 868 | let y = x_iter.next().unwrap(); 869 | let raw_leading_zeros = 870 | zero_item_count * A::Item::ELEMENT_BIT_WIDTH + y.leading_zeros() as usize; 871 | let mut extra_leading_zeros = self.nbits % A::Item::BIT_WIDTH; 872 | if extra_leading_zeros > 0 { 873 | extra_leading_zeros = A::Item::BIT_WIDTH - extra_leading_zeros 874 | } 875 | return raw_leading_zeros - extra_leading_zeros; 876 | } 877 | 878 | self.nbits 879 | } 880 | 881 | /// return true if contains at least 1 element 882 | pub fn any(&self) -> bool { 883 | self.storage.iter().any(|x| { 884 | x.to_array() 885 | .into_iter() 886 | .map(|a| a.count_ones()) 887 | .sum::() 888 | > 0 889 | }) 890 | } 891 | 892 | /// return true if contains self.len elements 893 | pub fn all(&self) -> bool { 894 | self.count_ones() == self.nbits 895 | } 896 | 897 | /// return true if set is empty 898 | pub fn none(&self) -> bool { 899 | !self.any() 900 | } 901 | 902 | /// Return true if set is empty. 903 | /// Totally the same with `self.none()` 904 | pub fn is_empty(&self) -> bool { 905 | !self.any() 906 | } 907 | 908 | /// Consume self and generate a `Vec` with length == self.len(). 909 | /// 910 | /// Example: 911 | /// 912 | /// ```rust 913 | /// use bitsvec::BitVec; 914 | /// 915 | /// let bitvec = BitVec::from_bool_iterator((0..10).map(|i| i % 3 == 0)); 916 | /// let bool_vec = bitvec.into_bools(); 917 | /// assert_eq!(bool_vec, vec![true, false, false, true, false, false, true, false, false, true]) 918 | /// ``` 919 | pub fn into_bools(self) -> Vec { 920 | self.into() 921 | } 922 | 923 | /// Consume self and geterate a `Vec` which only contains the number exists in this set. 924 | /// 925 | /// Example: 926 | /// 927 | /// ```rust 928 | /// use bitsvec::BitVec; 929 | /// 930 | /// let bitvec = BitVec::from_bool_iterator((0..10).map(|i| i%3 == 0)); 931 | /// let usize_vec = bitvec.into_usizes(); 932 | /// assert_eq!(usize_vec, vec![0,3,6,9]); 933 | /// ``` 934 | pub fn into_usizes(self) -> Vec { 935 | self.into() 936 | } 937 | } 938 | 939 | impl, const L: usize> From for BitVecSimd 940 | where 941 | A: Array + Index, 942 | A::Item: BitBlock, 943 | { 944 | fn from(i: I) -> Self { 945 | Self::from_bool_iterator(i) 946 | } 947 | } 948 | 949 | macro_rules! impl_trait { 950 | ( 951 | ( $( $name:tt )+ ), 952 | ( $( $name1:tt )+ ), 953 | { $( $body:tt )* } 954 | ) => 955 | { 956 | impl $( $name )+ for $( $name1 )+ 957 | where 958 | A: Array + Index, 959 | A::Item: BitBlock, 960 | { $( $body )* } 961 | }; 962 | } 963 | 964 | impl_trait! { 965 | (From< BitVecSimd >), 966 | (Vec), 967 | { 968 | fn from(v: BitVecSimd) -> Self { 969 | v.storage 970 | .into_iter() 971 | .flat_map(|x| x.to_array()) 972 | .flat_map(|x| { 973 | (0..A::Item::ELEMENT_BIT_WIDTH) 974 | .map(move |i| (x.wrapping_shr(i as u32)) & A::Item::ONE_ELEMENT != A::Item::ZERO_ELEMENT) 975 | }) 976 | .take(v.nbits) 977 | .collect() 978 | } 979 | } 980 | } 981 | 982 | impl_trait! { 983 | (From< BitVecSimd >), 984 | (Vec), 985 | { 986 | fn from(v: BitVecSimd) -> Self { 987 | v.storage 988 | .into_iter() 989 | .flat_map(|x| x.to_array()) 990 | .flat_map(|x| { (0..A::Item::ELEMENT_BIT_WIDTH).map(move |i| (x.wrapping_shr(i as u32)) & A::Item::ONE_ELEMENT != A::Item::ZERO_ELEMENT) }) 991 | .take(v.nbits) 992 | .enumerate() 993 | .filter(|(_, b)| *b) 994 | .map(|(i, _)| i) 995 | .collect() 996 | } 997 | } 998 | } 999 | 1000 | impl_trait! { 1001 | (Index), 1002 | (BitVecSimd), 1003 | { 1004 | type Output = bool; 1005 | fn index(&self, index: usize) -> &Self::Output { 1006 | if self.get_unchecked(index) { 1007 | &true 1008 | } else { 1009 | &false 1010 | } 1011 | } 1012 | } 1013 | } 1014 | 1015 | impl_trait! { 1016 | (Display), 1017 | (BitVecSimd), 1018 | { 1019 | fn fmt(&self, f: &mut Formatter) -> Result { 1020 | for i in 0..self.nbits { 1021 | write!(f, "{}", if self.get_unchecked(i) { 1 } else { 0 })?; 1022 | } 1023 | Ok(()) 1024 | } 1025 | } 1026 | } 1027 | 1028 | macro_rules! impl_eq_fn { 1029 | ($( $rhs:tt )+) => { 1030 | // eq should always ignore the bits > nbits 1031 | fn eq(&self, other: $( $rhs )+) -> bool { 1032 | assert_eq!(self.nbits, other.nbits); 1033 | self.storage 1034 | .iter() 1035 | .zip(other.storage.iter()) 1036 | .all(|(a, b)| a == b) 1037 | } 1038 | } 1039 | } 1040 | 1041 | impl_trait! { (PartialEq), (BitVecSimd), { impl_eq_fn!(&Self); } } 1042 | impl_trait! { (PartialEq< &BitVecSimd >), (BitVecSimd), { impl_eq_fn!(&&Self); } } 1043 | impl_trait! { (PartialEq< &mut BitVecSimd >), (BitVecSimd), { impl_eq_fn!(&&mut Self); } } 1044 | impl_trait! { (PartialEq< BitVecSimd >), (&BitVecSimd), { impl_eq_fn!(&BitVecSimd); } } 1045 | impl_trait! { (PartialEq< BitVecSimd >), (&mut BitVecSimd), { impl_eq_fn!(&BitVecSimd); } } 1046 | 1047 | macro_rules! impl_bit_op_fn { 1048 | ($fn:ident, $op:ident, ( $( $rhs:tt )+ )) => 1049 | { 1050 | type Output = BitVecSimd; 1051 | fn $fn(self, rhs: $( $rhs )+) -> Self::Output { 1052 | self.$op(rhs) 1053 | } 1054 | }; 1055 | ($fn:ident, $op:ident, &, ( $( $rhs:tt )+ )) => 1056 | { 1057 | type Output = BitVecSimd; 1058 | fn $fn(self, rhs: $( $rhs )+) -> Self::Output { 1059 | self.$op(&rhs) 1060 | } 1061 | } 1062 | } 1063 | 1064 | macro_rules! impl_bit_op { 1065 | ($trait:ident, $fn:ident, $op:ident, $op_cloned:ident) => { 1066 | impl_trait! {($trait), (BitVecSimd), { impl_bit_op_fn!($fn, $op, (Self)); } } // a & b 1067 | impl_trait! {($trait< &BitVecSimd >), (BitVecSimd), { impl_bit_op_fn!($fn, $op_cloned, (&Self)); } } // a & &b 1068 | impl_trait! { ($trait< &mut BitVecSimd >), (BitVecSimd), { impl_bit_op_fn!($fn, $op_cloned, (&mut Self)); } } // a & &mut b 1069 | impl_trait! { ($trait< BitVecSimd >), (&BitVecSimd), { impl_bit_op_fn!($fn, $op_cloned, &, (BitVecSimd)); } } // &a & b 1070 | impl_trait! { ($trait), (&BitVecSimd), { impl_bit_op_fn!($fn, $op_cloned, (Self)); } } // &a & &b 1071 | impl_trait! { ($trait< &mut BitVecSimd >), (&BitVecSimd), { impl_bit_op_fn!($fn, $op_cloned, (&mut BitVecSimd)); } } // &a & &mut b 1072 | impl_trait! { ($trait< BitVecSimd >), (&mut BitVecSimd), { impl_bit_op_fn!($fn, $op_cloned, &, (BitVecSimd)); } } // &mut a & b 1073 | impl_trait! { ($trait< &BitVecSimd >), (&mut BitVecSimd), { impl_bit_op_fn!($fn, $op_cloned, (&BitVecSimd)); } } // &mut a & &b 1074 | impl_trait! { ($trait), (&mut BitVecSimd), { impl_bit_op_fn!($fn, $op_cloned, (Self)); } } // &mut a & &mut b 1075 | }; 1076 | } 1077 | 1078 | impl_bit_op!(BitAnd, bitand, and, and_cloned); 1079 | impl_bit_op!(BitOr, bitor, or, or_cloned); 1080 | impl_bit_op!(BitXor, bitxor, xor, xor_cloned); 1081 | 1082 | macro_rules! impl_not_fn { 1083 | () => { 1084 | type Output = BitVecSimd; 1085 | fn not(self) -> Self::Output { 1086 | self.inverse() 1087 | } 1088 | }; 1089 | } 1090 | 1091 | impl_trait! {(Not), (BitVecSimd), { impl_not_fn!(); }} 1092 | impl_trait! {(Not), (&BitVecSimd), { impl_not_fn!(); }} 1093 | impl_trait! {(Not), (&mut BitVecSimd), { impl_not_fn!(); }} 1094 | 1095 | macro_rules! impl_bit_assign_fn { 1096 | (($( $rhs:tt )+), $fn:ident, $fn1:ident, &) => { 1097 | fn $fn(&mut self, rhs: $( $rhs )+) { 1098 | self.$fn1(&rhs); 1099 | } 1100 | }; 1101 | (($( $rhs:tt )+), $fn:ident, $fn1:ident) => { 1102 | fn $fn(&mut self, rhs: $( $rhs )+) { 1103 | self.$fn1(rhs); 1104 | } 1105 | } 1106 | } 1107 | 1108 | impl_trait! {(BitAndAssign), (BitVecSimd), { impl_bit_assign_fn!((Self), bitand_assign, and_inplace, &); } } 1109 | impl_trait! {(BitAndAssign< &BitVecSimd >), (BitVecSimd), { impl_bit_assign_fn!((&BitVecSimd), bitand_assign, and_inplace); } } 1110 | impl_trait! {(BitAndAssign< &mut BitVecSimd >), (BitVecSimd), { impl_bit_assign_fn!((&mut BitVecSimd), bitand_assign, and_inplace); } } 1111 | impl_trait! {(BitOrAssign), (BitVecSimd), { impl_bit_assign_fn!((Self), bitor_assign, or_inplace, &); } } 1112 | impl_trait! {(BitOrAssign< &BitVecSimd >), (BitVecSimd), { impl_bit_assign_fn!((&BitVecSimd), bitor_assign, or_inplace); } } 1113 | impl_trait! {(BitOrAssign< &mut BitVecSimd >), (BitVecSimd), { impl_bit_assign_fn!((&mut BitVecSimd), bitor_assign, or_inplace); } } 1114 | impl_trait! {(BitXorAssign), (BitVecSimd), { impl_bit_assign_fn!((Self), bitxor_assign, xor_inplace, &); } } 1115 | impl_trait! {(BitXorAssign< &BitVecSimd >), (BitVecSimd), { impl_bit_assign_fn!((&BitVecSimd), bitxor_assign, xor_inplace); } } 1116 | impl_trait! {(BitXorAssign< &mut BitVecSimd >), (BitVecSimd), { impl_bit_assign_fn!((&mut BitVecSimd), bitxor_assign, xor_inplace); } } 1117 | 1118 | // BitBlockItem is the element of a SIMD type BitBlock 1119 | pub trait BitBlockItem: 1120 | Not 1121 | + BitAnd 1122 | + BitOr 1123 | + BitXor 1124 | + Shl 1125 | + Shr 1126 | + BitAndAssign 1127 | + BitOrAssign 1128 | + Add 1129 | + Sub 1130 | + PartialEq 1131 | + Sized 1132 | + Copy 1133 | + Clone 1134 | + Binary 1135 | { 1136 | const BIT_WIDTH: usize; 1137 | const ZERO: Self; 1138 | const ONE: Self; 1139 | const MAX: Self; 1140 | 1141 | fn count_ones(self) -> u32; 1142 | fn leading_zeros(self) -> u32; 1143 | fn wrapping_shl(self, rhs: u32) -> Self; 1144 | fn wrapping_shr(self, rhs: u32) -> Self; 1145 | fn clear_high_bits(self, rhs: u32) -> Self; 1146 | fn clear_low_bits(self, rhs: u32) -> Self; 1147 | } 1148 | 1149 | macro_rules! impl_bitblock_item { 1150 | ($type: ty, $zero: expr, $one: expr, $max: expr) => { 1151 | impl BitBlockItem for $type { 1152 | const BIT_WIDTH: usize = Self::BITS as usize; 1153 | const ZERO: Self = $zero; 1154 | const ONE: Self = $one; 1155 | const MAX: Self = $max; 1156 | 1157 | #[inline] 1158 | fn count_ones(self) -> u32 { 1159 | Self::count_ones(self) 1160 | } 1161 | 1162 | #[inline] 1163 | fn leading_zeros(self) -> u32 { 1164 | Self::leading_zeros(self) 1165 | } 1166 | 1167 | #[inline] 1168 | fn wrapping_shl(self, rhs: u32) -> Self { 1169 | self.wrapping_shl(rhs) 1170 | } 1171 | 1172 | #[inline] 1173 | fn wrapping_shr(self, rhs: u32) -> Self { 1174 | self.wrapping_shr(rhs) 1175 | } 1176 | 1177 | #[inline] 1178 | fn clear_high_bits(self, rhs: u32) -> Self { 1179 | self.wrapping_shl(rhs).wrapping_shr(rhs) 1180 | } 1181 | 1182 | #[inline] 1183 | fn clear_low_bits(self, rhs: u32) -> Self { 1184 | self.wrapping_shr(rhs).wrapping_shl(rhs) 1185 | } 1186 | } 1187 | }; 1188 | } 1189 | 1190 | impl_bitblock_item!(u8, 0u8, 1u8, 0xFFu8); 1191 | impl_bitblock_item!(u16, 0u16, 1u16, 0xFFFFu16); 1192 | impl_bitblock_item!(u32, 0u32, 1u32, 0xFFFFFFFFu32); 1193 | impl_bitblock_item!(u64, 0u64, 1u64, 0xFFFFFFFFFFFFFFFFu64); 1194 | 1195 | // BitBlock is the basic building block for internal storage 1196 | // BitVec is expected to be aligned properly 1197 | pub trait BitBlock: 1198 | Not 1199 | + BitAnd 1200 | + BitOr 1201 | + BitXor 1202 | + Add 1203 | + Sub 1204 | + Eq 1205 | + Sized 1206 | + Copy 1207 | + Clone 1208 | + Debug 1209 | + From<[Self::Item; L]> 1210 | { 1211 | type Item: BitBlockItem; 1212 | const BIT_WIDTH: usize; 1213 | const ELEMENT_BIT_WIDTH: usize; 1214 | const LANES: usize; 1215 | const ZERO_ELEMENT: Self::Item; 1216 | const ONE_ELEMENT: Self::Item; 1217 | const MAX_ELEMENT: Self::Item; 1218 | const ZERO: Self; 1219 | const MAX: Self; 1220 | fn to_array(self) -> [Self::Item; L]; 1221 | fn and_inplace(&mut self, rhs: &Self); 1222 | fn or_inplace(&mut self, rhs: &Self); 1223 | fn xor_inplace(&mut self, rhs: &Self); 1224 | } 1225 | 1226 | macro_rules! impl_bitblock { 1227 | ($type: ty, $item_type: ty, $lanes: expr) => { 1228 | impl BitBlock<$lanes> for $type { 1229 | type Item = $item_type; 1230 | const BIT_WIDTH: usize = ($lanes * <$item_type>::BIT_WIDTH) as usize; 1231 | const ELEMENT_BIT_WIDTH: usize = <$item_type>::BIT_WIDTH; 1232 | const LANES: usize = $lanes; 1233 | const ZERO_ELEMENT: $item_type = <$item_type>::ZERO; 1234 | const ONE_ELEMENT: $item_type = <$item_type>::ONE; 1235 | const MAX_ELEMENT: $item_type = <$item_type>::MAX; 1236 | const ZERO: Self = <$type>::from_array([0; Self::LANES]); 1237 | const MAX: Self = <$type>::from_array([<$item_type>::MAX; Self::LANES]); 1238 | 1239 | #[inline] 1240 | fn to_array(self) -> [$item_type; $lanes] { 1241 | <$type>::to_array(self) 1242 | } 1243 | 1244 | #[inline] 1245 | fn and_inplace(&mut self, rhs: &Self) { 1246 | *self &= rhs; 1247 | } 1248 | 1249 | #[inline] 1250 | fn or_inplace(&mut self, rhs: &Self) { 1251 | *self |= rhs; 1252 | } 1253 | 1254 | #[inline] 1255 | fn xor_inplace(&mut self, rhs: &Self) { 1256 | *self ^= rhs; 1257 | } 1258 | } 1259 | }; 1260 | } 1261 | 1262 | impl_bitblock!(u8x16, u8, 16); 1263 | impl_bitblock!(u16x8, u16, 8); 1264 | impl_bitblock!(u32x4, u32, 4); 1265 | impl_bitblock!(u32x8, u32, 8); 1266 | impl_bitblock!(u64x2, u64, 2); 1267 | impl_bitblock!(u64x4, u64, 4); 1268 | impl_bitblock!(u64x8, u64, 8); 1269 | -------------------------------------------------------------------------------- /src/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | #[test] 4 | fn test_bit_vec_count_ones() { 5 | let mut bitvec = BitVec::ones(1000); 6 | assert_eq!(bitvec.count_ones(), 1000); 7 | assert_eq!(bitvec.count_ones_before(500), 500); 8 | bitvec.set(1500, true); 9 | assert_eq!(bitvec.count_ones(), 1001); 10 | assert_eq!(bitvec.count_ones_before(500), 500); 11 | } 12 | 13 | #[test] 14 | fn test_bitvec_set_raw_copy() { 15 | let v = vec![7]; 16 | let buf = v.as_ptr(); 17 | let mut bitvec = unsafe { BitVec::from_raw_copy(buf, 1, 64) }; 18 | let ptr = bitvec.storage.as_mut_ptr(); 19 | let buffer_len = bitvec.storage.len(); 20 | let mut bitvec2 = BitVec::zeros(1); 21 | unsafe { 22 | bitvec2.set_raw_copy(ptr, buffer_len, bitvec.nbits); 23 | } 24 | assert_eq!(v.len(), 1); // ensure v lives long enough 25 | assert_eq!(bitvec2.get(0), Some(true)); 26 | assert_eq!(bitvec2.get(1), Some(true)); 27 | assert_eq!(bitvec2.get(2), Some(true)); 28 | assert_eq!(bitvec2.get(3), Some(false)); 29 | assert_eq!(bitvec2.get(63), Some(false)); 30 | assert_eq!(bitvec2.get(64), None); 31 | } 32 | 33 | #[test] 34 | fn test_bitvec_set_raw() { 35 | let mut bitvec = BitVec::ones(1025); 36 | let ptr = bitvec.storage.as_mut_ptr(); 37 | let buffer_len = bitvec.storage.len(); 38 | let capacity = bitvec.storage.capacity(); 39 | let nbits = bitvec.nbits; 40 | let spilled = bitvec.storage.spilled(); 41 | let mut bitvec2 = BitVec::zeros(1); 42 | unsafe { 43 | std::mem::forget(bitvec); 44 | assert!(spilled); 45 | bitvec2.set_raw(ptr, buffer_len, capacity, nbits); 46 | assert_eq!(bitvec2.get(0), Some(true)); 47 | assert_eq!(bitvec2.get(1024), Some(true)); 48 | assert_eq!(bitvec2.get(1025), None); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/it/main.rs: -------------------------------------------------------------------------------- 1 | use core::ops::Not; 2 | 3 | use bitsvec::*; 4 | 5 | #[test] 6 | fn test_bit_vec_count_ones() { 7 | let mut bitvec = BitVec::ones(1000); 8 | assert_eq!(bitvec.count_ones(), 1000); 9 | assert_eq!(bitvec.count_ones_before(500), 500); 10 | bitvec.set(1500, true); 11 | assert_eq!(bitvec.count_ones(), 1001); 12 | assert_eq!(bitvec.count_ones_before(500), 500); 13 | } 14 | 15 | #[test] 16 | fn test_bit_vec_leading_zeros() { 17 | let mut bitvec = BitVec::zeros(1000); 18 | assert_eq!(bitvec.leading_zeros(), 1000); 19 | bitvec.set(499, true); 20 | assert_eq!(bitvec.leading_zeros(), 500); 21 | bitvec.set(599, true); 22 | assert_eq!(bitvec.leading_zeros(), 400); 23 | bitvec.set(699, true); 24 | assert_eq!(bitvec.leading_zeros(), 300); 25 | bitvec.set(799, true); 26 | assert_eq!(bitvec.leading_zeros(), 200); 27 | bitvec.set(899, true); 28 | assert_eq!(bitvec.leading_zeros(), 100); 29 | bitvec.set(999, true); 30 | assert_eq!(bitvec.leading_zeros(), 0); 31 | 32 | bitvec = BitVecSimd::zeros(10); 33 | bitvec.set(3, true); 34 | assert_eq!(bitvec.leading_zeros(), 6); 35 | } 36 | 37 | #[test] 38 | fn test_bit_vec_resize() { 39 | for i in (0..3333).filter(|x| x % 13 == 0) { 40 | for j in (0..6666).filter(|x| x % 37 == 0) { 41 | let mut b = BitVec::ones(i); 42 | b.resize(j, true); 43 | assert_eq!(b.len(), j); 44 | assert_eq!(b.count_ones(), j); 45 | } 46 | } 47 | 48 | let mut bitvec = BitVec::ones(3333); 49 | for i in 3333..6666 { 50 | bitvec.resize(i, false); 51 | assert_eq!(bitvec.len(), i); 52 | } 53 | for i in (0..3333).rev() { 54 | bitvec.resize(i, false); 55 | assert_eq!(bitvec.len(), i); 56 | assert_eq!(bitvec.count_ones(), i); 57 | } 58 | } 59 | 60 | #[test] 61 | fn test_bit_vec_shrink_to() { 62 | let mut bitvec = BitVec::ones(3333); 63 | bitvec.shrink_to(2222); 64 | assert_eq!(bitvec.len(), 2222); 65 | } 66 | 67 | #[test] 68 | #[should_panic] 69 | fn test_bit_vec_shrink_to_painc() { 70 | let mut bitvec = BitVec::ones(3333); 71 | bitvec.shrink_to(4444); 72 | } 73 | 74 | #[test] 75 | fn test_bit_vec_all_any() { 76 | let mut bitvec = BitVec::ones(1000); 77 | assert!(bitvec.all()); 78 | assert!(bitvec.any()); 79 | assert!(!bitvec.none()); 80 | bitvec.set(10, false); 81 | assert!(!bitvec.all()); 82 | assert!(bitvec.any()); 83 | assert!(!bitvec.none()); 84 | bitvec.set(1500, true); 85 | assert!(!bitvec.all()); 86 | assert!(bitvec.any()); 87 | assert!(!bitvec.none()); 88 | let mut bitvec = BitVec::zeros(1000); 89 | assert!(!bitvec.all()); 90 | assert!(!bitvec.any()); 91 | assert!(bitvec.none()); 92 | bitvec.set(1500, true); 93 | assert!(!bitvec.all()); 94 | assert!(bitvec.any()); 95 | assert!(!bitvec.none()); 96 | } 97 | 98 | #[test] 99 | fn test_bitvec_xor() { 100 | let mut bitvec = BitVec::ones(1000); 101 | let mut bitvec2 = BitVec::ones(1000); 102 | let bitvec3 = BitVec::zeros(1000); 103 | assert_eq!(bitvec.xor_cloned(&bitvec2), BitVec::zeros(1000)); 104 | assert_eq!(bitvec.xor_cloned(&bitvec3), BitVec::ones(1000)); 105 | assert_eq!(&bitvec ^ &bitvec2, BitVec::zeros(1000)); 106 | assert_eq!((&mut bitvec) ^ &bitvec2, BitVec::zeros(1000)); 107 | assert_eq!(&bitvec ^ (&mut bitvec2), BitVec::zeros(1000)); 108 | assert_eq!((&mut bitvec) ^ (&mut bitvec2), BitVec::zeros(1000)); 109 | assert_eq!(&bitvec ^ bitvec2.clone(), BitVec::zeros(1000)); 110 | assert_eq!((&mut bitvec) ^ bitvec2.clone(), BitVec::zeros(1000)); 111 | assert_eq!(bitvec.clone() ^ &bitvec2, BitVec::zeros(1000)); 112 | assert_eq!(bitvec.clone() ^ (&mut bitvec2), BitVec::zeros(1000)); 113 | assert_eq!(bitvec ^ bitvec2, BitVec::zeros(1000)); 114 | 115 | let mut bitvec = BitVec::ones(1000); 116 | let bitvec2 = BitVec::ones(1000); 117 | bitvec.set(400, false); 118 | let bitvec3 = bitvec ^ bitvec2; 119 | assert!(bitvec3[400]); 120 | assert_eq!(bitvec3.count_ones(), 1); 121 | 122 | let mut bitvec = BitVec::ones(1000); 123 | bitvec ^= BitVec::ones(1000); 124 | assert_eq!(bitvec.count_ones(), 0); 125 | bitvec ^= &BitVec::ones(1000); 126 | assert_eq!(bitvec.count_ones(), 1000); 127 | bitvec ^= &mut BitVec::ones(1000); 128 | assert_eq!(bitvec.count_ones(), 0); 129 | } 130 | 131 | #[test] 132 | fn test_bitvec_or() { 133 | let mut bitvec = BitVec::ones(1000); 134 | let mut bitvec2 = BitVec::ones(1000); 135 | let bitvec3 = BitVec::zeros(1000); 136 | assert_eq!(bitvec.or_cloned(&bitvec2), BitVec::ones(1000)); 137 | assert_eq!(bitvec.or_cloned(&bitvec3), BitVec::ones(1000)); 138 | assert_eq!(&bitvec | &bitvec2, BitVec::ones(1000)); 139 | assert_eq!((&mut bitvec) | &bitvec2, BitVec::ones(1000)); 140 | assert_eq!(&bitvec | (&mut bitvec2), BitVec::ones(1000)); 141 | assert_eq!((&mut bitvec) | (&mut bitvec2), BitVec::ones(1000)); 142 | assert_eq!(&bitvec | bitvec2.clone(), BitVec::ones(1000)); 143 | assert_eq!((&mut bitvec) | bitvec2.clone(), BitVec::ones(1000)); 144 | assert_eq!(bitvec.clone() | &bitvec2, BitVec::ones(1000)); 145 | assert_eq!(bitvec.clone() | (&mut bitvec2), BitVec::ones(1000)); 146 | assert_eq!(bitvec | bitvec2, BitVec::ones(1000)); 147 | let mut bitvec = BitVec::ones(1000); 148 | let bitvec2 = BitVec::ones(1000); 149 | bitvec.set(400, false); 150 | let bitvec3 = bitvec | bitvec2; 151 | assert!(bitvec3.get_unchecked(400)); 152 | assert_eq!(bitvec3.count_ones(), 1000); 153 | 154 | let mut bitvec = BitVec::ones(1000); 155 | bitvec |= BitVec::ones(1000); 156 | assert_eq!(bitvec.count_ones(), 1000); 157 | bitvec |= &BitVec::ones(1000); 158 | assert_eq!(bitvec.count_ones(), 1000); 159 | bitvec |= &mut BitVec::ones(1000); 160 | assert_eq!(bitvec.count_ones(), 1000); 161 | } 162 | 163 | #[test] 164 | fn test_bitvec_and() { 165 | let mut bitvec = BitVec::ones(1000); 166 | let mut bitvec2 = BitVec::ones(1000); 167 | let bitvec3 = BitVec::zeros(1000); 168 | assert_eq!(bitvec.and_cloned(&bitvec2), BitVec::ones(1000)); 169 | assert_eq!(bitvec.and_cloned(&bitvec3), BitVec::zeros(1000)); 170 | assert_eq!(&bitvec & &bitvec2, BitVec::ones(1000)); 171 | assert_eq!((&mut bitvec) & &bitvec2, BitVec::ones(1000)); 172 | assert_eq!(&bitvec & (&mut bitvec2), BitVec::ones(1000)); 173 | assert_eq!((&mut bitvec) & (&mut bitvec2), BitVec::ones(1000)); 174 | assert_eq!(&bitvec & bitvec2.clone(), BitVec::ones(1000)); 175 | assert_eq!((&mut bitvec) & bitvec2.clone(), BitVec::ones(1000)); 176 | assert_eq!(bitvec.clone() & &bitvec2, BitVec::ones(1000)); 177 | assert_eq!(bitvec.clone() & (&mut bitvec2), BitVec::ones(1000)); 178 | assert_eq!(bitvec & bitvec2, BitVec::ones(1000)); 179 | let mut bitvec = BitVec::ones(1000); 180 | let bitvec2 = BitVec::ones(1000); 181 | bitvec.set(400, false); 182 | let bitvec3 = bitvec & bitvec2; 183 | assert!(!bitvec3.get_unchecked(400)); 184 | assert_eq!(bitvec3.count_ones(), 1000 - 1); 185 | 186 | let mut bitvec = BitVec::ones(1000); 187 | bitvec &= BitVec::ones(1000); 188 | assert_eq!(bitvec.count_ones(), 1000); 189 | bitvec &= &BitVec::ones(1000); 190 | assert_eq!(bitvec.count_ones(), 1000); 191 | bitvec &= &mut BitVec::ones(1000); 192 | assert_eq!(bitvec.count_ones(), 1000); 193 | } 194 | 195 | #[test] 196 | fn test_bitvec_not() { 197 | let mut bitvec = BitVec::ones(1000); 198 | assert_eq!(bitvec, BitVec::ones(1000)); 199 | assert_eq!((&bitvec).not(), BitVec::zeros(1000)); 200 | assert_eq!((&mut bitvec).not(), BitVec::zeros(1000)); 201 | assert_eq!(bitvec.not(), BitVec::zeros(1000)); 202 | } 203 | 204 | #[test] 205 | #[allow(clippy::op_ref)] 206 | fn test_bitvec_eq() { 207 | let mut bitvec = BitVec::ones(1000); 208 | assert_eq!(bitvec, BitVec::ones(1000)); 209 | assert_ne!(bitvec, BitVec::zeros(1000)); 210 | bitvec.set(50, false); 211 | assert_ne!(bitvec, BitVec::ones(1000)); 212 | bitvec.set(50, true); 213 | assert_eq!(bitvec, BitVec::ones(1000)); 214 | 215 | assert!(&bitvec == BitVec::ones(1000)); 216 | assert!(&bitvec == &BitVec::ones(1000)); 217 | assert!(&bitvec == (&mut BitVec::ones(1000))); 218 | assert!((&mut bitvec) == BitVec::ones(1000)); 219 | assert!((&mut bitvec) == &BitVec::ones(1000)); 220 | assert!((&mut bitvec) == (&mut BitVec::ones(1000))); 221 | assert!(bitvec == BitVec::ones(1000)); 222 | assert!(bitvec == &BitVec::ones(1000)); 223 | assert!(bitvec == (&mut BitVec::ones(1000))); 224 | } 225 | 226 | #[test] 227 | fn test_bitvec_creation() { 228 | let mut bitvec = BitVec::zeros(1000); 229 | for i in 0..1500 { 230 | if i < 1000 { 231 | assert_eq!(bitvec.get(i), Some(false)); 232 | } else { 233 | assert_eq!(bitvec.get(i), None); 234 | } 235 | } 236 | bitvec.set(900, true); 237 | for i in 0..1500 { 238 | if i < 1000 { 239 | if i == 900 { 240 | assert_eq!(bitvec.get(i), Some(true)); 241 | } else { 242 | assert_eq!(bitvec.get(i), Some(false)); 243 | } 244 | } else { 245 | assert_eq!(bitvec.get(i), None); 246 | } 247 | } 248 | bitvec.set(1300, true); 249 | for i in 0..1500 { 250 | if i <= 1300 { 251 | if i == 900 || i == 1300 { 252 | assert_eq!(bitvec.get(i), Some(true)); 253 | } else { 254 | assert_eq!(bitvec.get(i), Some(false)); 255 | } 256 | } else { 257 | assert_eq!(bitvec.get(i), None); 258 | } 259 | } 260 | 261 | let bitvec = BitVec::from_slice_copy(&[7], 2); 262 | assert_eq!(bitvec.get(0), Some(true)); 263 | assert_eq!(bitvec.get(1), Some(true)); 264 | assert_eq!(bitvec.get(2), None); 265 | 266 | let bitvec = BitVec::from_slice_copy(&[7], 64); 267 | assert_eq!(bitvec.get(0), Some(true)); 268 | assert_eq!(bitvec.get(1), Some(true)); 269 | assert_eq!(bitvec.get(2), Some(true)); 270 | assert_eq!(bitvec.get(3), Some(false)); 271 | assert_eq!(bitvec.get(63), Some(false)); 272 | assert_eq!(bitvec.get(64), None); 273 | 274 | let v = vec![7]; 275 | let buf = v.as_ptr(); 276 | let bitvec = unsafe { BitVec::from_raw_copy(buf, 1, 2) }; 277 | assert_eq!(v.len(), 1); // ensure v lives long enough 278 | assert_eq!(bitvec.get(0), Some(true)); 279 | assert_eq!(bitvec.get(1), Some(true)); 280 | assert_eq!(bitvec.get(2), None); 281 | 282 | let v = vec![7]; 283 | let buf = v.as_ptr(); 284 | let bitvec = unsafe { BitVec::from_raw_copy(buf, 1, 64) }; 285 | assert_eq!(v.len(), 1); // ensure v lives long enough 286 | assert_eq!(bitvec.get(0), Some(true)); 287 | assert_eq!(bitvec.get(1), Some(true)); 288 | assert_eq!(bitvec.get(2), Some(true)); 289 | assert_eq!(bitvec.get(3), Some(false)); 290 | assert_eq!(bitvec.get(63), Some(false)); 291 | assert_eq!(bitvec.get(64), None); 292 | } 293 | 294 | #[test] 295 | fn test_bitvec_set_all() { 296 | let mut bitvec = BitVec::zeros(1000); 297 | bitvec.set_all(true); 298 | for i in 0..1500 { 299 | if i < 1000 { 300 | assert_eq!(bitvec.get(i), Some(true)); 301 | } else { 302 | assert_eq!(bitvec.get(i), None); 303 | } 304 | } 305 | bitvec.set_all(false); 306 | for i in 0..1500 { 307 | if i < 1000 { 308 | assert_eq!(bitvec.get(i), Some(false)); 309 | } else { 310 | assert_eq!(bitvec.get(i), None); 311 | } 312 | } 313 | } 314 | 315 | #[test] 316 | fn test_bitvec_display() { 317 | let bitvec = BitVec::ones(5); 318 | assert_eq!(format!("{}", bitvec), "11111"); 319 | } 320 | --------------------------------------------------------------------------------