-
Notifications
You must be signed in to change notification settings - Fork 38
Add fastPfor decoder to Typescript #714
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Turtelll
wants to merge
29
commits into
maplibre:main
Choose a base branch
from
Turtelll:fastPfor
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 23 commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
23e531c
add getFeatures() methode to access features without Iterator
e470b6e
Revert "add getFeatures() methode to access features without Iterator"
b609a5c
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec
f78f778
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec
877bd7c
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec
077dab0
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec
0359a9a
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec
db9b846
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec
ef388d8
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec
401c231
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec
5fdb210
Merge branch 'main' of https://github.com/Turtelll/maplibre-tile-spec
96ad804
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec
31b6bc0
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec
b79d4e6
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec
14fab73
fastPfor decoder implementation
c497fdb
export fastPfor decoder implementation with other physical level tech…
80578a8
add alignment check for Int32Array buffer reads
6c1a917
add fastPfor decoding tests
245bc57
Merge branch 'main' of https://github.com/maplibre/maplibre-tile-spec…
bb864d0
comment
0787763
refactor fastPfor test
284054e
refactor fastPfor test
8acb844
delete json data
dd30539
use .bin data for fastPfor test
d505195
add more test cases to fastPfor test
361d374
fix nullable RLE offset tracking prevent dynamic loop condition bug
fdd49c1
add byteLength param to RLE decoders
1d4db71
fix filepath for fastPfor tests
8f449aa
add byteLength param to RLE in main decoder
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| import {describe, expect, it} from "vitest"; | ||
| import {decodeFastPfor} from "./fastPforDecoder"; | ||
| import IntWrapper from "./intWrapper"; | ||
|
|
||
| // encoded data was generated using the java fastPfor encoder and expected values are re-generated in the tests | ||
| const ENCODED_NON_ALINGED_358_ENCODED = new Uint8Array([0, 0, 1, 0, 0, 0, 0, 65, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 19, 18, 17, 16, 23, 22, 21, 20, 27, 26, 25, 24, 31, 30, 29, 28, 35, 34, 33, 32, 39, 38, 37, 36, 43, 42, 41, 40, 47, 46, 45, 44, 51, 50, 49, 48, 55, 54, 53, 52, | ||
| 59, 58, 57, 56, 63, 62, 61, 60, 67, 66, 65, 64, 71, 70, 69, 68, 75, 74, 73, 72, 79, 78, 77, 76, 83, 82, 81, 80, 87, 86, 85, 84, 91, 90, 89, 88, 95, 94, 93, 92, 99, 98, 97, 96, 103, 102, 101, 100, 107, 106, 105, 104, 111, 110, 109, 108, 115, 114, 113, 112, 119, 118, 117, 116, | ||
| 123, 122, 121, 120, 127, 126, 125, 124, 131, 130, 129, 128, 135, 134, 133, 132, 139, 138, 137, 136, 143, 142, 141, 140, 147, 146, 145, 144, 151, 150, 149, 148, 155, 154, 153, 152, 159, 158, 157, 156, 163, 162, 161, 160, 167, 166, 165, 164, 171, 170, 169, 168, 175, 174, 173, 172, 179, 178, 177, 176, 183, 182, 181, 180, | ||
| 187, 186, 185, 184, 191, 190, 189, 188, 195, 194, 193, 192, 199, 198, 197, 196, 203, 202, 201, 200, 207, 206, 205, 204, 211, 210, 209, 208, 215, 214, 213, 212, 219, 218, 217, 216, 223, 222, 221, 220, 227, 226, 225, 224, 231, 230, 229, 228, 235, 234, 233, 232, 239, 238, 237, 236, 243, 242, 241, 240, 247, 246, 245, 244, | ||
| 251, 250, 249, 248, 255, 254, 253, 252, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 0, 130, 1, 130, 0, 130, 3, 130, 2, 130, 5, 130, 4, 130, 7, 130, 6, 130, 9, 130, 8, 130, 11, 130, 10, 130, 13, 130, 12, 130, 15, 130, 14, 130, 17, 130, 16, 130, 19, 130, 18, 130, 21, 130, 20, | ||
| 130, 23, 130, 22, 130, 25, 130, 24, 130, 27, 130, 26, 130, 29, 130, 28, 130, 31, 130, 30, 130, 33, 130, 32, 130, 35, 130, 34, 130, 37, 130, 36, 130, 39, 130, 38, 130, 41, 130, 40, 130, 43, 130, 42, 130, 45, 130, 44, 130, 47, 130, 46, 130, 49, 130, 48, 130, 51, 130, 50, 130, 53, 130, 52, | ||
| 130, 55, 130, 54, 130, 57, 130, 56, 130, 59, 130, 58, 130, 61, 130, 60, 130, 63, 130, 62, 130, 65, 130, 64, 130, 67, 130, 66, 130, 69, 130, 68, 130, 71, 130, 70, 130, 73, 130, 72, 130, 75, 130, 74, 130, 77, 130, 76, 130, 79, 130, 78, 130, 81, 130, 80, 130, 83, 130, 82, 130, 85, 130, 84, | ||
| 130, 87, 130, 86, 130, 89, 130, 88, 130, 91, 130, 90, 130, 93, 130, 92, 130, 95, 130, 94, 130, 97, 130, 96, 130, 99, 130, 98, 130, 101, 130, 100],); | ||
|
|
||
| const LARGE_EXCEPTIONS_ENCODED = new Uint8Array([ | ||
| 0, 0, 1, 0, 0, 0, 0, 25, 191, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 254, 63, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 143, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||
| 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 7, 10, 27, 4, 3, 0, 200, 100, 50, 0, 128, 0, 0, 0, 0, 0, 4, 196, 190, 204, 252, | ||
| 14, 166, 0, 9, 95, 94, 16, 0, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, | ||
| 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, | ||
| 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, | ||
| 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135],); | ||
|
|
||
| const SEQUENTIAL_ENCODED = new Uint8Array([0, 0, 2, 0, 0, 0, 0, 137, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 19, 18, 17, 16, 23, 22, 21, 20, 27, 26, 25, 24, 31, 30, 29, 28, 35, 34, 33, 32, 39, 38, 37, 36, 43, 42, 41, 40, 47, 46, 45, 44, 51, 50, 49, 48, 55, 54, 53, 52, | ||
| 59, 58, 57, 56, 63, 62, 61, 60, 67, 66, 65, 64, 71, 70, 69, 68, 75, 74, 73, 72, 79, 78, 77, 76, 83, 82, 81, 80, 87, 86, 85, 84, 91, 90, 89, 88, 95, 94, 93, 92, 99, 98, 97, 96, 103, 102, 101, 100, 107, 106, 105, 104, 111, 110, 109, 108, 115, 114, 113, 112, 119, 118, 117, 116, 123, 122, 121, 120, 127, 126, 125, 124, 131, 130, 129, 128, 135, 134, 133, 132, 139, 138, 137, 136, 143, 142, 141, 140, 147, 146, 145, 144, 151, 150, 149, 148, | ||
| 155, 154, 153, 152, 159, 158, 157, 156, 163, 162, 161, 160, 167, 166, 165, 164, 171, 170, 169, 168, 175, 174, 173, 172, 179, 178, 177, 176, 183, 182, 181, 180, 187, 186, 185, 184, 191, 190, 189, 188, 195, 194, 193, 192, 199, 198, 197, 196, 203, 202, 201, 200, 207, 206, 205, 204, 211, 210, 209, 208, 215, 214, 213, 212, | ||
| 219, 218, 217, 216, 223, 222, 221, 220, 227, 226, 225, 224, 231, 230, 229, 228, 235, 234, 233, 232, 239, 238, 237, 236, 243, 242, 241, 240, 247, 246, 245, 244, 251, 250, 249, 248, 255, 254, 253, 252, 28, 10, 3, 0, 193, 160, 176, 72, 42, 19, 8, 131, 161, 176, 200, 92, 35, 16, 135, 195, 177, 72, 156, 74, | ||
| 24, 139, 197, 162, 200, 220, 106, 51, 143, 199, 163, 177, 28, 138, 67, 32, 201, 164, 178, 73, 170, 83, 40, 147, 165, 178, 201, 92, 99, 48, 151, 203, 179, 73, 156, 202, 56, 155, 205, 166, 201, 220, 234, 115, 159, 207, 167, 179, 29, 10, 131, 64, 209, 168, 180, 74, 42, 147, 72, 163, 169, 180, 202, 93, | ||
| 163, 80, 167, 211, 181, 74, 157, 74, 88, 171, 213, 170, 202, 221, 106, 179, 175, 215, 171, 181, 29, 138, 195, 96, 217, 172, 182, 75, 170, 211, 104, 179, 173, 182, 203, 93, 227, 112, 183, 219, 183, 75, 157, 202, 120, 187, 221, 174, 203, 221, 234, 243, 191, 223, 175, 183, 30, 11, 3, 128, 225, 176, 184, 76, | ||
| 43, 19, 136, 195, 177, 184, 204, 94, 35, 144, 199, 227, 185, 76, 158, 75, 152, 203, 229, 178, 204, 222, 107, 51, 207, 231, 179, 185, 30, 139, 67, 160, 233, 180, 186, 77, 171, 83, 168, 211, 181, 186, 205, 94, 99, 176, 215, 235, 187, 77, 158, 203, 184, 219, 237, 182, 205, 222, 235, 115, 223, 239, 183, 187, | ||
| 31, 11, 131, 192, 241, 184, 188, 78, 43, 147, 200, 227, 185, 188, 206, 95, 163, 208, 231, 243, 189, 78, 159, 75, 216, 235, 245, 186, 206, 223, 107, 179, 239, 247, 187, 189, 31, 139, 195, 224, 249, 188, 190, 79, 171, 211, 232, 243, 189, 190, 207, 95, 227, 240, 247, 251, 191, 79, 159, 203, 248, 251, 253, 190, | ||
| 207, 223, 235, 243, 255, 255, 191, 191, 0, 0, 0, 4, 0, 9, 0, 8, 0, 0, 0, 0]); | ||
|
|
||
| const SMAL_VALUES_ENCODED = new Uint8Array([0, 0, 1, 0, 0, 0, 0, 25, 136, 250, 198, 136, 198, 136, 250, 198, 250, 198, 136, 250, 136, 250, 198, 136, 198, 136, 250, 198, 250, 198, 136, 250, 136, 250, 198, 136, 198, 136, 250, 198, 250, 198, 136, 250, 136, 250, 198, 136, 198, 136, 250, 198, 250, 198, 136, 250, 136, 250, 198, 136, 198, 136, 250, 198, | ||
| 250, 198, 136, 250, 136, 250, 198, 136, 198, 136, 250, 198, 250, 198, 136, 250, 136, 250, 198, 136, 198, 136, 250, 198, 250, 198, 136, 250, 136, 250, 198, 136, 198, 136, 250, 198, 250, 198, 136, 250, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0]); | ||
|
|
||
| const ZEROS_ENCODED = new Uint8Array([0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]); | ||
|
|
||
| describe("FastPFOR Decoder - Java Generated Test Vectors", () => { | ||
|
|
||
| describe("Core Functionality", () => { | ||
| it("should decode non_aligned_358 (256 FastPFOR + 102 VariableByte)", () => { | ||
| const decoded = decodeFastPfor(ENCODED_NON_ALINGED_358_ENCODED, 358, 480, new IntWrapper(0)); | ||
|
|
||
| expect(decoded.length).toBe(358); | ||
| for(let i = 0; i < 358; i++) { | ||
| expect(decoded[i]).toBe(i) | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| describe("Exception Handling", () => { | ||
| it("should decode large_exceptions", () => { | ||
| const decoded = decodeFastPfor(LARGE_EXCEPTIONS_ENCODED, 500, 380, new IntWrapper(0)); | ||
|
|
||
| expect(decoded.length).toBe(500); | ||
| for(let i = 0; i < 10; i++) { | ||
| expect(decoded[i]).toBe(7) | ||
| } | ||
|
|
||
| // exceptions | ||
| expect(decoded[10]).toBe(100034530); | ||
| expect(decoded[50]).toBe(20000); | ||
| expect(decoded[100]).toBe(30000) | ||
| expect(decoded[499]).toBe(7) | ||
| }); | ||
|
|
||
| it("should decode small_values (3-bit wide)", () => { | ||
| const decoded = decodeFastPfor(SMAL_VALUES_ENCODED, 256, 116, new IntWrapper(0)); | ||
| for (let i = 0; i < 256; i++) { | ||
| expect(decoded[i]).toBe(i % 8); | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| describe("Special Cases", () => { | ||
| it("should decode zeros (all zeros)", () => { | ||
| const decoded = decodeFastPfor(ZEROS_ENCODED, 265, 20, new IntWrapper(0)); | ||
|
|
||
| expect(decoded.length).toBe(265); | ||
| expect(Array.from(decoded).every((v) => v === 0)).toBe(true); | ||
| }); | ||
|
|
||
| it("should decode sequential (512 values)", () => { | ||
| const decoded = decodeFastPfor(SEQUENTIAL_ENCODED, 512, 564, new IntWrapper(0)); | ||
|
|
||
| expect(decoded.length).toBe(512); | ||
|
|
||
| // Sequential values 0-511 | ||
| for (let i = 0; i < 512; i++) { | ||
| expect(decoded[i]).toBe(i); | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| describe("Offset Handling", () => { | ||
| it("should handle non-zero initial offset", () => { | ||
| // Add padding before the actual data | ||
| const padding = new Uint8Array(32); | ||
| const combined = new Uint8Array(padding.length + SMAL_VALUES_ENCODED.length); | ||
| combined.set(padding, 0); | ||
| combined.set(SMAL_VALUES_ENCODED, padding.length); | ||
|
|
||
| const offset = new IntWrapper(32); | ||
| const decoded = decodeFastPfor(combined, 256, 116, offset); | ||
|
|
||
| expect(decoded.length).toBe(256); | ||
| expect(offset.get()).toBe(32 + Math.ceil(116 / 4) * 4); | ||
|
|
||
| // Verify first few values | ||
| for (let i = 0; i < 10; i++) { | ||
| expect(decoded[i]).toBe(i % 8); | ||
| } | ||
| }); | ||
|
|
||
| it("should advance offset correctly for sequential decoding", () => { | ||
| // Combine two encoded streams | ||
| const combined = new Uint8Array(Math.ceil(20 / 4) * 4 + Math.ceil(116 / 4) * 4); | ||
| combined.set(ZEROS_ENCODED, 0); | ||
| combined.set(SMAL_VALUES_ENCODED, Math.ceil(20 / 4) * 4); | ||
|
|
||
| const offset = new IntWrapper(0); | ||
|
|
||
| // Decode first stream | ||
| const decoded1 = decodeFastPfor(ZEROS_ENCODED, 256, 20, offset); | ||
| expect(decoded1.length).toBe(256); | ||
| expect(Array.from(decoded1).every((v) => v === 0)).toBe(true); | ||
|
|
||
| // Decode second stream | ||
| const decoded2 = decodeFastPfor(combined, 256, 116, offset); | ||
| expect(decoded2.length).toBe(256); | ||
| for (let i = 0; i < 10; i++) { | ||
| expect(decoded2[i]).toBe(i % 8); | ||
| } | ||
| }); | ||
| }); | ||
| }); | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add the FastPfor test data as binary files to keep the tests more clean.
Also let's add more test cases to ensure that the implementation is also valid for edge cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i switched to using binary files and will add more tests