wgtmac commented on code in PR #557:
URL: https://github.com/apache/parquet-format/pull/557#discussion_r3627344791


##########
Encodings.md:
##########
@@ -391,3 +391,423 @@ After applying the transformation, the data has the 
following representation:
 ```
 Bytes  AA 00 A3 BB 11 B4 CC 22 C5 DD 33 D6
 ```
+
+<a name="ALP"></a>
+### Adaptive Lossless floating-Point: (ALP = 10)
+
+Supported Types: FLOAT, DOUBLE
+
+This encoding is adapted from the paper
+["ALP: Adaptive Lossless floating-Point 
Compression"](https://dl.acm.org/doi/10.1145/3626717)
+by Afroozeh and Boncz (SIGMOD 2024).
+
+ALP works by converting floating-point values to integers using decimal scaling
+(controlled by an *exponent* `e` and *factor* `f`), then applying Frame of
+Reference (FOR) encoding and bit-packing. Values that cannot be losslessly
+converted are stored separately as *exceptions*. The encoding achieves high
+compression for decimal-like floating-point data (e.g., monetary values, sensor
+readings) while remaining fully lossless. Each value is encoded independently,
+enabling random access to individual values and parallel encode/decode.
+
+#### Overview
+
+ALP encoding consists of a page-level header followed by an offset array and 
one
+or more encoded vectors (batches of values). Each vector contains up to
+`vector_size` elements (default 1024).
+
+```
++-------------+-----------------------------+--------------------------------------+
+|   Header    |        Offset Array         |            Vector Data           
    |
+|  (7 bytes)  |   (num_vectors * 4 bytes)   |            (variable)            
    |
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+| Page Header | off0 | off1 | ... | off N-1 | Vector 0 | Vector 1 | ... | Vec 
N-1  |
+|  (7 bytes)  | (4B) | (4B) |     |  (4B)   |(variable)|(variable)|     
|(variable)|
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+```
+
+The compression pipeline below describes *one* way to produce a conforming
+vector. It is informative, not normative: an encoder may use any strategy as 
long
+as it emits the byte layout defined in [Page Layout](#page-layout). Only that
+byte layout and the [Decoding](#decoding) procedure are normative.
+
+```
+                    Input: float/double array
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  1. CHOOSE PARAMETERS                                    |
+    |     Select (exponent, factor) pair for this vector       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  2. DECIMAL ENCODING                                     |
+    |     encoded[i] = fast_round(value[i] * 10^e * 10^(-f))  |
+    |     Detect exceptions where decode(encode(v)) != v       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  3. FRAME OF REFERENCE (FOR)                             |
+    |     min_val = min(encoded[:])                            |
+    |     delta[i] = encoded[i] - min_val                      |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  4. BIT PACKING                                          |
+    |     bit_width = ceil(log2(max_delta + 1))                |
+    |     Pack each delta into bit_width bits                  |
+    +----------------------------------------------------------+
+                              |
+                              v
+                   Output: Serialized vector bytes
+```
+
+The `fast_round` used in step 2 is defined precisely in
+[Fast Rounding](#fast-rounding) below, including the exact magic-number values
+and the sign branching required for negative values.
+
+#### Page Layout
+
+##### Header (7 bytes)
+
+All multi-byte values are stored in little-endian order.
+
+```
+ Byte:    0              1               2              3    4    5    6
+       +----------------+---------------+--------------+----+----+----+----+
+       | compression    | integer       | log_vector   |     num_elements  |
+       | _mode          | _encoding     | _size        |     (int32 LE)    |
+       +----------------+---------------+--------------+----+----+----+----+
+```
+
+| Offset | Field | Size | Type | Description |
+|--------|-------|------|------|-------------|
+| 0 | compression_mode | 1 byte | uint8 | Compression mode (0 = ALP). Reserved 
for future variants (e.g., ALP-RD). |
+| 1 | integer_encoding | 1 byte | uint8 | Integer encoding (must be 0 = FOR + 
bit-packing) |
+| 2 | log_vector_size | 1 byte | uint8 | log2(vector\_size). Must be in the 
inclusive range \[3, 15\]. Recommended default: 10 (vector size 1024) |
+| 3 | num_elements | 4 bytes | int32 | Total number of floating-point values 
in the page |
+
+The number of vectors is `ceil(num_elements / vector_size)`. The last vector 
may
+contain fewer than `vector_size` elements.
+
+**Note:** The number of elements per vector is NOT stored in the header — it is
+derived: `vector_size` for all vectors except the last, which may be smaller.
+
+##### Offset Array
+
+Immediately following the header is an array of `num_vectors` little-endian 
uint32
+values. Each offset gives the byte position of the corresponding vector's data,
+measured from the start of the offset array itself.
+
+The first offset always equals `num_vectors * 4` (pointing just past the 
offset array).
+Each subsequent offset equals the previous offset plus the stored size of the
+previous vector. No padding is inserted between vectors.
+
+A vector's absolute byte position within the page is
+`page_data_start + 7 + offset`, where `page_data_start` is the first byte after
+the page's Thrift header and `7` is the size of the ALP header.
+
+##### Vector Format
+
+Each vector is self-describing and contains the encoding parameters, FOR 
metadata,
+bit-packed encoded values, and exception data.
+
+```
++-------------------+-----------------+-------------------+---------------------+-------------------+
+|      AlpInfo      |     ForInfo     |   PackedValues    | ExceptionPositions 
 | ExceptionValues   |

Review Comment:
   Why here we use camel case but other places use snake case?



##########
Encodings.md:
##########
@@ -391,3 +391,423 @@ After applying the transformation, the data has the 
following representation:
 ```
 Bytes  AA 00 A3 BB 11 B4 CC 22 C5 DD 33 D6
 ```
+
+<a name="ALP"></a>
+### Adaptive Lossless floating-Point: (ALP = 10)
+
+Supported Types: FLOAT, DOUBLE
+
+This encoding is adapted from the paper
+["ALP: Adaptive Lossless floating-Point 
Compression"](https://dl.acm.org/doi/10.1145/3626717)
+by Afroozeh and Boncz (SIGMOD 2024).
+
+ALP works by converting floating-point values to integers using decimal scaling
+(controlled by an *exponent* `e` and *factor* `f`), then applying Frame of
+Reference (FOR) encoding and bit-packing. Values that cannot be losslessly
+converted are stored separately as *exceptions*. The encoding achieves high
+compression for decimal-like floating-point data (e.g., monetary values, sensor
+readings) while remaining fully lossless. Each value is encoded independently,
+enabling random access to individual values and parallel encode/decode.
+
+#### Overview
+
+ALP encoding consists of a page-level header followed by an offset array and 
one
+or more encoded vectors (batches of values). Each vector contains up to
+`vector_size` elements (default 1024).
+
+```
++-------------+-----------------------------+--------------------------------------+
+|   Header    |        Offset Array         |            Vector Data           
    |
+|  (7 bytes)  |   (num_vectors * 4 bytes)   |            (variable)            
    |
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+| Page Header | off0 | off1 | ... | off N-1 | Vector 0 | Vector 1 | ... | Vec 
N-1  |
+|  (7 bytes)  | (4B) | (4B) |     |  (4B)   |(variable)|(variable)|     
|(variable)|
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+```
+
+The compression pipeline below describes *one* way to produce a conforming
+vector. It is informative, not normative: an encoder may use any strategy as 
long
+as it emits the byte layout defined in [Page Layout](#page-layout). Only that
+byte layout and the [Decoding](#decoding) procedure are normative.
+
+```
+                    Input: float/double array
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  1. CHOOSE PARAMETERS                                    |
+    |     Select (exponent, factor) pair for this vector       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  2. DECIMAL ENCODING                                     |
+    |     encoded[i] = fast_round(value[i] * 10^e * 10^(-f))  |
+    |     Detect exceptions where decode(encode(v)) != v       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  3. FRAME OF REFERENCE (FOR)                             |
+    |     min_val = min(encoded[:])                            |
+    |     delta[i] = encoded[i] - min_val                      |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  4. BIT PACKING                                          |
+    |     bit_width = ceil(log2(max_delta + 1))                |
+    |     Pack each delta into bit_width bits                  |
+    +----------------------------------------------------------+
+                              |
+                              v
+                   Output: Serialized vector bytes
+```
+
+The `fast_round` used in step 2 is defined precisely in
+[Fast Rounding](#fast-rounding) below, including the exact magic-number values
+and the sign branching required for negative values.
+
+#### Page Layout
+
+##### Header (7 bytes)
+
+All multi-byte values are stored in little-endian order.
+
+```
+ Byte:    0              1               2              3    4    5    6
+       +----------------+---------------+--------------+----+----+----+----+
+       | compression    | integer       | log_vector   |     num_elements  |
+       | _mode          | _encoding     | _size        |     (int32 LE)    |
+       +----------------+---------------+--------------+----+----+----+----+
+```
+
+| Offset | Field | Size | Type | Description |
+|--------|-------|------|------|-------------|
+| 0 | compression_mode | 1 byte | uint8 | Compression mode (0 = ALP). Reserved 
for future variants (e.g., ALP-RD). |
+| 1 | integer_encoding | 1 byte | uint8 | Integer encoding (must be 0 = FOR + 
bit-packing) |
+| 2 | log_vector_size | 1 byte | uint8 | log2(vector\_size). Must be in the 
inclusive range \[3, 15\]. Recommended default: 10 (vector size 1024) |
+| 3 | num_elements | 4 bytes | int32 | Total number of floating-point values 
in the page |

Review Comment:
   ```suggestion
   | 3 | num_elements | 4 bytes | int32 | Total number of non-null 
floating-point values in the page |
   ```



##########
Encodings.md:
##########
@@ -391,3 +391,423 @@ After applying the transformation, the data has the 
following representation:
 ```
 Bytes  AA 00 A3 BB 11 B4 CC 22 C5 DD 33 D6
 ```
+
+<a name="ALP"></a>
+### Adaptive Lossless floating-Point: (ALP = 10)
+
+Supported Types: FLOAT, DOUBLE
+
+This encoding is adapted from the paper
+["ALP: Adaptive Lossless floating-Point 
Compression"](https://dl.acm.org/doi/10.1145/3626717)
+by Afroozeh and Boncz (SIGMOD 2024).

Review Comment:
   It seems that the paper has THREE authors but we have only listed TWO.



##########
Encodings.md:
##########
@@ -391,3 +391,423 @@ After applying the transformation, the data has the 
following representation:
 ```
 Bytes  AA 00 A3 BB 11 B4 CC 22 C5 DD 33 D6
 ```
+
+<a name="ALP"></a>
+### Adaptive Lossless floating-Point: (ALP = 10)
+
+Supported Types: FLOAT, DOUBLE
+
+This encoding is adapted from the paper
+["ALP: Adaptive Lossless floating-Point 
Compression"](https://dl.acm.org/doi/10.1145/3626717)
+by Afroozeh and Boncz (SIGMOD 2024).
+
+ALP works by converting floating-point values to integers using decimal scaling
+(controlled by an *exponent* `e` and *factor* `f`), then applying Frame of
+Reference (FOR) encoding and bit-packing. Values that cannot be losslessly
+converted are stored separately as *exceptions*. The encoding achieves high
+compression for decimal-like floating-point data (e.g., monetary values, sensor
+readings) while remaining fully lossless. Each value is encoded independently,
+enabling random access to individual values and parallel encode/decode.
+
+#### Overview
+
+ALP encoding consists of a page-level header followed by an offset array and 
one
+or more encoded vectors (batches of values). Each vector contains up to
+`vector_size` elements (default 1024).
+
+```
++-------------+-----------------------------+--------------------------------------+
+|   Header    |        Offset Array         |            Vector Data           
    |
+|  (7 bytes)  |   (num_vectors * 4 bytes)   |            (variable)            
    |
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+| Page Header | off0 | off1 | ... | off N-1 | Vector 0 | Vector 1 | ... | Vec 
N-1  |
+|  (7 bytes)  | (4B) | (4B) |     |  (4B)   |(variable)|(variable)|     
|(variable)|
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+```
+
+The compression pipeline below describes *one* way to produce a conforming
+vector. It is informative, not normative: an encoder may use any strategy as 
long
+as it emits the byte layout defined in [Page Layout](#page-layout). Only that
+byte layout and the [Decoding](#decoding) procedure are normative.
+
+```
+                    Input: float/double array
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  1. CHOOSE PARAMETERS                                    |
+    |     Select (exponent, factor) pair for this vector       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  2. DECIMAL ENCODING                                     |
+    |     encoded[i] = fast_round(value[i] * 10^e * 10^(-f))  |
+    |     Detect exceptions where decode(encode(v)) != v       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  3. FRAME OF REFERENCE (FOR)                             |
+    |     min_val = min(encoded[:])                            |
+    |     delta[i] = encoded[i] - min_val                      |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  4. BIT PACKING                                          |
+    |     bit_width = ceil(log2(max_delta + 1))                |
+    |     Pack each delta into bit_width bits                  |
+    +----------------------------------------------------------+
+                              |
+                              v
+                   Output: Serialized vector bytes
+```
+
+The `fast_round` used in step 2 is defined precisely in
+[Fast Rounding](#fast-rounding) below, including the exact magic-number values
+and the sign branching required for negative values.
+
+#### Page Layout
+
+##### Header (7 bytes)
+
+All multi-byte values are stored in little-endian order.
+
+```
+ Byte:    0              1               2              3    4    5    6
+       +----------------+---------------+--------------+----+----+----+----+
+       | compression    | integer       | log_vector   |     num_elements  |
+       | _mode          | _encoding     | _size        |     (int32 LE)    |
+       +----------------+---------------+--------------+----+----+----+----+
+```
+
+| Offset | Field | Size | Type | Description |
+|--------|-------|------|------|-------------|
+| 0 | compression_mode | 1 byte | uint8 | Compression mode (0 = ALP). Reserved 
for future variants (e.g., ALP-RD). |
+| 1 | integer_encoding | 1 byte | uint8 | Integer encoding (must be 0 = FOR + 
bit-packing) |
+| 2 | log_vector_size | 1 byte | uint8 | log2(vector\_size). Must be in the 
inclusive range \[3, 15\]. Recommended default: 10 (vector size 1024) |
+| 3 | num_elements | 4 bytes | int32 | Total number of floating-point values 
in the page |
+
+The number of vectors is `ceil(num_elements / vector_size)`. The last vector 
may
+contain fewer than `vector_size` elements.
+
+**Note:** The number of elements per vector is NOT stored in the header — it is
+derived: `vector_size` for all vectors except the last, which may be smaller.
+
+##### Offset Array
+
+Immediately following the header is an array of `num_vectors` little-endian 
uint32
+values. Each offset gives the byte position of the corresponding vector's data,
+measured from the start of the offset array itself.
+
+The first offset always equals `num_vectors * 4` (pointing just past the 
offset array).
+Each subsequent offset equals the previous offset plus the stored size of the
+previous vector. No padding is inserted between vectors.
+
+A vector's absolute byte position within the page is
+`page_data_start + 7 + offset`, where `page_data_start` is the first byte after
+the page's Thrift header and `7` is the size of the ALP header.
+
+##### Vector Format
+
+Each vector is self-describing and contains the encoding parameters, FOR 
metadata,
+bit-packed encoded values, and exception data.
+
+```
++-------------------+-----------------+-------------------+---------------------+-------------------+

Review Comment:
   Can we enhance the graph by pointing out areas of vector header and data 
section?



##########
Encodings.md:
##########
@@ -391,3 +391,423 @@ After applying the transformation, the data has the 
following representation:
 ```
 Bytes  AA 00 A3 BB 11 B4 CC 22 C5 DD 33 D6
 ```
+
+<a name="ALP"></a>
+### Adaptive Lossless floating-Point: (ALP = 10)
+
+Supported Types: FLOAT, DOUBLE
+
+This encoding is adapted from the paper
+["ALP: Adaptive Lossless floating-Point 
Compression"](https://dl.acm.org/doi/10.1145/3626717)
+by Afroozeh and Boncz (SIGMOD 2024).
+
+ALP works by converting floating-point values to integers using decimal scaling
+(controlled by an *exponent* `e` and *factor* `f`), then applying Frame of
+Reference (FOR) encoding and bit-packing. Values that cannot be losslessly
+converted are stored separately as *exceptions*. The encoding achieves high
+compression for decimal-like floating-point data (e.g., monetary values, sensor
+readings) while remaining fully lossless. Each value is encoded independently,
+enabling random access to individual values and parallel encode/decode.
+
+#### Overview
+
+ALP encoding consists of a page-level header followed by an offset array and 
one
+or more encoded vectors (batches of values). Each vector contains up to
+`vector_size` elements (default 1024).
+
+```
++-------------+-----------------------------+--------------------------------------+
+|   Header    |        Offset Array         |            Vector Data           
    |
+|  (7 bytes)  |   (num_vectors * 4 bytes)   |            (variable)            
    |
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+| Page Header | off0 | off1 | ... | off N-1 | Vector 0 | Vector 1 | ... | Vec 
N-1  |
+|  (7 bytes)  | (4B) | (4B) |     |  (4B)   |(variable)|(variable)|     
|(variable)|
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+```
+
+The compression pipeline below describes *one* way to produce a conforming
+vector. It is informative, not normative: an encoder may use any strategy as 
long
+as it emits the byte layout defined in [Page Layout](#page-layout). Only that
+byte layout and the [Decoding](#decoding) procedure are normative.
+
+```
+                    Input: float/double array
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  1. CHOOSE PARAMETERS                                    |
+    |     Select (exponent, factor) pair for this vector       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  2. DECIMAL ENCODING                                     |
+    |     encoded[i] = fast_round(value[i] * 10^e * 10^(-f))  |
+    |     Detect exceptions where decode(encode(v)) != v       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  3. FRAME OF REFERENCE (FOR)                             |
+    |     min_val = min(encoded[:])                            |
+    |     delta[i] = encoded[i] - min_val                      |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  4. BIT PACKING                                          |
+    |     bit_width = ceil(log2(max_delta + 1))                |
+    |     Pack each delta into bit_width bits                  |
+    +----------------------------------------------------------+
+                              |
+                              v
+                   Output: Serialized vector bytes
+```
+
+The `fast_round` used in step 2 is defined precisely in
+[Fast Rounding](#fast-rounding) below, including the exact magic-number values
+and the sign branching required for negative values.
+
+#### Page Layout
+
+##### Header (7 bytes)
+
+All multi-byte values are stored in little-endian order.
+
+```
+ Byte:    0              1               2              3    4    5    6
+       +----------------+---------------+--------------+----+----+----+----+
+       | compression    | integer       | log_vector   |     num_elements  |
+       | _mode          | _encoding     | _size        |     (int32 LE)    |
+       +----------------+---------------+--------------+----+----+----+----+
+```
+
+| Offset | Field | Size | Type | Description |
+|--------|-------|------|------|-------------|
+| 0 | compression_mode | 1 byte | uint8 | Compression mode (0 = ALP). Reserved 
for future variants (e.g., ALP-RD). |
+| 1 | integer_encoding | 1 byte | uint8 | Integer encoding (must be 0 = FOR + 
bit-packing) |
+| 2 | log_vector_size | 1 byte | uint8 | log2(vector\_size). Must be in the 
inclusive range \[3, 15\]. Recommended default: 10 (vector size 1024) |
+| 3 | num_elements | 4 bytes | int32 | Total number of floating-point values 
in the page |
+
+The number of vectors is `ceil(num_elements / vector_size)`. The last vector 
may
+contain fewer than `vector_size` elements.
+
+**Note:** The number of elements per vector is NOT stored in the header — it is
+derived: `vector_size` for all vectors except the last, which may be smaller.
+
+##### Offset Array
+
+Immediately following the header is an array of `num_vectors` little-endian 
uint32
+values. Each offset gives the byte position of the corresponding vector's data,
+measured from the start of the offset array itself.
+
+The first offset always equals `num_vectors * 4` (pointing just past the 
offset array).
+Each subsequent offset equals the previous offset plus the stored size of the
+previous vector. No padding is inserted between vectors.
+
+A vector's absolute byte position within the page is
+`page_data_start + 7 + offset`, where `page_data_start` is the first byte after
+the page's Thrift header and `7` is the size of the ALP header.
+
+##### Vector Format
+
+Each vector is self-describing and contains the encoding parameters, FOR 
metadata,
+bit-packed encoded values, and exception data.
+
+```
++-------------------+-----------------+-------------------+---------------------+-------------------+
+|      AlpInfo      |     ForInfo     |   PackedValues    | ExceptionPositions 
 | ExceptionValues   |
+|     (4 bytes)     | (5B or 9B)      |    (variable)     |     (variable)     
 |    (variable)     |
++-------------------+-----------------+-------------------+---------------------+-------------------+
+```
+
+Vector header sizes:
+| Type   | AlpInfo | ForInfo | Total Header |
+|--------|---------|---------|--------------|
+| FLOAT  | 4 bytes | 5 bytes | 9 bytes      |
+| DOUBLE | 4 bytes | 9 bytes | 13 bytes     |
+
+Data section sizes:
+| Section             | Size Formula                | Description              
    |
+|---------------------|-----------------------------|------------------------------|
+| PackedValues        | ceil(num\_elements\_in\_vector * bit\_width / 8) | 
Bit-packed delta values      |
+| ExceptionPositions  | num\_exceptions * 2 bytes   | uint16 indices of 
exceptions |

Review Comment:
   `num_exceptions` is described below so readers may have no idea where is 
comes from when reading this line.



##########
Encodings.md:
##########
@@ -391,3 +391,423 @@ After applying the transformation, the data has the 
following representation:
 ```
 Bytes  AA 00 A3 BB 11 B4 CC 22 C5 DD 33 D6
 ```
+
+<a name="ALP"></a>
+### Adaptive Lossless floating-Point: (ALP = 10)
+
+Supported Types: FLOAT, DOUBLE
+
+This encoding is adapted from the paper
+["ALP: Adaptive Lossless floating-Point 
Compression"](https://dl.acm.org/doi/10.1145/3626717)
+by Afroozeh and Boncz (SIGMOD 2024).
+
+ALP works by converting floating-point values to integers using decimal scaling
+(controlled by an *exponent* `e` and *factor* `f`), then applying Frame of
+Reference (FOR) encoding and bit-packing. Values that cannot be losslessly
+converted are stored separately as *exceptions*. The encoding achieves high
+compression for decimal-like floating-point data (e.g., monetary values, sensor
+readings) while remaining fully lossless. Each value is encoded independently,
+enabling random access to individual values and parallel encode/decode.
+
+#### Overview
+
+ALP encoding consists of a page-level header followed by an offset array and 
one
+or more encoded vectors (batches of values). Each vector contains up to
+`vector_size` elements (default 1024).
+
+```
++-------------+-----------------------------+--------------------------------------+
+|   Header    |        Offset Array         |            Vector Data           
    |
+|  (7 bytes)  |   (num_vectors * 4 bytes)   |            (variable)            
    |
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+| Page Header | off0 | off1 | ... | off N-1 | Vector 0 | Vector 1 | ... | Vec 
N-1  |
+|  (7 bytes)  | (4B) | (4B) |     |  (4B)   |(variable)|(variable)|     
|(variable)|
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+```
+
+The compression pipeline below describes *one* way to produce a conforming
+vector. It is informative, not normative: an encoder may use any strategy as 
long
+as it emits the byte layout defined in [Page Layout](#page-layout). Only that
+byte layout and the [Decoding](#decoding) procedure are normative.
+
+```
+                    Input: float/double array
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  1. CHOOSE PARAMETERS                                    |
+    |     Select (exponent, factor) pair for this vector       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  2. DECIMAL ENCODING                                     |
+    |     encoded[i] = fast_round(value[i] * 10^e * 10^(-f))  |
+    |     Detect exceptions where decode(encode(v)) != v       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  3. FRAME OF REFERENCE (FOR)                             |
+    |     min_val = min(encoded[:])                            |
+    |     delta[i] = encoded[i] - min_val                      |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  4. BIT PACKING                                          |
+    |     bit_width = ceil(log2(max_delta + 1))                |
+    |     Pack each delta into bit_width bits                  |
+    +----------------------------------------------------------+
+                              |
+                              v
+                   Output: Serialized vector bytes
+```
+
+The `fast_round` used in step 2 is defined precisely in
+[Fast Rounding](#fast-rounding) below, including the exact magic-number values
+and the sign branching required for negative values.
+
+#### Page Layout
+
+##### Header (7 bytes)
+
+All multi-byte values are stored in little-endian order.
+
+```
+ Byte:    0              1               2              3    4    5    6
+       +----------------+---------------+--------------+----+----+----+----+
+       | compression    | integer       | log_vector   |     num_elements  |
+       | _mode          | _encoding     | _size        |     (int32 LE)    |
+       +----------------+---------------+--------------+----+----+----+----+
+```
+
+| Offset | Field | Size | Type | Description |
+|--------|-------|------|------|-------------|
+| 0 | compression_mode | 1 byte | uint8 | Compression mode (0 = ALP). Reserved 
for future variants (e.g., ALP-RD). |
+| 1 | integer_encoding | 1 byte | uint8 | Integer encoding (must be 0 = FOR + 
bit-packing) |
+| 2 | log_vector_size | 1 byte | uint8 | log2(vector\_size). Must be in the 
inclusive range \[3, 15\]. Recommended default: 10 (vector size 1024) |
+| 3 | num_elements | 4 bytes | int32 | Total number of floating-point values 
in the page |
+
+The number of vectors is `ceil(num_elements / vector_size)`. The last vector 
may
+contain fewer than `vector_size` elements.
+
+**Note:** The number of elements per vector is NOT stored in the header — it is
+derived: `vector_size` for all vectors except the last, which may be smaller.
+
+##### Offset Array
+
+Immediately following the header is an array of `num_vectors` little-endian 
uint32
+values. Each offset gives the byte position of the corresponding vector's data,
+measured from the start of the offset array itself.
+
+The first offset always equals `num_vectors * 4` (pointing just past the 
offset array).
+Each subsequent offset equals the previous offset plus the stored size of the
+previous vector. No padding is inserted between vectors.
+
+A vector's absolute byte position within the page is
+`page_data_start + 7 + offset`, where `page_data_start` is the first byte after
+the page's Thrift header and `7` is the size of the ALP header.
+
+##### Vector Format
+
+Each vector is self-describing and contains the encoding parameters, FOR 
metadata,

Review Comment:
   This only applies to `compression_mode=0` and `integer_encoding=0`, right? 
Should we be explicit on this? Future settings may not even have `AlpInfo` and 
`ForInfo`.



##########
Encodings.md:
##########
@@ -391,3 +391,423 @@ After applying the transformation, the data has the 
following representation:
 ```
 Bytes  AA 00 A3 BB 11 B4 CC 22 C5 DD 33 D6
 ```
+
+<a name="ALP"></a>
+### Adaptive Lossless floating-Point: (ALP = 10)
+
+Supported Types: FLOAT, DOUBLE
+
+This encoding is adapted from the paper
+["ALP: Adaptive Lossless floating-Point 
Compression"](https://dl.acm.org/doi/10.1145/3626717)
+by Afroozeh and Boncz (SIGMOD 2024).
+
+ALP works by converting floating-point values to integers using decimal scaling
+(controlled by an *exponent* `e` and *factor* `f`), then applying Frame of
+Reference (FOR) encoding and bit-packing. Values that cannot be losslessly
+converted are stored separately as *exceptions*. The encoding achieves high
+compression for decimal-like floating-point data (e.g., monetary values, sensor
+readings) while remaining fully lossless. Each value is encoded independently,
+enabling random access to individual values and parallel encode/decode.
+
+#### Overview
+
+ALP encoding consists of a page-level header followed by an offset array and 
one
+or more encoded vectors (batches of values). Each vector contains up to
+`vector_size` elements (default 1024).
+
+```
++-------------+-----------------------------+--------------------------------------+
+|   Header    |        Offset Array         |            Vector Data           
    |
+|  (7 bytes)  |   (num_vectors * 4 bytes)   |            (variable)            
    |
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+| Page Header | off0 | off1 | ... | off N-1 | Vector 0 | Vector 1 | ... | Vec 
N-1  |
+|  (7 bytes)  | (4B) | (4B) |     |  (4B)   |(variable)|(variable)|     
|(variable)|
++-------------+------+------+-----+---------+----------+----------+-----+----------+
+```
+
+The compression pipeline below describes *one* way to produce a conforming
+vector. It is informative, not normative: an encoder may use any strategy as 
long
+as it emits the byte layout defined in [Page Layout](#page-layout). Only that
+byte layout and the [Decoding](#decoding) procedure are normative.
+
+```
+                    Input: float/double array
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  1. CHOOSE PARAMETERS                                    |
+    |     Select (exponent, factor) pair for this vector       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  2. DECIMAL ENCODING                                     |
+    |     encoded[i] = fast_round(value[i] * 10^e * 10^(-f))  |
+    |     Detect exceptions where decode(encode(v)) != v       |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  3. FRAME OF REFERENCE (FOR)                             |
+    |     min_val = min(encoded[:])                            |
+    |     delta[i] = encoded[i] - min_val                      |
+    +----------------------------------------------------------+
+                              |
+                              v
+    +----------------------------------------------------------+
+    |  4. BIT PACKING                                          |
+    |     bit_width = ceil(log2(max_delta + 1))                |
+    |     Pack each delta into bit_width bits                  |
+    +----------------------------------------------------------+
+                              |
+                              v
+                   Output: Serialized vector bytes
+```
+
+The `fast_round` used in step 2 is defined precisely in
+[Fast Rounding](#fast-rounding) below, including the exact magic-number values
+and the sign branching required for negative values.
+
+#### Page Layout
+
+##### Header (7 bytes)
+
+All multi-byte values are stored in little-endian order.
+
+```
+ Byte:    0              1               2              3    4    5    6
+       +----------------+---------------+--------------+----+----+----+----+
+       | compression    | integer       | log_vector   |     num_elements  |
+       | _mode          | _encoding     | _size        |     (int32 LE)    |
+       +----------------+---------------+--------------+----+----+----+----+
+```
+
+| Offset | Field | Size | Type | Description |
+|--------|-------|------|------|-------------|
+| 0 | compression_mode | 1 byte | uint8 | Compression mode (0 = ALP). Reserved 
for future variants (e.g., ALP-RD). |
+| 1 | integer_encoding | 1 byte | uint8 | Integer encoding (must be 0 = FOR + 
bit-packing) |
+| 2 | log_vector_size | 1 byte | uint8 | log2(vector\_size). Must be in the 
inclusive range \[3, 15\]. Recommended default: 10 (vector size 1024) |
+| 3 | num_elements | 4 bytes | int32 | Total number of floating-point values 
in the page |
+
+The number of vectors is `ceil(num_elements / vector_size)`. The last vector 
may
+contain fewer than `vector_size` elements.
+
+**Note:** The number of elements per vector is NOT stored in the header — it is
+derived: `vector_size` for all vectors except the last, which may be smaller.
+
+##### Offset Array
+
+Immediately following the header is an array of `num_vectors` little-endian 
uint32
+values. Each offset gives the byte position of the corresponding vector's data,
+measured from the start of the offset array itself.
+
+The first offset always equals `num_vectors * 4` (pointing just past the 
offset array).

Review Comment:
   Why `num_vectors * 4` but not `num_vectors * 4 + 7` to include the header? 
Usually the whole buffer is stored including header, so implementations need to 
manually add 7 each time to get an absolute offset to each vector.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to