Initial commit.
This commit is contained in:
commit
0e372df756
4 changed files with 343 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/target
|
||||||
175
Cargo.lock
generated
Normal file
175
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitexperimentation"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"quickcheck",
|
||||||
|
"quickcheck_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.158"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.86"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quickcheck"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
|
||||||
|
dependencies = [
|
||||||
|
"env_logger",
|
||||||
|
"log",
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quickcheck_macros"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b22a693222d716a9587786f37ac3f6b4faedb5b80c23914e7303ff5a1d8016e9"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
[package]
|
||||||
|
name = "bitexperimentation"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
quickcheck = "1"
|
||||||
|
quickcheck_macros = "1"
|
||||||
156
src/main.rs
Normal file
156
src/main.rs
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn L(k: u8) -> u64 {
|
||||||
|
let mut s = 0;
|
||||||
|
for i in 0..64u8.div_ceil(k) {
|
||||||
|
s |= 1 << (i * k);
|
||||||
|
}
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn H(k: u8) -> u64 {
|
||||||
|
L(k) << (k - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sideways_addition(x: u64) -> u64 {
|
||||||
|
let s = x - ((x & 0xAAAAAAAAAAAAAAAA) >> 1);
|
||||||
|
// 0xA = 0b1010
|
||||||
|
let s = (s & 0x3333333333333333) + ((s >> 2) & 0x3333333333333333);
|
||||||
|
// 0x3 = 0b0011
|
||||||
|
let s = (s + (s >> 4)) & 0x0F0F0F0F0F0F0F0F;
|
||||||
|
u64::wrapping_mul(s, L(8)) >> 56
|
||||||
|
}
|
||||||
|
|
||||||
|
fn less_equal_k_signed(x: u64, y: u64, k: u8) -> u64 {
|
||||||
|
let s = (y | H(k)) - (x & !H(k));
|
||||||
|
let s = s ^ x ^ y;
|
||||||
|
let s = s | (x & !y);
|
||||||
|
let s = s & !(!x & y);
|
||||||
|
s & H(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn less_equal_k_unsigned(x: u64, y: u64, k: u8) -> u64 {
|
||||||
|
let s = (y | H(k)) - (x & !H(k));
|
||||||
|
let s = s | x ^ y;
|
||||||
|
let s = s ^ (x & !y);
|
||||||
|
s & H(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grater_than_0_k_unsigned(x: u64, k: u8) -> u64 {
|
||||||
|
(((x | H(k)) - L(k)) | x) & H(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select64(x: u64, r: u64) -> u64 {
|
||||||
|
// Same as in sideways addition
|
||||||
|
let s = x - ((x & 0xAAAAAAAAAAAAAAAA) >> 1);
|
||||||
|
// 0xA = 0b1010
|
||||||
|
let s = (s & 0x3333333333333333) + ((s >> 2) & 0x3333333333333333);
|
||||||
|
// 0x3 = 0b0011
|
||||||
|
let s = ((s + (s >> 4)) & 0x0F0F0F0F0F0F0F0F).wrapping_mul(L(8));
|
||||||
|
|
||||||
|
// Select byte
|
||||||
|
// b: byte index << 3
|
||||||
|
let b =
|
||||||
|
(less_equal_k_signed(s, r.wrapping_mul(L(8)), 8) >> 7).wrapping_mul(L(8)) >> 53 & (!0x7);
|
||||||
|
if b == 64 {
|
||||||
|
return 72;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract selected byte
|
||||||
|
let l = r - (((s << 8) >> b) & 0xFF);
|
||||||
|
|
||||||
|
// select index in byte
|
||||||
|
let s = (grater_than_0_k_unsigned((x >> b & 0xFF).wrapping_mul(L(8)) & 0x8040201008040201, 8)
|
||||||
|
>> 7)
|
||||||
|
.wrapping_mul(L(8));
|
||||||
|
|
||||||
|
b + ((less_equal_k_signed(s, l.wrapping_mul(L(8)), 8) >> 7).wrapping_mul(L(8)) >> 56)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trivial_select(data: u64, count: u8) -> u8 {
|
||||||
|
let mut l = 0;
|
||||||
|
let mut r = 63;
|
||||||
|
|
||||||
|
while l < r {
|
||||||
|
let m = (l + r) / 2;
|
||||||
|
|
||||||
|
let shift = 64 - m - 1;
|
||||||
|
let shifted = data << shift;
|
||||||
|
|
||||||
|
let local_count = shifted.count_ones();
|
||||||
|
|
||||||
|
// dbg!(l, r, m, shift, local_count, r);
|
||||||
|
|
||||||
|
if local_count < count as u32 {
|
||||||
|
l = m + 1;
|
||||||
|
} else {
|
||||||
|
r = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
dbg!(select64(3, 1));
|
||||||
|
dbg!(trivial_select(3, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use quickcheck_macros::quickcheck;
|
||||||
|
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
#[quickcheck]
|
||||||
|
fn qc_test_sideways_addition(x: u64) -> bool {
|
||||||
|
x.count_ones() as u64 == sideways_addition(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[quickcheck]
|
||||||
|
fn qc_less_equal_8_signed(x: u64, y: u64) -> bool {
|
||||||
|
let s = less_equal_k_signed(x, y, 8).to_be_bytes();
|
||||||
|
|
||||||
|
s.iter()
|
||||||
|
.zip(x.to_be_bytes().iter().zip(y.to_be_bytes().iter()))
|
||||||
|
.all(|(s, (&x, &y))| match s {
|
||||||
|
0x00 => (x as i8) > (y as i8),
|
||||||
|
0x80 => (x as i8) <= (y as i8),
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[quickcheck]
|
||||||
|
fn qc_less_equal_k_unsigned(x: u64, y: u64) -> bool {
|
||||||
|
let s = less_equal_k_unsigned(x, y, 8).to_be_bytes();
|
||||||
|
|
||||||
|
s.iter()
|
||||||
|
.zip(x.to_be_bytes().iter().zip(y.to_be_bytes().iter()))
|
||||||
|
.all(|(s, (&x, &y))| match s {
|
||||||
|
0x00 => x > y,
|
||||||
|
0x80 => x <= y,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[quickcheck]
|
||||||
|
fn qc_grater_than_0_k_unsigned(x: u64) -> bool {
|
||||||
|
let s = grater_than_0_k_unsigned(x, 8).to_be_bytes();
|
||||||
|
s.iter().zip(x.to_be_bytes().iter()).all(|(a, b)| match a {
|
||||||
|
0x00 => b == &0,
|
||||||
|
0x80 => b > &0,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[quickcheck]
|
||||||
|
fn qc_select64(x: u64, r: u8) -> bool {
|
||||||
|
let r = r.clamp(1, 64);
|
||||||
|
let s = select64(x, r as u64);
|
||||||
|
|
||||||
|
if x.count_ones() <= r as u32 {
|
||||||
|
s == 72
|
||||||
|
} else {
|
||||||
|
trivial_select(x, r + 1) as u64 == s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue