@@ -49,6 +49,14 @@ public final class AlpCodec implements Codec {
4949 1e-0f , 1e-1f , 1e-2f , 1e-3f , 1e-4f , 1e-5f , 1e-6f , 1e-7f , 1e-8f , 1e-9f , 1e-10f
5050 };
5151
52+ private static final ValueLayout .OfLong LE_LONG = ValueLayout .JAVA_LONG_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
53+ private static final ValueLayout .OfDouble LE_DOUBLE = ValueLayout .JAVA_DOUBLE_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
54+ private static final ValueLayout .OfInt LE_INT = ValueLayout .JAVA_INT_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
55+ private static final ValueLayout .OfFloat LE_FLOAT = ValueLayout .JAVA_FLOAT_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
56+
57+ private static final DType I64_DTYPE = new DType .Primitive (PType .I64 , false );
58+ private static final DType I32_DTYPE = new DType .Primitive (PType .I32 , false );
59+
5260 private static Array decodeChildAs (DecodeContext parent , int childIdx , DType dtype , long rowCount ) {
5361 ArrayNode childNode = parent .node ().children ()[childIdx ];
5462 DecodeContext childCtx = new DecodeContext (
@@ -85,8 +93,6 @@ public EncodeResult encode(DType dtype, Object data) {
8593 throw new UnsupportedOperationException ("encode not supported by " + encodingId ());
8694 }
8795
88- // ── F32 ───────────────────────────────────────────────────────────────────
89-
9096 @ Override
9197 public Array decode (DecodeContext ctx ) {
9298 ByteBuffer rawMeta = ctx .metadata ();
@@ -117,102 +123,58 @@ public Array decode(DecodeContext ctx) {
117123 }
118124
119125 private Array decodeF64 (DecodeContext ctx , EncodingProtos .ALPMetadata meta , int expE , int expF , long n ) {
120- DType encodedDtype = new DType .Primitive (PType .I64 , false );
121- Array encoded = decodeChildAs (ctx , 0 , encodedDtype , n );
126+ Array encoded = decodeChildAs (ctx , 0 , I64_DTYPE , n );
122127
123128 // Precompute single factor — avoids 2 FP mults per element in the hot loop.
124129 double factor = F10_F64 [expF ] * IF10_F64 [expE ];
125130
126- MemorySegment out = ctx .arena ().allocate (n * 8 );
127- var srcLayout = ValueLayout .JAVA_LONG_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
128- var dstLayout = ValueLayout .JAVA_DOUBLE_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
129131 MemorySegment src = encoded .buffer (0 );
130- // Strength-reduce: running byte offset instead of i*8 per iteration.
131- for (long off = 0 , end = n * 8 ; off < end ; off += 8 ) {
132- long encVal = src .get (srcLayout , off );
133- double dec = (double ) encVal * factor ;
134- out .set (dstLayout , off , dec );
132+ MemorySegment out = ctx .arena ().allocate (n * 8 , 8 );
133+ for (long i = 0 ; i < n ; i ++) {
134+ out .setAtIndex (LE_DOUBLE , i , (double ) src .getAtIndex (LE_LONG , i ) * factor );
135135 }
136136
137137 if (meta .hasPatches ()) {
138- applyPatchesF64 (ctx , meta .getPatches (), out , n );
138+ applyPatches (ctx , meta .getPatches (), out , LE_LONG , 8 );
139139 }
140140
141141 return new Array (ctx .dtype (), n , new MemorySegment []{out .asReadOnly ()}, Array .NO_CHILDREN , ArrayStats .empty ());
142142 }
143143
144- // ── Helpers ───────────────────────────────────────────────────────────────
145-
146- private void applyPatchesF64 (DecodeContext ctx , EncodingProtos .PatchesMetadata pm ,
147- MemorySegment out , long n ) {
148- long numPatches = pm .getLen ();
149- long offset = pm .getOffset ();
150- PType idxPtype = ptypeFromProto (pm .getIndicesPtype ());
151-
152- DType idxDtype = new DType .Primitive (idxPtype , false );
153- DType valDtype = ctx .dtype ();
154-
155- Array idxArr = decodeChildAs (ctx , 1 , idxDtype , numPatches );
156- Array valArr = decodeChildAs (ctx , 2 , valDtype , numPatches );
157-
158- var valLayout = ValueLayout .JAVA_LONG_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
159- var dstLayout = ValueLayout .JAVA_LONG_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
160-
161- MemorySegment idxSeg = idxArr .buffer (0 );
162- MemorySegment valSeg = valArr .buffer (0 );
163-
164- for (long i = 0 ; i < numPatches ; i ++) {
165- long absIdx = readUnsigned (idxSeg , i , idxPtype ) - offset ;
166- long rawBits = valSeg .get (valLayout , i * 8 );
167- out .set (dstLayout , absIdx * 8 , rawBits );
168- }
169- }
170-
171144 private Array decodeF32 (DecodeContext ctx , EncodingProtos .ALPMetadata meta , int expE , int expF , long n ) {
172- DType encodedDtype = new DType .Primitive (PType .I32 , false );
173- Array encoded = decodeChildAs (ctx , 0 , encodedDtype , n );
145+ Array encoded = decodeChildAs (ctx , 0 , I32_DTYPE , n );
174146
147+ // Precompute single factor — avoids 2 FP mults per element in the hot loop.
175148 float factor = F10_F32 [expF ] * IF10_F32 [expE ];
176149
177- MemorySegment out = ctx .arena ().allocate (n * 4 );
178- var srcLayout = ValueLayout .JAVA_INT_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
179- var dstLayout = ValueLayout .JAVA_FLOAT_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
180150 MemorySegment src = encoded .buffer (0 );
181- for (long off = 0 , end = n * 4 ; off < end ; off += 4 ) {
182- int encVal = src .get (srcLayout , off );
183- float dec = (float ) encVal * factor ;
184- out .set (dstLayout , off , dec );
151+ MemorySegment out = ctx .arena ().allocate (n * 4 , 4 );
152+ for (long i = 0 ; i < n ; i ++) {
153+ out .setAtIndex (LE_FLOAT , i , (float ) src .getAtIndex (LE_INT , i ) * factor );
185154 }
186155
187156 if (meta .hasPatches ()) {
188- applyPatchesF32 (ctx , meta .getPatches (), out , n );
157+ applyPatches (ctx , meta .getPatches (), out , LE_INT , 4 );
189158 }
190159
191160 return new Array (ctx .dtype (), n , new MemorySegment []{out .asReadOnly ()}, Array .NO_CHILDREN , ArrayStats .empty ());
192161 }
193162
194- private void applyPatchesF32 (DecodeContext ctx , EncodingProtos .PatchesMetadata pm ,
195- MemorySegment out , long n ) {
163+ private void applyPatches (DecodeContext ctx , EncodingProtos .PatchesMetadata pm ,
164+ MemorySegment out , ValueLayout elemLayout , int elemBytes ) {
196165 long numPatches = pm .getLen ();
197166 long offset = pm .getOffset ();
198167 PType idxPtype = ptypeFromProto (pm .getIndicesPtype ());
199168
200- DType idxDtype = new DType .Primitive (idxPtype , false );
201- DType valDtype = ctx .dtype ();
202-
203- Array idxArr = decodeChildAs (ctx , 1 , idxDtype , numPatches );
204- Array valArr = decodeChildAs (ctx , 2 , valDtype , numPatches );
205-
206- var valLayout = ValueLayout .JAVA_INT_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
207- var dstLayout = ValueLayout .JAVA_INT_UNALIGNED .withOrder (ByteOrder .LITTLE_ENDIAN );
169+ Array idxArr = decodeChildAs (ctx , 1 , new DType .Primitive (idxPtype , false ), numPatches );
170+ Array valArr = decodeChildAs (ctx , 2 , ctx .dtype (), numPatches );
208171
209172 MemorySegment idxSeg = idxArr .buffer (0 );
210173 MemorySegment valSeg = valArr .buffer (0 );
211174
212175 for (long i = 0 ; i < numPatches ; i ++) {
213176 long absIdx = readUnsigned (idxSeg , i , idxPtype ) - offset ;
214- int rawBits = valSeg .get (valLayout , i * 4 );
215- out .set (dstLayout , absIdx * 4 , rawBits );
177+ MemorySegment .copy (valSeg , i * elemBytes , out , absIdx * elemBytes , elemBytes );
216178 }
217179 }
218180}
0 commit comments