None of this has been built on a Mac - there is none yet. It is the list a read-only audit of the
viewer/rugnux subtree produced, plus a serial -fsyntax-only pass of every reachable .cpp with
clang 16 + libc++ on Linux, which found exactly one error (the first item).
- JFJochDatasetInfoChartView: std::vector<fftwf_complex> does not compile with libc++, whose
construct_at refuses an array element type (float[2]). Use std::vector<std::complex<float>> and
the reinterpret_cast every other FFTW call site already uses.
- libcurl: GSSAPI off on Linux, and neither TLS nor GSSAPI on macOS. The viewer never sets
CURLOPT_HTTPAUTH, so Negotiate was dead weight that cost a krb5-devel build dependency; on macOS
curl's FindGSS refuses the system Heimdal outright, and with Secure Transport gone from curl
(8.15) TLS would mean a Homebrew OpenSSL - the only host library a Mac build would need.
Linux keeps OpenSSL. CURL_USE_GSSAPI is forced OFF rather than left unset so an existing build
tree drops its cached ON.
- libjpeg-turbo ExternalProject: CMAKE_SYSTEM_NAME/PROCESSOR were forwarded unconditionally, which
puts even a native sub-build into cross-compiling mode, and CMAKE_OSX_ARCHITECTURES / SYSROOT /
DEPLOYMENT_TARGET were not forwarded at all. Now the same rule the zlib-ng sub-build follows.
- ShadowAccumulatorGPU.cu was added on the JFJOCH_USE_CUDA option (default ON) instead of
JFJOCH_CUDA_AVAILABLE like every other .cu, so a machine without nvcc got a CUDA source in a
target with no CUDA language.
- CMAKE_OSX_DEPLOYMENT_TARGET defaults to 12.0 (overridable). Left unset, CMake takes the build
machine's OS version and the .dmg starts nowhere older.
- Standard headers that were only arriving transitively (<chrono>, <cmath>, <limits>, <cstring>,
<atomic>, <thread>, <string>); newer libc++ releases keep removing such transitive includes.
Checked: the seven changed sources pass clang 16 + libc++ -fsyntax-only. The CMake changes are
not configured or built.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015eAE2K7i5JGDwgwifiCfuA
(cherry picked from commit 5a7282759a)
198 lines
7.4 KiB
C++
198 lines
7.4 KiB
C++
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include "JFJochZstdCompressor.h"
|
|
|
|
#include <cstring>
|
|
#include <map>
|
|
#include <zstd.h>
|
|
#include <lz4/lz4.h>
|
|
|
|
#include <common/mem.h>
|
|
#include <stdexcept>
|
|
|
|
enum class CompressorState {RLE_0, RLE_FF, RAW};
|
|
|
|
#define BLOCK_RAW 0
|
|
#define BLOCK_RLE 1
|
|
#define BLOCK_COMP 2
|
|
#define LITERAL_COMPRESSED 2
|
|
#define LITERAL_TREELESS 3
|
|
|
|
JFJochZstdCompressor::JFJochZstdCompressor() {
|
|
unsigned count[256];
|
|
for (int i = 0; i < 256; i++) count[i] = i;
|
|
}
|
|
|
|
size_t JFJochZstdCompressor::RawBlock(uint8_t *dst, const void *src, uint32_t src_size, bool last) {
|
|
size_t ret_value = 0;
|
|
int32_t bytes_left = src_size;
|
|
auto src_u8 = (uint8_t *)src;
|
|
|
|
while (bytes_left > 0) {
|
|
int32_t bytes_to_write = std::min(bytes_left,ZSTD_BLOCKSIZE_MAX);
|
|
bytes_left -= bytes_to_write;
|
|
uint32_t block_header = (bytes_to_write << 3) + (BLOCK_RAW<<1) + (((last && (bytes_left == 0)) ? 1 : 0));
|
|
|
|
MEM_writeLE24(dst, block_header);
|
|
memcpy(dst + 3, src_u8, bytes_to_write);
|
|
|
|
src_u8 += bytes_to_write;
|
|
ret_value += 3 + bytes_to_write;
|
|
dst += 3 + bytes_to_write;
|
|
}
|
|
return ret_value;
|
|
}
|
|
|
|
size_t JFJochZstdCompressor::RLEBlock(uint8_t *dst, uint8_t src, uint32_t src_size, bool last) {
|
|
size_t ret_value = 0;
|
|
int32_t bytes_left = src_size;
|
|
|
|
while (bytes_left > 0) {
|
|
int32_t bytes_to_write = std::min(bytes_left, ZSTD_BLOCKSIZE_MAX);
|
|
bytes_left -= bytes_to_write;
|
|
uint32_t block_header = (bytes_to_write << 3) + (BLOCK_RLE<<1) + ((last && (bytes_left == 0))? 1 : 0);
|
|
uint32_t block = block_header + (src<<24); // Little Endian!
|
|
MEM_writeLE32(dst + ret_value, block);
|
|
ret_value += 4;
|
|
}
|
|
return ret_value;
|
|
}
|
|
|
|
size_t JFJochZstdCompressor::DataBlock(uint8_t *dst, const void *src, uint32_t src_size, bool last) {
|
|
return RawBlock(dst, src, src_size, last);
|
|
}
|
|
|
|
size_t JFJochZstdCompressor::BlockStateMachine(uint8_t *dst, const uint64_t *src, size_t frame_size64) {
|
|
size_t dst_size = 0;
|
|
|
|
CompressorState state;
|
|
size_t seq_len = 8;
|
|
|
|
if (src[0] == 0x0) state = CompressorState::RLE_0;
|
|
else if (src[0] == UINT64_MAX) state = CompressorState::RLE_FF;
|
|
else state = CompressorState::RAW;
|
|
|
|
for (int i = 1; i < frame_size64; i++) {
|
|
switch (state) {
|
|
case CompressorState::RLE_0:
|
|
if (src[i] == 0x0) seq_len += 8;
|
|
else if ((src[i] & 0x00000000000000FF) != 0) {
|
|
dst_size += RLEBlock(dst + dst_size, 0x0, seq_len, false);
|
|
state = CompressorState::RAW;
|
|
seq_len = 8;
|
|
} else if (src[i] == UINT64_MAX) {
|
|
dst_size += RLEBlock(dst + dst_size, 0x0, seq_len, false);
|
|
state = CompressorState::RLE_FF;
|
|
seq_len = 8;
|
|
} else {
|
|
int delta1 = 1;
|
|
if ((src[i] & 0x00FFFFFFFFFFFFFF) == 0) delta1 = 7;
|
|
else if ((src[i] & 0x0000FFFFFFFFFFFF) == 0) delta1 = 6;
|
|
else if ((src[i] & 0x000000FFFFFFFFFF) == 0) delta1 = 5;
|
|
else if ((src[i] & 0x00000000FFFFFFFF) == 0) delta1 = 4;
|
|
else if ((src[i] & 0x0000000000FFFFFF) == 0) delta1 = 3;
|
|
else if ((src[i] & 0x000000000000FFFF) == 0) delta1 = 2;
|
|
|
|
dst_size += RLEBlock(dst + dst_size, 0x0, seq_len + delta1, false);
|
|
state = CompressorState::RAW;
|
|
seq_len = 8 - delta1;
|
|
}
|
|
break;
|
|
case CompressorState::RLE_FF:
|
|
if (src[i] == UINT64_MAX) seq_len += 8;
|
|
else {
|
|
dst_size += RLEBlock(dst + dst_size, 0xFFu, seq_len, false);
|
|
seq_len = 8;
|
|
if (src[i] == 0x0u)
|
|
state = CompressorState::RLE_0;
|
|
else
|
|
state = CompressorState::RAW;
|
|
}
|
|
break;
|
|
case CompressorState::RAW:
|
|
if (src[i] == 0x0u) {
|
|
dst_size += DataBlock(dst + dst_size, (uint8_t *) (src + i) - seq_len,
|
|
seq_len, false);
|
|
state = CompressorState::RLE_0;
|
|
seq_len = 8;
|
|
} else if ((i < frame_size64 - 1) && (src[i+1] == 0x0u) && ((src[i] & 0xFF00000000000000) == 0)) {
|
|
int delta2 = 1;
|
|
if ((src[i] & 0xFFFFFFFFFFFFFF00) == 0) delta2 = 7;
|
|
else if ((src[i] & 0xFFFFFFFFFFFF0000) == 0) delta2 = 6;
|
|
else if ((src[i] & 0xFFFFFFFFFF000000) == 0) delta2 = 5;
|
|
else if ((src[i] & 0xFFFFFFFF00000000) == 0) delta2 = 4;
|
|
else if ((src[i] & 0xFFFFFF0000000000) == 0) delta2 = 3;
|
|
else if ((src[i] & 0xFFFF000000000000) == 0) delta2 = 2;
|
|
dst_size += DataBlock(dst + dst_size, (uint8_t *) (src + i) - seq_len,
|
|
seq_len + 8 - delta2, false);
|
|
state = CompressorState::RLE_0;
|
|
seq_len = delta2;
|
|
} else if (src[i] == UINT64_MAX) {
|
|
dst_size += DataBlock(dst + dst_size, (uint8_t *) (src + i) - seq_len,
|
|
seq_len, false);
|
|
state = CompressorState::RLE_FF;
|
|
seq_len = 8;
|
|
} else seq_len += 8;
|
|
break;
|
|
|
|
}
|
|
}
|
|
if (state == CompressorState::RLE_0)
|
|
dst_size += RLEBlock(dst + dst_size, 0x0 , seq_len, true);
|
|
else if (state == CompressorState::RLE_FF)
|
|
dst_size += RLEBlock(dst + dst_size, 0xFFu, seq_len, true);
|
|
else
|
|
dst_size += DataBlock(dst + dst_size, (uint8_t *) (src + frame_size64) - seq_len, seq_len, true);
|
|
|
|
return dst_size;
|
|
}
|
|
|
|
size_t JFJochZstdCompressor::CompressFrame(uint8_t *dst, const uint64_t *src, size_t frame_size64) {
|
|
//if (frame_size64 > 1000 * 1000)
|
|
// throw SLSException(SLSExceptionCategory::ZSTDCompressionError,
|
|
// "ZSTD frame cannot be larger than 8 MB");
|
|
|
|
// Assumptions:
|
|
// One frame = One module = 512*1024*2 (2^20 == 1048576) - 514*1030*4 (2117680 < 2 ^22)
|
|
// --> frame size needs 32-bit
|
|
|
|
size_t dst_size = 0;
|
|
|
|
// Magic number
|
|
MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
|
|
|
|
dst_size += 4;
|
|
|
|
// Frame header descriptor
|
|
uint8_t frame_header_descriptor = (1<<7) + (1<<5);
|
|
dst[dst_size] = frame_header_descriptor;
|
|
dst_size += 1;
|
|
|
|
// Frame size
|
|
MEM_writeLE32(dst + dst_size, frame_size64*8);
|
|
dst_size += 4;
|
|
|
|
dst_size += BlockStateMachine(dst + dst_size, src, frame_size64);
|
|
|
|
return dst_size;
|
|
}
|
|
|
|
size_t JFJochZstdCompressor::Compress(uint8_t *dst, const uint64_t *src, size_t src_size, size_t frame_size) {
|
|
size_t dst_size = 0;
|
|
|
|
if (frame_size % 8 != 0)
|
|
throw std::runtime_error("ZSTD frame has to have size multiple of 8");
|
|
|
|
if (src_size % frame_size != 0)
|
|
throw std::runtime_error("ZSTD source has to be multiple of frame");
|
|
|
|
size_t nframes = src_size / frame_size;
|
|
|
|
size_t frame_size64 = frame_size / 8;
|
|
|
|
for (int frame = 0; frame < nframes; frame++)
|
|
dst_size += CompressFrame(dst + dst_size, src + frame * frame_size64, frame_size64);
|
|
|
|
return dst_size;
|
|
} |