Skip to content

Commit 8a55b7e

Browse files
author
Ιωάννης Νικολαΐδης
committed
Δημιουργία απαραιτήτων αρχείων
0 parents  commit 8a55b7e

File tree

5 files changed

+1443
-0
lines changed

5 files changed

+1443
-0
lines changed

Cargo.toml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[package]
2+
name = "lindel"
3+
version = "0.1.0"
4+
authors = ["froderick <[email protected]>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[package.metadata.docs.rs]
10+
all-features = true
11+
12+
[dependencies]
13+
num = {version = "*"}
14+
num-traits = {version = "*"}
15+
nalgebra = {version = "*", optional = true}
16+
17+
[dev-dependencies]
18+
rand = "*"
19+
20+
[dependencies.morton-encoding]
21+
version = "^2"
22+
default-features = false
23+
24+
[features]
25+
default = ["std"]
26+
std = []
27+
nalg = ["nalgebra"]

src/compact_encoding.rs

+213
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
//! Implementation of [Compact Hilbert Indices](https://dl.acm.org/doi/10.1109/CISIS.2007.16) by
2+
//! Chris Hamilton, and of Compact Z-indices by the crate maintainer.
3+
4+
/// Right rotation of x by b bits out of n.
5+
fn rotate_right(x: usize, b: u32, n: u32) -> usize {
6+
let l = x & ((1 << b) - 1);
7+
let r = x >> b;
8+
(l << (n - b)) | r
9+
}
10+
11+
/// Left rotation of x by b bits out of n.
12+
fn rotate_left(x: usize, b: u32, n: u32) -> usize {
13+
rotate_right(x, n - b, n)
14+
}
15+
16+
/// Binary reflected Gray code.
17+
fn gray_code(i: usize) -> usize {
18+
i ^ (i >> 1)
19+
}
20+
21+
/// e(i), the entry point for the ith sub-hypercube.
22+
fn entry_point(i: usize) -> usize {
23+
if i == 0 {
24+
0
25+
} else {
26+
gray_code((i - 1) & !1)
27+
}
28+
}
29+
30+
/// g(i), the inter sub-hypercube direction.
31+
fn inter_direction(i: usize) -> u32 {
32+
// g(i) counts the trailing set bits in i
33+
(!i).trailing_zeros()
34+
}
35+
36+
/// d(i), the intra sub-hypercube direction.
37+
fn intra_direction(i: usize) -> u32 {
38+
if i & 1 != 0 {
39+
inter_direction(i)
40+
} else if i > 0 {
41+
inter_direction(i - 1)
42+
} else {
43+
0
44+
}
45+
}
46+
47+
/// T transformation inverse
48+
fn t_inverse(dims: u32, e: usize, d: u32, a: usize) -> usize {
49+
rotate_left(a, d, dims) ^ e
50+
}
51+
52+
/// GrayCodeRankInverse
53+
fn gray_code_rank_inverse(
54+
dims: u32,
55+
mu: usize,
56+
pi: usize,
57+
r: usize,
58+
free_bits: u32,
59+
) -> (usize, usize) {
60+
// The inverse rank of r
61+
let mut i = 0;
62+
// gray_code(i)
63+
let mut g = 0;
64+
65+
let mut j = free_bits - 1;
66+
for k in (0..dims).rev() {
67+
if mu & (1 << k) == 0 {
68+
g |= pi & (1 << k);
69+
i |= (g ^ (i >> 1)) & (1 << k);
70+
} else {
71+
i |= ((r >> j) & 1) << k;
72+
g |= (i ^ (i >> 1)) & (1 << k);
73+
j = j.wrapping_sub(1);
74+
}
75+
}
76+
77+
(i, g)
78+
}
79+
80+
/// ExtractMask.
81+
fn extract_mask(bits: &[u32], i: u32) -> (usize, u32) {
82+
// The mask
83+
let mut mu = 0;
84+
// popcount(mu)
85+
let mut free_bits = 0;
86+
87+
let dims = bits.len();
88+
for j in (0..dims).rev() {
89+
mu <<= 1;
90+
if bits[j] > i {
91+
mu |= 1;
92+
free_bits += 1;
93+
}
94+
}
95+
96+
(mu, free_bits)
97+
}
98+
99+
/// Compute the corresponding point for a Hilbert index (CompactHilbertIndexInverse).
100+
pub fn from_compact_hilbert_index(index: usize, bits: &[u32], point: &mut [usize]) {
101+
let dims = bits.len() as u32;
102+
let max = *bits.iter().max().unwrap();
103+
let sum: u32 = bits.iter().sum();
104+
105+
let mut e = 0;
106+
let mut k = 0;
107+
108+
// Next direction; we use d instead of d + 1 everywhere
109+
let mut d = 1;
110+
111+
for x in point.iter_mut() {
112+
*x = 0;
113+
}
114+
115+
for i in (0..max).rev() {
116+
let (mut mu, free_bits) = extract_mask(bits, i);
117+
mu = rotate_right(mu, d, dims);
118+
119+
let pi = rotate_right(e, d, dims) & !mu;
120+
121+
let r = (index >> (sum - k - free_bits)) & ((1 << free_bits) - 1);
122+
123+
k += free_bits;
124+
125+
let (w, mut l) = gray_code_rank_inverse(dims, mu, pi, r, free_bits);
126+
l = t_inverse(dims, e, d, l);
127+
128+
for x in point.iter_mut() {
129+
*x |= (l & 1) << i;
130+
l >>= 1;
131+
}
132+
133+
e ^= rotate_right(entry_point(w), d, dims);
134+
d = (d + intra_direction(w) + 1) % dims;
135+
}
136+
}
137+
138+
/// T transformation
139+
fn t(dims: u32, e: usize, d: u32, b: usize) -> usize {
140+
rotate_right(b ^ e, d, dims)
141+
}
142+
143+
/// GrayCodeInverse
144+
fn gray_code_inverse(mut g: usize) -> usize {
145+
let mut i = 0;
146+
147+
while g != 0 {
148+
i ^= g;
149+
g >>= 1;
150+
}
151+
152+
i
153+
}
154+
155+
/// GrayCodeRank
156+
fn gray_code_rank(dims: u32, mu: usize, i: usize) -> usize {
157+
let mut r = 0;
158+
159+
for k in (0..dims).rev() {
160+
if mu & (1 << k) != 0 {
161+
r <<= 1;
162+
r |= (i >> k) & 1;
163+
}
164+
}
165+
166+
r
167+
}
168+
169+
/// CompactHilbertIndex
170+
pub fn compact_hilbert_index(bits: &[u32], point: &[usize]) -> usize {
171+
let dims = bits.len() as u32;
172+
let max = *bits.iter().max().unwrap();
173+
174+
let mut h = 0;
175+
let mut e = 0;
176+
177+
// Next direction; we use d instead of d + 1 everywhere
178+
let mut d = 1;
179+
180+
for i in (0..max).rev() {
181+
let (mut mu, free_bits) = extract_mask(bits, i);
182+
mu = rotate_right(mu, d, dims);
183+
184+
let mut l = 0;
185+
for x in point.iter().rev() {
186+
l <<= 1;
187+
l |= (x >> i) & 1;
188+
}
189+
l = t(dims, e, d, l);
190+
191+
let w = gray_code_inverse(l);
192+
let r = gray_code_rank(dims, mu, w);
193+
194+
e ^= rotate_right(entry_point(w), d, dims);
195+
d = (d + intra_direction(w) + 1) % dims;
196+
h = (h << free_bits) | r;
197+
}
198+
199+
h
200+
}
201+
202+
203+
204+
/*fn returns_closure (xs: &[u8]) -> impl Fn(u32) -> u32 {
205+
let sum: u32 = xs.iter().map(|&x| x as u32).sum();
206+
move |a| a*sum
207+
}
208+
209+
fn main() {
210+
println!("Hello, world!");
211+
let fnoo = returns_closure(&[1, 2, 3, 4, 5, 6]);
212+
dbg!(fnoo(15));
213+
}*/

0 commit comments

Comments
 (0)