|
1 | 1 | // SPDX-License-Identifier: Apache-2.0 |
2 | 2 | // SPDX-FileCopyrightText: Copyright the Vortex contributors |
3 | 3 |
|
4 | | -// Re-export builtin schemes from vortex-compressor. |
| 4 | +//! Integer compression schemes. |
| 5 | +
|
5 | 6 | use vortex_array::ArrayRef; |
6 | 7 | use vortex_array::Canonical; |
7 | 8 | use vortex_array::IntoArray; |
8 | 9 | use vortex_array::ToCanonical; |
9 | 10 | use vortex_array::arrays::ConstantArray; |
10 | 11 | use vortex_array::arrays::PrimitiveArray; |
11 | 12 | use vortex_array::scalar::Scalar; |
12 | | -pub use vortex_compressor::builtins::IntConstantScheme as ConstantScheme; |
13 | | -pub use vortex_compressor::builtins::IntDictScheme as DictScheme; |
14 | | -pub use vortex_compressor::builtins::IntUncompressedScheme as UncompressedScheme; |
15 | | -pub use vortex_compressor::builtins::is_integer_primitive; |
| 13 | +use vortex_compressor::builtins::FloatDictScheme; |
| 14 | +use vortex_compressor::builtins::StringDictScheme; |
16 | 15 | use vortex_compressor::scheme::AncestorExclusion; |
17 | 16 | use vortex_compressor::scheme::ChildSelection; |
18 | 17 | use vortex_compressor::scheme::DescendantExclusion; |
19 | | -pub use vortex_compressor::stats::IntegerStats; |
20 | 18 | use vortex_error::VortexExpect; |
21 | 19 | use vortex_error::VortexResult; |
22 | 20 | use vortex_error::vortex_bail; |
@@ -74,6 +72,13 @@ pub struct SequenceScheme; |
74 | 72 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
75 | 73 | pub struct PcoScheme; |
76 | 74 |
|
| 75 | +// Re-export builtin schemes from vortex-compressor. |
| 76 | +pub use vortex_compressor::builtins::IntConstantScheme; |
| 77 | +pub use vortex_compressor::builtins::IntDictScheme; |
| 78 | +pub use vortex_compressor::builtins::IntUncompressedScheme; |
| 79 | +pub use vortex_compressor::builtins::is_integer_primitive; |
| 80 | +pub use vortex_compressor::stats::IntegerStats; |
| 81 | + |
77 | 82 | /// Threshold for the average run length in an array before we consider run-end encoding. |
78 | 83 | const RUN_END_THRESHOLD: u32 = 4; |
79 | 84 |
|
@@ -224,10 +229,13 @@ impl Scheme for ZigZagScheme { |
224 | 229 | 1 |
225 | 230 | } |
226 | 231 |
|
| 232 | + /// Container-style schemes (Dict, RunEnd, Sparse) restructure data and should only be |
| 233 | + /// applied once in a cascade chain. ZigZag's output is a simple value transformation, |
| 234 | + /// so further restructuring is wasteful. |
227 | 235 | fn descendant_exclusions(&self) -> Vec<DescendantExclusion> { |
228 | 236 | vec![ |
229 | 237 | DescendantExclusion { |
230 | | - excluded: DictScheme.id(), |
| 238 | + excluded: IntDictScheme.id(), |
231 | 239 | children: ChildSelection::All, |
232 | 240 | }, |
233 | 241 | DescendantExclusion { |
@@ -361,9 +369,11 @@ impl Scheme for SparseScheme { |
361 | 369 | 2 |
362 | 370 | } |
363 | 371 |
|
| 372 | + /// Sparse values and indices are already low-cardinality by construction, so dictionary |
| 373 | + /// encoding doesn't add anything. |
364 | 374 | fn descendant_exclusions(&self) -> Vec<DescendantExclusion> { |
365 | 375 | vec![DescendantExclusion { |
366 | | - excluded: DictScheme.id(), |
| 376 | + excluded: IntDictScheme.id(), |
367 | 377 | children: ChildSelection::All, |
368 | 378 | }] |
369 | 379 | } |
@@ -488,24 +498,21 @@ impl Scheme for RunEndScheme { |
488 | 498 | 2 |
489 | 499 | } |
490 | 500 |
|
| 501 | + /// Run-end values and ends are already deduplicated, so dictionary encoding doesn't add |
| 502 | + /// anything. |
491 | 503 | fn descendant_exclusions(&self) -> Vec<DescendantExclusion> { |
492 | 504 | vec![DescendantExclusion { |
493 | | - excluded: DictScheme.id(), |
| 505 | + excluded: IntDictScheme.id(), |
494 | 506 | children: ChildSelection::All, |
495 | 507 | }] |
496 | 508 | } |
497 | 509 |
|
| 510 | + // TODO(connor): There seems to be stuff missing here... |
498 | 511 | fn ancestor_exclusions(&self) -> Vec<AncestorExclusion> { |
499 | | - use vortex_compressor::builtins::FloatDictScheme; |
500 | | - |
501 | | - vec![ |
502 | | - // Exclude from FloatDict values child (child 0). This replaces the old ALP |
503 | | - // conditional propagation of float RLE exclusion to integer RunEnd. |
504 | | - AncestorExclusion { |
505 | | - ancestor: FloatDictScheme.id(), |
506 | | - children: ChildSelection::One(0), |
507 | | - }, |
508 | | - ] |
| 512 | + vec![AncestorExclusion { |
| 513 | + ancestor: FloatDictScheme.id(), |
| 514 | + children: ChildSelection::One(0), |
| 515 | + }] |
509 | 516 | } |
510 | 517 |
|
511 | 518 | fn expected_compression_ratio( |
@@ -564,22 +571,19 @@ impl Scheme for SequenceScheme { |
564 | 571 | is_integer_primitive(canonical) |
565 | 572 | } |
566 | 573 |
|
| 574 | + /// Sequence encoding on dictionary codes just adds a layer of indirection without compressing |
| 575 | + /// the data. Dict codes are compact integers that benefit from BitPacking or FoR, not from |
| 576 | + /// sequence detection. |
567 | 577 | fn ancestor_exclusions(&self) -> Vec<AncestorExclusion> { |
568 | | - use vortex_compressor::builtins::FloatDictScheme; |
569 | | - use vortex_compressor::builtins::StringDictScheme; |
570 | | - |
571 | 578 | vec![ |
572 | | - // Exclude from IntDict codes. |
573 | 579 | AncestorExclusion { |
574 | | - ancestor: DictScheme.id(), |
| 580 | + ancestor: IntDictScheme.id(), |
575 | 581 | children: ChildSelection::All, |
576 | 582 | }, |
577 | | - // Exclude from FloatDict codes (child 1). |
578 | 583 | AncestorExclusion { |
579 | 584 | ancestor: FloatDictScheme.id(), |
580 | 585 | children: ChildSelection::One(1), |
581 | 586 | }, |
582 | | - // Exclude from StringDict codes (child 1). |
583 | 587 | AncestorExclusion { |
584 | 588 | ancestor: StringDictScheme.id(), |
585 | 589 | children: ChildSelection::One(1), |
|
0 commit comments