FZGPUModules 2.0
GPU-accelerated modular compression pipelines
Loading...
Searching...
No Matches
stage_factory.h
Go to the documentation of this file.
1#pragma once
2
8#include "stage/stage.h"
9#include "fzm_format.h"
11#include "coders/rle/rle.h"
29
30#include <memory>
31#include <stdexcept>
32#include <cstring>
33
34namespace fz {
35
45inline Stage* createStage(StageType type, const uint8_t* config, size_t config_size) {
46 Stage* stage = nullptr;
47
48 switch (type) {
49 case StageType::LORENZO_QUANT: {
50 // Dims are restored by deserializeHeader(); template types come from stored fields.
51 if (config_size >= sizeof(LorenzoQuantConfig)) {
53 std::memcpy(&lc, config, sizeof(LorenzoQuantConfig));
54 if (lc.input_type == DataType::FLOAT32 && lc.code_type == DataType::UINT16) {
56 s->deserializeHeader(config, config_size);
57 stage = s;
58 } else if (lc.input_type == DataType::FLOAT64 && lc.code_type == DataType::UINT16) {
60 s->deserializeHeader(config, config_size);
61 stage = s;
62 } else {
63 throw std::runtime_error(
64 "Unsupported Lorenzo template instantiation: input_type="
65 + std::to_string(static_cast<int>(lc.input_type))
66 + " code_type=" + std::to_string(static_cast<int>(lc.code_type)));
67 }
68 } else {
69 throw std::runtime_error("Lorenzo config too small: " + std::to_string(config_size));
70 }
71 break;
72 }
73
74 case StageType::DIFFERENCE: {
75 // Header: [0] TIn DataType, [1] TOut DataType, [2..5] chunk_size, [6] FusionMode (fused only).
76 // TIn == TOut → same-type (legacy); TIn signed + TOut unsigned → fused
77 // (byte 6 selects NEGABINARY (default, for 6-byte legacy headers) vs. ZIGZAG).
78 if (config_size >= 2) {
79 DataType tin_dt = static_cast<DataType>(config[0]);
80 DataType tout_dt = static_cast<DataType>(config[1]);
82 if (config_size >= 7) mode = static_cast<FusionMode>(config[6]);
83 // Negabinary/zigzag-fused instantiations
84 if (tin_dt == DataType::INT8 && tout_dt == DataType::UINT8) {
85 stage = (mode == FusionMode::ZIGZAG)
88 } else if (tin_dt == DataType::INT16 && tout_dt == DataType::UINT16) {
89 stage = (mode == FusionMode::ZIGZAG)
92 } else if (tin_dt == DataType::INT32 && tout_dt == DataType::UINT32) {
93 stage = (mode == FusionMode::ZIGZAG)
96 } else if (tin_dt == DataType::INT64 && tout_dt == DataType::UINT64) {
97 stage = (mode == FusionMode::ZIGZAG)
100 }
101 // Same-type instantiations
102 else if (tin_dt == DataType::FLOAT32) stage = new DifferenceStage<float>();
103 else if (tin_dt == DataType::FLOAT64) stage = new DifferenceStage<double>();
104 else if (tin_dt == DataType::UINT8) stage = new DifferenceStage<uint8_t>();
105 else if (tin_dt == DataType::UINT16) stage = new DifferenceStage<uint16_t>();
106 else if (tin_dt == DataType::UINT32) stage = new DifferenceStage<uint32_t>();
107 else if (tin_dt == DataType::INT32) stage = new DifferenceStage<int32_t>();
108 else if (tin_dt == DataType::INT64) stage = new DifferenceStage<int64_t>();
109 else
110 throw std::runtime_error("Unsupported Difference data type: "
111 + std::to_string(static_cast<int>(tin_dt)));
112 stage->deserializeHeader(config, config_size);
113 } else if (config_size >= 1) {
114 // Legacy 1-byte header (same-type only)
115 DataType dt = static_cast<DataType>(config[0]);
116 switch (dt) {
117 case DataType::FLOAT32: stage = new DifferenceStage<float>(); break;
118 case DataType::FLOAT64: stage = new DifferenceStage<double>(); break;
119 case DataType::UINT8: stage = new DifferenceStage<uint8_t>(); break;
120 case DataType::UINT16: stage = new DifferenceStage<uint16_t>(); break;
121 case DataType::UINT32: stage = new DifferenceStage<uint32_t>(); break;
122 case DataType::INT32: stage = new DifferenceStage<int32_t>(); break;
123 case DataType::INT64: stage = new DifferenceStage<int64_t>(); break;
124 default:
125 throw std::runtime_error("Unsupported Difference data type: "
126 + std::to_string(static_cast<int>(dt)));
127 }
128 } else {
129 stage = new DifferenceStage<float>();
130 }
131 break;
132 }
133
134 case StageType::QUANTIZER: {
135 if (config_size < sizeof(QuantizerConfig)) {
136 throw std::runtime_error(
137 "QuantizerConfig too small: " + std::to_string(config_size));
138 }
140 std::memcpy(&qc, config, sizeof(QuantizerConfig));
141 if (qc.input_type == DataType::FLOAT32 && qc.code_type == DataType::UINT16) {
142 auto* s = new QuantizerStage<float, uint16_t>();
143 s->deserializeHeader(config, config_size);
144 stage = s;
145 } else if (qc.input_type == DataType::FLOAT32 && qc.code_type == DataType::UINT32) {
146 auto* s = new QuantizerStage<float, uint32_t>();
147 s->deserializeHeader(config, config_size);
148 stage = s;
149 } else if (qc.input_type == DataType::FLOAT64 && qc.code_type == DataType::UINT16) {
150 auto* s = new QuantizerStage<double, uint16_t>();
151 s->deserializeHeader(config, config_size);
152 stage = s;
153 } else if (qc.input_type == DataType::FLOAT64 && qc.code_type == DataType::UINT32) {
154 auto* s = new QuantizerStage<double, uint32_t>();
155 s->deserializeHeader(config, config_size);
156 stage = s;
157 } else {
158 throw std::runtime_error(
159 "Unsupported QuantizerStage types: input_type="
160 + std::to_string(static_cast<int>(qc.input_type))
161 + " code_type=" + std::to_string(static_cast<int>(qc.code_type)));
162 }
163 break;
164 }
165
166 case StageType::RLE: {
167 if (config_size >= 1) {
168 DataType dt;
169 std::memcpy(&dt, config, sizeof(DataType));
170 switch (dt) {
171 case DataType::UINT8: stage = new RLEStage<uint8_t>(); break;
172 case DataType::UINT16: stage = new RLEStage<uint16_t>(); break;
173 case DataType::UINT32: stage = new RLEStage<uint32_t>(); break;
174 case DataType::UINT64: stage = new RLEStage<uint64_t>(); break;
175 case DataType::INT8: stage = new RLEStage<int8_t>(); break;
176 case DataType::INT16: stage = new RLEStage<int16_t>(); break;
177 case DataType::INT32: stage = new RLEStage<int32_t>(); break;
178 case DataType::INT64: stage = new RLEStage<int64_t>(); break;
179 default:
180 throw std::runtime_error("Unsupported RLE data type: "
181 + std::to_string(static_cast<int>(dt)));
182 }
183 stage->deserializeHeader(config, config_size);
184 } else {
185 // No config — default to uint16_t
186 stage = new RLEStage<uint16_t>();
187 }
188 break;
189 }
190
191 case StageType::ZIGZAG: {
192 if (config_size >= 2) {
193 DataType tin_dt = static_cast<DataType>(config[0]);
194 DataType tout_dt = static_cast<DataType>(config[1]);
195 if (tin_dt == DataType::INT8 && tout_dt == DataType::UINT8)
196 stage = new ZigzagStage<int8_t, uint8_t>();
197 else if (tin_dt == DataType::INT16 && tout_dt == DataType::UINT16)
198 stage = new ZigzagStage<int16_t, uint16_t>();
199 else if (tin_dt == DataType::INT32 && tout_dt == DataType::UINT32)
200 stage = new ZigzagStage<int32_t, uint32_t>();
201 else if (tin_dt == DataType::INT64 && tout_dt == DataType::UINT64)
202 stage = new ZigzagStage<int64_t, uint64_t>();
203 else
204 throw std::runtime_error(
205 "Unsupported ZigzagStage type pair: TIn="
206 + std::to_string(static_cast<int>(tin_dt))
207 + " TOut=" + std::to_string(static_cast<int>(tout_dt)));
208 } else {
209 // Default: int32_t → uint32_t
210 stage = new ZigzagStage<int32_t, uint32_t>();
211 }
212 stage->deserializeHeader(config, config_size);
213 break;
214 }
215
216 case StageType::NEGABINARY: {
217 if (config_size >= 2) {
218 DataType tin_dt = static_cast<DataType>(config[0]);
219 DataType tout_dt = static_cast<DataType>(config[1]);
220 if (tin_dt == DataType::INT8 && tout_dt == DataType::UINT8)
222 else if (tin_dt == DataType::INT16 && tout_dt == DataType::UINT16)
224 else if (tin_dt == DataType::INT32 && tout_dt == DataType::UINT32)
226 else if (tin_dt == DataType::INT64 && tout_dt == DataType::UINT64)
228 else
229 throw std::runtime_error(
230 "Unsupported NegabinaryStage type pair: TIn="
231 + std::to_string(static_cast<int>(tin_dt))
232 + " TOut=" + std::to_string(static_cast<int>(tout_dt)));
233 } else {
235 }
236 stage->deserializeHeader(config, config_size);
237 break;
238 }
239
240 case StageType::BITSHUFFLE: {
241 auto* s = new BitshuffleStage();
242 s->deserializeHeader(config, config_size);
243 stage = s;
244 break;
245 }
246
247 case StageType::BITPACK: {
248 // config[0] holds the DataType of T; use it to pick the instantiation.
249 DataType dt = (config_size > 0)
250 ? static_cast<DataType>(config[0])
251 : DataType::UINT16;
252 if (dt == DataType::UINT8) stage = new BitpackStage<uint8_t>();
253 else if (dt == DataType::UINT16) stage = new BitpackStage<uint16_t>();
254 else if (dt == DataType::UINT32) stage = new BitpackStage<uint32_t>();
255 else throw std::runtime_error(
256 "Unsupported BitpackStage DataType: "
257 + std::to_string(static_cast<int>(dt)));
258 stage->deserializeHeader(config, config_size);
259 break;
260 }
261
262 case StageType::RZE: {
263 auto* s = new RZEStage();
264 s->deserializeHeader(config, config_size);
265 stage = s;
266 break;
267 }
268
269 case StageType::RRE: {
270 auto* s = new RREStage();
271 s->deserializeHeader(config, config_size);
272 stage = s;
273 break;
274 }
275
276 case StageType::MERGE: {
277 auto* s = new MergeStage();
278 s->deserializeHeader(config, config_size);
279 stage = s;
280 break;
281 }
282
283 case StageType::HUFFMAN: {
284 // config[0] holds the DataType of T; use it to pick the instantiation.
285 DataType dt = (config_size > 0)
286 ? static_cast<DataType>(config[0])
287 : DataType::UINT16;
288 if (dt == DataType::UINT8) stage = new HuffmanStage<uint8_t>();
289 else if (dt == DataType::UINT16) stage = new HuffmanStage<uint16_t>();
290 else if (dt == DataType::UINT32) stage = new HuffmanStage<uint32_t>();
291 else throw std::runtime_error(
292 "Unsupported HuffmanStage DataType: "
293 + std::to_string(static_cast<int>(dt)));
294 stage->deserializeHeader(config, config_size);
295 break;
296 }
297
298 case StageType::LORENZO: {
299 DataType dt = (config_size >= sizeof(LorenzoConfig))
300 ? static_cast<DataType>(config[0])
301 : DataType::INT32;
302 if (dt == DataType::INT8) stage = new LorenzoStage<int8_t>();
303 else if (dt == DataType::INT16) stage = new LorenzoStage<int16_t>();
304 else if (dt == DataType::INT32) stage = new LorenzoStage<int32_t>();
305 else if (dt == DataType::INT64) stage = new LorenzoStage<int64_t>();
306 else throw std::runtime_error(
307 "Unsupported LorenzoStage DataType: "
308 + std::to_string(static_cast<int>(dt)));
309 stage->deserializeHeader(config, config_size);
310 break;
311 }
312
313 case StageType::ANS: {
314 auto* s = new ANSStage();
315 s->deserializeHeader(config, config_size);
316 stage = s;
317 break;
318 }
319
320 case StageType::ADM: {
321 auto* s = new ADMStage();
322 s->deserializeHeader(config, config_size);
323 stage = s;
324 break;
325 }
326
327 case StageType::G_INTERP: {
328 // Code type stored in config[5] (DataType code_type in GInterpConfig).
329 if (config_size < sizeof(GInterpConfig)) {
330 throw std::runtime_error(
331 "GInterp config too small: " + std::to_string(config_size));
332 }
333 GInterpConfig gc;
334 std::memcpy(&gc, config, sizeof(GInterpConfig));
335 auto make_ginterp = [&](auto input_tag) {
336 using TInput = decltype(input_tag);
337 if (gc.code_type == DataType::UINT8) {
338 auto* s = new GInterpStage<TInput, uint8_t>();
339 s->deserializeHeader(config, config_size);
340 stage = s;
341 } else if (gc.code_type == DataType::UINT16) {
342 auto* s = new GInterpStage<TInput, uint16_t>();
343 s->deserializeHeader(config, config_size);
344 stage = s;
345 } else if (gc.code_type == DataType::UINT32) {
346 auto* s = new GInterpStage<TInput, uint32_t>();
347 s->deserializeHeader(config, config_size);
348 stage = s;
349 } else {
350 throw std::runtime_error(
351 "Unsupported GInterp code_type: "
352 + std::to_string(static_cast<int>(gc.code_type)));
353 }
354 };
355 if (gc.input_type == DataType::FLOAT32) {
356 make_ginterp(float{});
357 } else if (gc.input_type == DataType::FLOAT64) {
358 make_ginterp(double{});
359 } else {
360 throw std::runtime_error(
361 "Unsupported GInterp input_type: "
362 + std::to_string(static_cast<int>(gc.input_type)));
363 }
364 break;
365 }
366
368 auto* s = new BitplaneRZEStage();
369 s->deserializeHeader(config, config_size);
370 stage = s;
371 break;
372 }
373
375 // config[0] holds the DataType of T (INT16 / INT32).
376 DataType dt = (config_size > 0)
377 ? static_cast<DataType>(config[0])
378 : DataType::INT32;
379 if (dt == DataType::INT16) stage = new AdaptiveBitpackStage<int16_t>();
380 else if (dt == DataType::INT32) stage = new AdaptiveBitpackStage<int32_t>();
381 else throw std::runtime_error(
382 "Unsupported AdaptiveBitpackStage DataType: "
383 + std::to_string(static_cast<int>(dt)));
384 stage->deserializeHeader(config, config_size);
385 break;
386 }
387
389 // config[0] holds the DataType of T (INT16 / INT32).
390 DataType dt = (config_size > 0)
391 ? static_cast<DataType>(config[0])
392 : DataType::INT32;
393 if (dt == DataType::INT16) stage = new TiledLorenzoStage<int16_t>();
394 else if (dt == DataType::INT32) stage = new TiledLorenzoStage<int32_t>();
395 else throw std::runtime_error(
396 "Unsupported TiledLorenzoStage DataType: "
397 + std::to_string(static_cast<int>(dt)));
398 stage->deserializeHeader(config, config_size);
399 break;
400 }
401
402 default:
403 throw std::runtime_error("Unknown stage type: "
404 + std::to_string(static_cast<uint16_t>(type)));
405 }
406
407 return stage;
408}
409
410} // namespace fz
Per-block adaptive fixed-rate bit-plane coder (cuSZp-style plain mode).
Adaptive Data Mapping (ADM) stage — remaps u16/u32 integer streams into a compact 8-bit symbol domain...
rANS entropy coding stage (GPU, via vendored dietGPU kernel templates).
Bit-packing stage: packs N-bit integers into a dense byte stream.
Fused bitplane-transpose + zero-group RZE stage — the FZ-GPU lossless encoder, ported as a single-ker...
GPU bit-matrix transpose stage (W × N bit shuffle over fixed-size chunks).
Definition adaptive_bitpack_stage.h:75
Definition bitpack_stage.h:47
Definition bitplane_rze_stage.h:60
Definition bitshuffle_stage.h:43
Definition diff.h:71
Definition ginterp_stage.h:204
Definition huffman_stage.h:68
Definition lorenzo_quant.h:96
Definition lorenzo_stage.h:53
Definition merge_stage.h:68
Definition negabinary_stage.h:34
Definition quantizer.h:111
Definition rle.h:47
Definition rre_stage.h:54
Definition rze_stage.h:55
Definition stage.h:30
virtual void deserializeHeader(const uint8_t *header_buffer, size_t size)
Definition stage.h:149
Definition tiled_lorenzo_stage.h:70
Definition zigzag_stage.h:30
First-order difference coding stage with optional negabinary fusion.
FZM binary file format definitions — structs, enums, and helpers.
G-Interp spline-interpolation predictor + quantizer (cuSZ-Hi port).
Huffman entropy coding stage with selectable encode mode.
Fused Lorenzo predictor and quantizer stage.
Plain integer Lorenzo predictor (delta coding / prefix sum). Lossless.
MergeStage — concatenate N input buffers into one, split back to N.
Definition fzm_format.h:25
Stage * createStage(StageType type, const uint8_t *config, size_t config_size)
Definition stage_factory.h:45
FusionMode
Definition diff.h:28
@ ZIGZAG
LC's DIFFMS — Zigzag<T>::encode/decode (sign-magnitude/TCMS).
@ NEGABINARY
LC's DIFFNB — Negabinary<T>::encode/decode.
StageType
Stage type identifiers written into the FZM header.
Definition fzm_format.h:76
@ ADAPTIVE_BITPACK
Per-block adaptive fixed-rate bit-plane coder (cuSZp plain mode)
@ ANS
rANS entropy coder (GPU, via dietGPU)
@ RRE
Repetition-Reduction Encoding (LC framework lossless component)
@ ADM
Adaptive Data Mapping transform (MANS)
@ TILED_LORENZO
Dimension-aware (tiled separable) Lorenzo predictor (cuSZp3 delta)
@ BITPLANE_RZE
Fused bitplane transpose + zero-group RZE (FZ-GPU lossless encoder)
@ G_INTERP
Spline interpolation predictor + quantizer (cuSZ-Hi G-Interp)
DataType
Element data type identifiers used in buffer and stage descriptors.
Definition fzm_format.h:109
Element-wise negabinary encode/decode stage (TIn[] ↔ TOut[]).
Direct-value quantizer stage with error-bounded coding and lossless outlier fallback.
Run-Length Encoding stage (lossless, stream-ordered).
Repetition-Reduction Encoding stage — lossless byte-stream compressor.
Zero-Elimination Encoding stage — lossless byte-stream compressor.
Base class interface for all compression stages.
Definition ginterp_stage.h:39
DataType code_type
Quant code type (1 B).
Definition ginterp_stage.h:47
DataType input_type
Float input type (1 B).
Definition ginterp_stage.h:46
Definition lorenzo_stage.h:28
Definition lorenzo_quant.h:43
DataType input_type
Original input type (1B).
Definition lorenzo_quant.h:48
DataType code_type
Quantization code type (1B).
Definition lorenzo_quant.h:49
Definition quantizer.h:25
DataType code_type
Quantization code type (1B).
Definition quantizer.h:33
DataType input_type
Original input type (1B).
Definition quantizer.h:32
Dimension-aware (tiled separable) Lorenzo predictor — cuSZp3 delta. Lossless.
Element-wise zigzag encode/decode stage (TIn[] ↔ TOut[]).