1use itertools::Itertools;
5use vortex_array::ArrayRef;
6use vortex_array::ArrayView;
7use vortex_array::ExecutionCtx;
8use vortex_array::IntoArray;
9use vortex_array::arrays::Primitive;
10use vortex_array::arrays::PrimitiveArray;
11use vortex_array::dtype::PType;
12use vortex_array::patches::Patches;
13use vortex_array::validity::Validity;
14use vortex_buffer::Buffer;
15use vortex_buffer::BufferMut;
16use vortex_error::VortexResult;
17use vortex_error::vortex_bail;
18use vortex_mask::Mask;
19
20use crate::ALP;
21use crate::Exponents;
22use crate::alp::ALPArray;
23use crate::alp::ALPFloat;
24
25#[macro_export]
26macro_rules! match_each_alp_float_ptype {
27 ($self:expr, | $enc:ident | $body:block) => {{
28 use vortex_array::dtype::PType;
29 use vortex_error::vortex_panic;
30 let ptype = $self;
31 match ptype {
32 PType::F32 => {
33 type $enc = f32;
34 $body
35 }
36 PType::F64 => {
37 type $enc = f64;
38 $body
39 }
40 _ => vortex_panic!("ALP can only encode f32 and f64, got {}", ptype),
41 }
42 }};
43}
44
45pub fn alp_encode(
46 parray: ArrayView<'_, Primitive>,
47 exponents: Option<Exponents>,
48 ctx: &mut ExecutionCtx,
49) -> VortexResult<ALPArray> {
50 let (exponents, encoded, patches) = match parray.ptype() {
51 PType::F32 => alp_encode_components_typed::<f32>(parray, exponents, ctx)?,
52 PType::F64 => alp_encode_components_typed::<f64>(parray, exponents, ctx)?,
53 _ => vortex_bail!("ALP can only encode f32 and f64"),
54 };
55
56 unsafe { Ok(ALP::new_unchecked(encoded, exponents, patches)) }
58}
59
60#[expect(
61 clippy::cast_possible_truncation,
62 reason = "u64 index cast to usize is safe for reasonable array sizes"
63)]
64fn alp_encode_components_typed<T>(
65 values: ArrayView<'_, Primitive>,
66 exponents: Option<Exponents>,
67 ctx: &mut ExecutionCtx,
68) -> VortexResult<(Exponents, ArrayRef, Option<Patches>)>
69where
70 T: ALPFloat,
71{
72 let values_slice = values.as_slice::<T>();
73
74 let (exponents, encoded, exceptional_positions, exceptional_values, mut chunk_offsets) =
75 T::encode(values_slice, exponents);
76
77 let encoded_array = PrimitiveArray::new(encoded, values.validity()?).into_array();
78
79 let validity = values
80 .array()
81 .validity()?
82 .to_mask(values.array().len(), ctx)?;
83 let (valid_exceptional_positions, valid_exceptional_values): (Buffer<u64>, Buffer<T>) =
86 match validity {
87 Mask::AllTrue(_) => (exceptional_positions, exceptional_values),
88 Mask::AllFalse(_) => {
89 (Buffer::empty(), Buffer::empty())
91 }
92 Mask::Values(is_valid) => {
93 let (pos, vals): (BufferMut<u64>, BufferMut<T>) = exceptional_positions
94 .into_iter()
95 .zip_eq(exceptional_values)
96 .filter(|(index, _)| {
97 let is_valid = is_valid.value(*index as usize);
98 if !is_valid {
99 let patch_chunk = *index as usize / 1024;
100 for chunk_idx in (patch_chunk + 1)..chunk_offsets.len() {
101 chunk_offsets[chunk_idx] -= 1;
102 }
103 }
104 is_valid
105 })
106 .unzip();
107 (pos.freeze(), vals.freeze())
108 }
109 };
110 let patches = if valid_exceptional_positions.is_empty() {
111 None
112 } else {
113 let patches_validity = if values.dtype().is_nullable() {
114 Validity::AllValid
115 } else {
116 Validity::NonNullable
117 };
118 let valid_exceptional_values =
119 PrimitiveArray::new(valid_exceptional_values, patches_validity).into_array();
120
121 Some(Patches::new(
122 values_slice.len(),
123 0,
124 valid_exceptional_positions.into_array(),
125 valid_exceptional_values,
126 Some(chunk_offsets.into_array()),
127 )?)
128 };
129 Ok((exponents, encoded_array, patches))
130}
131
132#[cfg(test)]
133mod tests {
134 use core::f64;
135
136 use f64::consts::E;
137 use f64::consts::PI;
138 use vortex_array::LEGACY_SESSION;
139 use vortex_array::ToCanonical;
140 use vortex_array::VortexSessionExecute;
141 use vortex_array::assert_arrays_eq;
142 use vortex_array::dtype::NativePType;
143 use vortex_array::validity::Validity;
144 use vortex_buffer::Buffer;
145 use vortex_buffer::buffer;
146
147 use super::*;
148 use crate::alp::array::ALPArrayExt;
149 use crate::alp::array::ALPArraySlotsExt;
150 use crate::decompress_into_array;
151
152 #[test]
153 fn test_compress() {
154 let array = PrimitiveArray::new(buffer![1.234f32; 1025], Validity::NonNullable);
155 let encoded = alp_encode(
156 array.as_view(),
157 None,
158 &mut LEGACY_SESSION.create_execution_ctx(),
159 )
160 .unwrap();
161 assert!(encoded.patches().is_none());
162 let expected_encoded = PrimitiveArray::from_iter(vec![1234i32; 1025]);
163 assert_arrays_eq!(encoded.encoded(), expected_encoded);
164 assert_eq!(encoded.exponents(), Exponents { e: 9, f: 6 });
165
166 let decoded =
167 decompress_into_array(encoded, &mut LEGACY_SESSION.create_execution_ctx()).unwrap();
168 assert_arrays_eq!(decoded, array);
169 }
170
171 #[test]
172 fn test_nullable_compress() {
173 let array = PrimitiveArray::from_option_iter([None, Some(1.234f32), None]);
174 let encoded = alp_encode(
175 array.as_view(),
176 None,
177 &mut LEGACY_SESSION.create_execution_ctx(),
178 )
179 .unwrap();
180 assert!(encoded.patches().is_none());
181 let expected_encoded = PrimitiveArray::from_option_iter([None, Some(1234i32), None]);
182 assert_arrays_eq!(encoded.encoded(), expected_encoded);
183 assert_eq!(encoded.exponents(), Exponents { e: 9, f: 6 });
184
185 let decoded =
186 decompress_into_array(encoded, &mut LEGACY_SESSION.create_execution_ctx()).unwrap();
187 let expected = PrimitiveArray::from_option_iter(vec![None, Some(1.234f32), None]);
188 assert_arrays_eq!(decoded, expected);
189 }
190
191 #[test]
192 #[expect(clippy::approx_constant)] fn test_patched_compress() {
194 let values = buffer![1.234f64, 2.718, PI, 4.0];
195 let array = PrimitiveArray::new(values.clone(), Validity::NonNullable);
196 let encoded = alp_encode(
197 array.as_view(),
198 None,
199 &mut LEGACY_SESSION.create_execution_ctx(),
200 )
201 .unwrap();
202 assert!(encoded.patches().is_some());
203 let expected_encoded = PrimitiveArray::from_iter(vec![1234i64, 2718, 1234, 4000]);
204 assert_arrays_eq!(encoded.encoded(), expected_encoded);
205 assert_eq!(encoded.exponents(), Exponents { e: 16, f: 13 });
206
207 let decoded =
208 decompress_into_array(encoded, &mut LEGACY_SESSION.create_execution_ctx()).unwrap();
209 let expected_decoded = PrimitiveArray::new(values, Validity::NonNullable);
210 assert_arrays_eq!(decoded, expected_decoded);
211 }
212
213 #[test]
214 #[expect(clippy::approx_constant)] fn test_compress_ignores_invalid_exceptional_values() {
216 let values = buffer![1.234f64, 2.718, PI, 4.0];
217 let array = PrimitiveArray::new(values, Validity::from_iter([true, true, false, true]));
218 let encoded = alp_encode(
219 array.as_view(),
220 None,
221 &mut LEGACY_SESSION.create_execution_ctx(),
222 )
223 .unwrap();
224 assert!(encoded.patches().is_none());
225 let expected_encoded =
226 PrimitiveArray::from_option_iter(buffer![Some(1234i64), Some(2718), None, Some(4000)]);
227 assert_arrays_eq!(encoded.encoded(), expected_encoded);
228 assert_eq!(encoded.exponents(), Exponents { e: 16, f: 13 });
229
230 let decoded =
231 decompress_into_array(encoded, &mut LEGACY_SESSION.create_execution_ctx()).unwrap();
232 assert_arrays_eq!(decoded, array);
233 }
234
235 #[test]
236 #[expect(clippy::approx_constant)] fn test_nullable_patched_scalar_at() {
238 let array = PrimitiveArray::from_option_iter([
239 Some(1.234f64),
240 Some(2.718),
241 Some(PI),
242 Some(4.0),
243 None,
244 ]);
245 let encoded = alp_encode(
246 array.as_view(),
247 None,
248 &mut LEGACY_SESSION.create_execution_ctx(),
249 )
250 .unwrap();
251 assert!(encoded.patches().is_some());
252
253 assert_eq!(encoded.exponents(), Exponents { e: 16, f: 13 });
254
255 assert_arrays_eq!(encoded, array);
256
257 let _decoded =
258 decompress_into_array(encoded, &mut LEGACY_SESSION.create_execution_ctx()).unwrap();
259 }
260
261 #[test]
262 fn roundtrips_close_fractional() {
263 let original = PrimitiveArray::from_iter([195.26274f32, 195.27837, -48.815685]);
264 let alp_arr = alp_encode(
265 original.as_view(),
266 None,
267 &mut LEGACY_SESSION.create_execution_ctx(),
268 )
269 .unwrap();
270 assert_arrays_eq!(alp_arr, original);
271 }
272
273 #[test]
274 fn roundtrips_all_null() {
275 let original =
276 PrimitiveArray::new(buffer![195.26274f64, PI, -48.815685], Validity::AllInvalid);
277 let alp_arr = alp_encode(
278 original.as_view(),
279 None,
280 &mut LEGACY_SESSION.create_execution_ctx(),
281 )
282 .unwrap();
283 let decompressed = alp_arr.into_array().to_primitive();
284
285 assert_eq!(
286 [195.26274, 195.26274, 195.26274],
288 decompressed.as_slice::<f64>()
289 );
290
291 assert_arrays_eq!(decompressed, original);
292 }
293
294 #[test]
295 fn non_finite_numbers() {
296 let original = PrimitiveArray::new(
297 buffer![0.0f32, -0.0, f32::NAN, f32::NEG_INFINITY, f32::INFINITY],
298 Validity::NonNullable,
299 );
300 let encoded = alp_encode(
301 original.as_view(),
302 None,
303 &mut LEGACY_SESSION.create_execution_ctx(),
304 )
305 .unwrap();
306 let decoded = encoded.as_array().to_primitive();
307 for idx in 0..original.len() {
308 let decoded_val = decoded.as_slice::<f32>()[idx];
309 let original_val = original.as_slice::<f32>()[idx];
310 assert!(
311 decoded_val.is_eq(original_val),
312 "Expected {original_val} but got {decoded_val}"
313 );
314 }
315 }
316
317 #[test]
318 fn test_chunk_offsets() {
319 let mut values = vec![1.0f64; 3072];
320
321 values[1023] = PI;
322 values[1024] = E;
323 values[1025] = PI;
324
325 let array = PrimitiveArray::new(Buffer::from(values), Validity::NonNullable);
326 let encoded = alp_encode(
327 array.as_view(),
328 None,
329 &mut LEGACY_SESSION.create_execution_ctx(),
330 )
331 .unwrap();
332 let patches = encoded.patches().unwrap();
333
334 let chunk_offsets = patches.chunk_offsets().clone().unwrap().to_primitive();
335 let expected_offsets = PrimitiveArray::from_iter(vec![0u64, 1, 3]);
336 assert_arrays_eq!(chunk_offsets, expected_offsets);
337
338 let patch_indices = patches.indices().to_primitive();
339 let expected_indices = PrimitiveArray::from_iter(vec![1023u64, 1024, 1025]);
340 assert_arrays_eq!(patch_indices, expected_indices);
341
342 let patch_values = patches.values().to_primitive();
343 let expected_values = PrimitiveArray::from_iter(vec![PI, E, PI]);
344 assert_arrays_eq!(patch_values, expected_values);
345 }
346
347 #[test]
348 fn test_chunk_offsets_no_patches_in_middle() {
349 let mut values = vec![1.0f64; 3072];
350 values[0] = PI;
351 values[2048] = E;
352
353 let array = PrimitiveArray::new(Buffer::from(values), Validity::NonNullable);
354 let encoded = alp_encode(
355 array.as_view(),
356 None,
357 &mut LEGACY_SESSION.create_execution_ctx(),
358 )
359 .unwrap();
360 let patches = encoded.patches().unwrap();
361
362 let chunk_offsets = patches.chunk_offsets().clone().unwrap().to_primitive();
363 let expected_offsets = PrimitiveArray::from_iter(vec![0u64, 1, 1]);
364 assert_arrays_eq!(chunk_offsets, expected_offsets);
365
366 let patch_indices = patches.indices().to_primitive();
367 let expected_indices = PrimitiveArray::from_iter(vec![0u64, 2048]);
368 assert_arrays_eq!(patch_indices, expected_indices);
369
370 let patch_values = patches.values().to_primitive();
371 let expected_values = PrimitiveArray::from_iter(vec![PI, E]);
372 assert_arrays_eq!(patch_values, expected_values);
373 }
374
375 #[test]
376 fn test_chunk_offsets_trailing_empty_chunks() {
377 let mut values = vec![1.0f64; 3072];
378 values[0] = PI;
379
380 let array = PrimitiveArray::new(Buffer::from(values), Validity::NonNullable);
381 let encoded = alp_encode(
382 array.as_view(),
383 None,
384 &mut LEGACY_SESSION.create_execution_ctx(),
385 )
386 .unwrap();
387 let patches = encoded.patches().unwrap();
388
389 let chunk_offsets = patches.chunk_offsets().clone().unwrap().to_primitive();
390 let expected_offsets = PrimitiveArray::from_iter(vec![0u64, 1, 1]);
391 assert_arrays_eq!(chunk_offsets, expected_offsets);
392
393 let patch_indices = patches.indices().to_primitive();
394 let expected_indices = PrimitiveArray::from_iter(vec![0u64]);
395 assert_arrays_eq!(patch_indices, expected_indices);
396
397 let patch_values = patches.values().to_primitive();
398 let expected_values = PrimitiveArray::from_iter(vec![PI]);
399 assert_arrays_eq!(patch_values, expected_values);
400 }
401
402 #[test]
403 fn test_chunk_offsets_single_chunk() {
404 let mut values = vec![1.0f64; 512];
405 values[0] = PI;
406 values[100] = E;
407
408 let array = PrimitiveArray::new(Buffer::from(values), Validity::NonNullable);
409 let encoded = alp_encode(
410 array.as_view(),
411 None,
412 &mut LEGACY_SESSION.create_execution_ctx(),
413 )
414 .unwrap();
415 let patches = encoded.patches().unwrap();
416
417 let chunk_offsets = patches.chunk_offsets().clone().unwrap().to_primitive();
418 let expected_offsets = PrimitiveArray::from_iter(vec![0u64]);
419 assert_arrays_eq!(chunk_offsets, expected_offsets);
420
421 let patch_indices = patches.indices().to_primitive();
422 let expected_indices = PrimitiveArray::from_iter(vec![0u64, 100]);
423 assert_arrays_eq!(patch_indices, expected_indices);
424
425 let patch_values = patches.values().to_primitive();
426 let expected_values = PrimitiveArray::from_iter(vec![PI, E]);
427 assert_arrays_eq!(patch_values, expected_values);
428 }
429
430 #[test]
431 fn test_slice_half_chunk_f32_roundtrip() {
432 let values = vec![1.234f32; 1024];
434 let original = PrimitiveArray::new(Buffer::from(values), Validity::NonNullable);
435 let encoded = alp_encode(
436 original.as_view(),
437 None,
438 &mut LEGACY_SESSION.create_execution_ctx(),
439 )
440 .unwrap();
441
442 let sliced_alp = encoded.slice(512..1024).unwrap();
443
444 let expected_slice = original.slice(512..1024).unwrap();
445 assert_arrays_eq!(sliced_alp, expected_slice);
446 }
447
448 #[test]
449 fn test_slice_half_chunk_f64_roundtrip() {
450 let values = vec![5.678f64; 1024];
451 let original = PrimitiveArray::new(Buffer::from(values), Validity::NonNullable);
452 let encoded = alp_encode(
453 original.as_view(),
454 None,
455 &mut LEGACY_SESSION.create_execution_ctx(),
456 )
457 .unwrap();
458
459 let sliced_alp = encoded.slice(512..1024).unwrap();
460
461 let expected_slice = original.slice(512..1024).unwrap();
462 assert_arrays_eq!(sliced_alp, expected_slice);
463 }
464
465 #[test]
466 fn test_slice_half_chunk_with_patches_roundtrip() {
467 let mut values = vec![1.0f64; 1024];
468 values[100] = PI;
469 values[200] = E;
470 values[600] = 42.42;
471
472 let original = PrimitiveArray::new(Buffer::from(values), Validity::NonNullable);
473 let encoded = alp_encode(
474 original.as_view(),
475 None,
476 &mut LEGACY_SESSION.create_execution_ctx(),
477 )
478 .unwrap();
479
480 let sliced_alp = encoded.slice(512..1024).unwrap();
481
482 let expected_slice = original.slice(512..1024).unwrap();
483 assert_arrays_eq!(sliced_alp, expected_slice);
484 assert!(encoded.patches().is_some());
485 }
486
487 #[test]
488 fn test_slice_across_chunks_with_patches_roundtrip() {
489 let mut values = vec![1.0f64; 2048];
490 values[100] = PI;
491 values[200] = E;
492 values[600] = 42.42;
493 values[800] = 42.42;
494 values[1000] = 42.42;
495 values[1023] = 42.42;
496
497 let original = PrimitiveArray::new(Buffer::from(values), Validity::NonNullable);
498 let encoded = alp_encode(
499 original.as_view(),
500 None,
501 &mut LEGACY_SESSION.create_execution_ctx(),
502 )
503 .unwrap();
504
505 let sliced_alp = encoded.slice(1023..1025).unwrap();
506
507 let expected_slice = original.slice(1023..1025).unwrap();
508 assert_arrays_eq!(sliced_alp, expected_slice);
509 assert!(encoded.patches().is_some());
510 }
511
512 #[test]
513 fn test_slice_half_chunk_nullable_roundtrip() {
514 let values = (0..1024)
515 .map(|i| if i % 3 == 0 { None } else { Some(2.5f32) })
516 .collect::<Vec<_>>();
517
518 let original = PrimitiveArray::from_option_iter(values);
519 let encoded = alp_encode(
520 original.as_view(),
521 None,
522 &mut LEGACY_SESSION.create_execution_ctx(),
523 )
524 .unwrap();
525
526 let sliced_alp = encoded.slice(512..1024).unwrap();
527 let decoded = sliced_alp.to_primitive();
528
529 let expected_slice = original.slice(512..1024).unwrap();
530 assert_arrays_eq!(decoded, expected_slice);
531 }
532
533 #[test]
534 fn test_large_f32_array_uniform_values() {
535 let size = 10_000;
536 let array = PrimitiveArray::new(buffer![42.125f32; size], Validity::NonNullable);
537 let encoded = alp_encode(
538 array.as_view(),
539 None,
540 &mut LEGACY_SESSION.create_execution_ctx(),
541 )
542 .unwrap();
543
544 assert!(encoded.patches().is_none());
545 let decoded =
546 decompress_into_array(encoded, &mut LEGACY_SESSION.create_execution_ctx()).unwrap();
547 assert_arrays_eq!(decoded, array);
548 }
549
550 #[test]
551 fn test_large_f64_array_uniform_values() {
552 let size = 50_000;
553 let array = PrimitiveArray::new(buffer![123.456789f64; size], Validity::NonNullable);
554 let encoded = alp_encode(
555 array.as_view(),
556 None,
557 &mut LEGACY_SESSION.create_execution_ctx(),
558 )
559 .unwrap();
560
561 assert!(encoded.patches().is_none());
562 let decoded =
563 decompress_into_array(encoded, &mut LEGACY_SESSION.create_execution_ctx()).unwrap();
564 assert_arrays_eq!(decoded, array);
565 }
566
567 #[test]
568 fn test_large_f32_array_with_patches() {
569 let size = 5_000;
570 let mut values = vec![1.5f32; size];
571 values[100] = std::f32::consts::PI;
572 values[1500] = std::f32::consts::E;
573 values[3000] = f32::NEG_INFINITY;
574 values[4500] = f32::INFINITY;
575
576 let array = PrimitiveArray::new(Buffer::from(values), Validity::NonNullable);
577 let encoded = alp_encode(
578 array.as_view(),
579 None,
580 &mut LEGACY_SESSION.create_execution_ctx(),
581 )
582 .unwrap();
583
584 assert!(encoded.patches().is_some());
585 let decoded =
586 decompress_into_array(encoded, &mut LEGACY_SESSION.create_execution_ctx()).unwrap();
587 assert_arrays_eq!(decoded, array);
588 }
589
590 #[test]
591 fn test_large_f64_array_with_patches() {
592 let size = 8_000;
593 let mut values = vec![2.2184f64; size];
594 values[0] = PI;
595 values[1000] = E;
596 values[2000] = f64::NAN;
597 values[3000] = f64::INFINITY;
598 values[4000] = f64::NEG_INFINITY;
599 values[5000] = 0.0;
600 values[6000] = -0.0;
601 values[7000] = 999.999999999;
602
603 let array = PrimitiveArray::new(Buffer::from(values.clone()), Validity::NonNullable);
604 let encoded = alp_encode(
605 array.as_view(),
606 None,
607 &mut LEGACY_SESSION.create_execution_ctx(),
608 )
609 .unwrap();
610
611 assert!(encoded.patches().is_some());
612 let decoded =
613 decompress_into_array(encoded, &mut LEGACY_SESSION.create_execution_ctx()).unwrap();
614
615 for idx in 0..size {
616 let decoded_val = decoded.as_slice::<f64>()[idx];
617 let original_val = values[idx];
618 assert!(
619 decoded_val.is_eq(original_val),
620 "At index {idx}: Expected {original_val} but got {decoded_val}"
621 );
622 }
623 }
624
625 #[test]
626 fn test_large_nullable_array() {
627 let size = 12_000;
628 let values: Vec<Option<f32>> = (0..size)
629 .map(|i| {
630 if i % 7 == 0 {
631 None
632 } else {
633 Some((i as f32) * 0.1)
634 }
635 })
636 .collect();
637
638 let array = PrimitiveArray::from_option_iter(values);
639 let encoded = alp_encode(
640 array.as_view(),
641 None,
642 &mut LEGACY_SESSION.create_execution_ctx(),
643 )
644 .unwrap();
645 let decoded =
646 decompress_into_array(encoded, &mut LEGACY_SESSION.create_execution_ctx()).unwrap();
647
648 assert_arrays_eq!(decoded, array);
649 }
650
651 #[test]
652 fn test_large_mixed_validity_with_patches() {
653 let size = 6_000;
654 let mut values = vec![10.125f64; size];
655
656 values[500] = PI;
657 values[1500] = E;
658 values[2500] = f64::INFINITY;
659 values[3500] = f64::NEG_INFINITY;
660 values[4500] = f64::NAN;
661
662 let validity = Validity::from_iter((0..size).map(|i| !matches!(i, 500 | 2500)));
663
664 let array = PrimitiveArray::new(Buffer::from(values), validity);
665 let encoded = alp_encode(
666 array.as_view(),
667 None,
668 &mut LEGACY_SESSION.create_execution_ctx(),
669 )
670 .unwrap();
671 let decoded =
672 decompress_into_array(encoded, &mut LEGACY_SESSION.create_execution_ctx()).unwrap();
673
674 assert_arrays_eq!(decoded, array);
675 }
676
677 #[test]
685 fn test_slice_mid_chunk_with_patches_in_trailing_chunk() {
686 let mut values = vec![1.0f64; 3072];
688 values[100] = PI;
690 values[500] = E;
691 values[1100] = PI;
693 values[1500] = E;
694 values[1900] = PI;
695 values[2100] = PI;
697 values[2500] = E;
698 values[2900] = PI;
699
700 let original = PrimitiveArray::new(Buffer::from(values), Validity::NonNullable);
701 let encoded = alp_encode(
702 original.as_view(),
703 None,
704 &mut LEGACY_SESSION.create_execution_ctx(),
705 )
706 .unwrap();
707 assert!(encoded.patches().is_some());
708
709 let sliced_alp = encoded.slice(0..2500).unwrap();
713 let expected = original.slice(0..2500).unwrap();
714 assert_arrays_eq!(sliced_alp, expected);
715
716 let sliced_alp = encoded.slice(500..2500).unwrap();
718 let expected = original.slice(500..2500).unwrap();
719 assert_arrays_eq!(sliced_alp, expected);
720 }
721}