1
+ use itertools:: Itertools ;
2
+ use num_traits:: { CheckedSub , Float , PrimInt , ToPrimitive } ;
1
3
use std:: fmt:: { Display , Formatter } ;
2
4
use std:: mem:: size_of;
3
5
4
- use num_traits:: { CheckedSub , Float , PrimInt , ToPrimitive } ;
5
-
6
6
const SAMPLE_SIZE : usize = 32 ;
7
7
8
8
#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
@@ -46,18 +46,16 @@ pub fn encode_single<F: ALPFloat>(value: F, exponents: Exponents) -> Result<F::A
46
46
47
47
/// Decodes an integer value to its matching floating point representation given the same exponents.
48
48
pub fn decode_single < F : ALPFloat > ( encoded : F :: ALPInt , exponents : Exponents ) -> F {
49
- F :: from_int ( encoded) * F :: F10 [ exponents. f as usize ] * F :: IF10 [ exponents . e as usize ]
49
+ F :: decode_single ( encoded, exponents)
50
50
}
51
51
52
52
/// Encodes a single value, it might not round-trip back it its original value
53
53
/// # Safety
54
54
///
55
55
/// The returned value may not decode back to the original value.
56
56
#[ inline( always) ]
57
- pub unsafe fn encode_single_unchecked < F : ALPFloat > ( value : F , exponents : Exponents ) -> F :: ALPInt {
58
- ( value * F :: F10 [ exponents. e as usize ] * F :: IF10 [ exponents. f as usize ] )
59
- . fast_round ( )
60
- . as_int ( )
57
+ pub fn encode_single_unchecked < F : ALPFloat > ( value : F , exponents : Exponents ) -> F :: ALPInt {
58
+ F :: encode_single_unchecked ( value, exponents)
61
59
}
62
60
63
61
pub trait ALPFloat : private:: Sealed + Float + Display + ' static {
@@ -81,16 +79,18 @@ pub trait ALPFloat: private::Sealed + Float + Display + 'static {
81
79
/// Convert from the integer type back to the float type using `as`.
82
80
fn from_int ( n : Self :: ALPInt ) -> Self ;
83
81
82
+ fn is_eq ( self , other : Self ) -> bool ;
83
+
84
84
fn find_best_exponents ( values : & [ Self ] ) -> Exponents {
85
85
let mut best_exp = Exponents { e : 0 , f : 0 } ;
86
86
let mut best_nbytes: usize = usize:: MAX ;
87
87
88
- let sample: Option < Vec < Self > > = ( values. len ( ) > SAMPLE_SIZE ) . then ( || {
88
+ let sample = ( values. len ( ) > SAMPLE_SIZE ) . then ( || {
89
89
values
90
90
. iter ( )
91
91
. step_by ( values. len ( ) / SAMPLE_SIZE )
92
92
. cloned ( )
93
- . collect ( )
93
+ . collect_vec ( )
94
94
} ) ;
95
95
96
96
for e in ( 0 ..Self :: MAX_EXPONENT ) . rev ( ) {
@@ -115,12 +115,10 @@ pub trait ALPFloat: private::Sealed + Float + Display + 'static {
115
115
116
116
#[ inline]
117
117
fn estimate_encoded_size ( encoded : & [ Self :: ALPInt ] , patches : & [ Self ] ) -> usize {
118
- let minmax = encoded. iter ( ) . fold ( None , |minmax, next| {
119
- let ( min, max) = minmax. unwrap_or ( ( next, next) ) ;
120
-
121
- Some ( ( min. min ( next) , max. max ( next) ) )
122
- } ) ;
123
- let bits_per_encoded = minmax
118
+ let bits_per_encoded = encoded
119
+ . iter ( )
120
+ . minmax ( )
121
+ . into_option ( )
124
122
// estimating bits per encoded value assuming frame-of-reference + bitpacking-without-patches
125
123
. and_then ( |( min, max) | max. checked_sub ( min) )
126
124
. and_then ( |range_size : <Self as ALPFloat >:: ALPInt | range_size. to_u64 ( ) )
@@ -168,11 +166,23 @@ pub trait ALPFloat: private::Sealed + Float + Display + 'static {
168
166
( exp, encoded_output, patch_indices, patch_values)
169
167
}
170
168
169
+ fn encode_above ( value : Self , exponents : Exponents ) -> Self :: ALPInt {
170
+ ( value * Self :: F10 [ exponents. e as usize ] * Self :: IF10 [ exponents. f as usize ] )
171
+ . ceil ( )
172
+ . as_int ( )
173
+ }
174
+
175
+ fn encode_below ( value : Self , exponents : Exponents ) -> Self :: ALPInt {
176
+ ( value * Self :: F10 [ exponents. e as usize ] * Self :: IF10 [ exponents. f as usize ] )
177
+ . floor ( )
178
+ . as_int ( )
179
+ }
180
+
171
181
#[ inline]
172
182
fn encode_single ( value : Self , exponents : Exponents ) -> Result < Self :: ALPInt , Self > {
173
- let encoded = unsafe { Self :: encode_single_unchecked ( value, exponents) } ;
183
+ let encoded = Self :: encode_single_unchecked ( value, exponents) ;
174
184
let decoded = Self :: decode_single ( encoded, exponents) ;
175
- if decoded == value {
185
+ if decoded. is_eq ( value) {
176
186
return Ok ( encoded) ;
177
187
}
178
188
Err ( value)
@@ -183,11 +193,9 @@ pub trait ALPFloat: private::Sealed + Float + Display + 'static {
183
193
Self :: from_int ( encoded) * Self :: F10 [ exponents. f as usize ] * Self :: IF10 [ exponents. e as usize ]
184
194
}
185
195
186
- /// # Safety
187
- ///
188
- /// The returned value may not decode back to the original value.
196
+ /// Encodes a single value, it might not round-trip back it its original value
189
197
#[ inline( always) ]
190
- unsafe fn encode_single_unchecked ( value : Self , exponents : Exponents ) -> Self :: ALPInt {
198
+ fn encode_single_unchecked ( value : Self , exponents : Exponents ) -> Self :: ALPInt {
191
199
( value * Self :: F10 [ exponents. e as usize ] * Self :: IF10 [ exponents. f as usize ] )
192
200
. fast_round ( )
193
201
. as_int ( )
@@ -209,10 +217,10 @@ fn encode_chunk_unchecked<T: ALPFloat>(
209
217
210
218
// encode the chunk, counting the number of patches
211
219
let mut chunk_patch_count = 0 ;
212
- encoded_output. extend ( chunk. iter ( ) . map ( |v| {
213
- let encoded = unsafe { T :: encode_single_unchecked ( * v, exp) } ;
220
+ encoded_output. extend ( chunk. iter ( ) . map ( |& v| {
221
+ let encoded = encode_single_unchecked ( v, exp) ;
214
222
let decoded = T :: decode_single ( encoded, exp) ;
215
- let neq = ( decoded != * v) as usize ;
223
+ let neq = !decoded . is_eq ( v) as usize ;
216
224
chunk_patch_count += neq;
217
225
encoded
218
226
} ) ) ;
@@ -234,7 +242,7 @@ fn encode_chunk_unchecked<T: ALPFloat>(
234
242
// write() is only safe to call more than once because the values are primitive (i.e., Drop is a no-op)
235
243
patch_indices_mut[ chunk_patch_index] . write ( i as u64 ) ;
236
244
patch_values_mut[ chunk_patch_index] . write ( chunk[ i - num_prev_encoded] ) ;
237
- chunk_patch_index += ( decoded != chunk[ i - num_prev_encoded] ) as usize ;
245
+ chunk_patch_index += !decoded . is_eq ( chunk[ i - num_prev_encoded] ) as usize ;
238
246
}
239
247
assert_eq ! ( chunk_patch_index, chunk_patch_count) ;
240
248
unsafe {
@@ -309,6 +317,10 @@ impl ALPFloat for f32 {
309
317
fn from_int ( n : Self :: ALPInt ) -> Self {
310
318
n as _
311
319
}
320
+
321
+ fn is_eq ( self , other : Self ) -> bool {
322
+ self . to_bits ( ) == other. to_bits ( )
323
+ }
312
324
}
313
325
314
326
impl ALPFloat for f64 {
@@ -380,4 +392,22 @@ impl ALPFloat for f64 {
380
392
fn from_int ( n : Self :: ALPInt ) -> Self {
381
393
n as _
382
394
}
395
+
396
+ fn is_eq ( self , other : Self ) -> bool {
397
+ self . to_bits ( ) == other. to_bits ( )
398
+ }
399
+ }
400
+
401
+ #[ cfg( test) ]
402
+ mod tests {
403
+ use super :: * ;
404
+
405
+ #[ test]
406
+ fn non_finite_numbers ( ) {
407
+ let original = vec ! [ 0.0f32 , -0.0 , f32 :: NAN , f32 :: NEG_INFINITY , f32 :: INFINITY ] ;
408
+ let ( _, encoded, patch_idx, _) = encode ( & original, None ) ;
409
+
410
+ assert_eq ! ( patch_idx, vec![ 1 , 2 , 3 , 4 ] ) ;
411
+ assert_eq ! ( encoded, vec![ 0 , 0 , 0 , 0 , 0 ] ) ;
412
+ }
383
413
}
0 commit comments