1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
pub use stream::{Writer, Reader};
use std::cmp::min;
pub enum DoubleStreamStateLeadTrail {
Initial,
Following {
value: u64,
leading_zeros: u8,
meaningful_count: u8,
}
}
pub struct DoubleStreamLeadTrail {
state: DoubleStreamStateLeadTrail
}
impl DoubleStreamLeadTrail {
pub fn new() -> Self {
DoubleStreamLeadTrail {
state: DoubleStreamStateLeadTrail::Initial
}
}
pub fn push(&mut self, number: f64, writer: &mut Writer) {
let number_as_bits = number.to_bits();
self.state = match self.state {
DoubleStreamStateLeadTrail::Initial => {
writer.write(number_as_bits, 64);
DoubleStreamStateLeadTrail::Following {
value: number_as_bits,
leading_zeros: 64,
meaningful_count: 0
}
},
DoubleStreamStateLeadTrail::Following { value: previous, leading_zeros: prev_lz, meaningful_count: prev_meaningful } => {
let xored = previous ^ number_as_bits;
match xored {
0 => {
writer.write(0, 1);
DoubleStreamStateLeadTrail::Following {
value: number_as_bits,
leading_zeros: prev_lz,
meaningful_count: prev_meaningful
}
},
_ => {
let lz = min(xored.leading_zeros() as u8, 31);
let tz = xored.trailing_zeros() as u8;
assert!(lz < 32);
let prev_tz = 64 - prev_lz - prev_meaningful;
if lz >= prev_lz && tz >= prev_tz {
let meaningful_bits = xored >> prev_tz;
let meaningful_bit_count = 64 - prev_tz - prev_lz;
writer.write(0b10, 2);
writer.write(meaningful_bits, meaningful_bit_count as u8);
DoubleStreamStateLeadTrail::Following {
value: number_as_bits,
leading_zeros: prev_lz,
meaningful_count: prev_meaningful
}
} else {
let meaningful_bits = xored >> tz;
let meaningful_bit_count = 64 - tz - lz;
assert!(meaningful_bit_count <= 64);
writer.write(0b11, 2);
writer.write(lz as u64, 5);
writer.write((meaningful_bit_count - 1) as u64, 6);
writer.write(meaningful_bits, meaningful_bit_count as u8);
DoubleStreamStateLeadTrail::Following {
value: number_as_bits,
leading_zeros: lz,
meaningful_count: meaningful_bit_count
}
}
}
}
}
};
}
}